From 62d6b5b30bd5a3a020e600622b2bb2b3d0664593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20H=C3=BCttemann?= Date: Wed, 24 May 2023 18:01:08 +0200 Subject: [PATCH] Implement user registration functions --- docker-compose.yml | 4 ++-- src/app.ts | 8 +++---- src/users.ts | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 00040b0..2ae3980 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,7 +6,7 @@ services: image: docker.io/matrixdotorg/synapse:latest # Since synapse does not retry to connect to the database, restart upon # failure - restart: unless-stopped + restart: "no" # See the readme for a full documentation of the environment settings # NOTE: You must edit homeserver.yaml to use postgres, it defaults to sqlite environment: @@ -46,4 +46,4 @@ services: image: awesometechnologies/synapse-admin:latest ports: - "8080:80" - restart: unless-stopped + restart: "no" diff --git a/src/app.ts b/src/app.ts index 4115131..2d88190 100644 --- a/src/app.ts +++ b/src/app.ts @@ -35,17 +35,17 @@ function loadRcExport(entity: Entities): Promise { } let userMapping = storage.users.find((e) => e.rcId === rcUser._id) // Lookup mapping - if (userMapping) { + if (userMapping && userMapping.matrixId) { log.debug('Mapping exists:', userMapping) } else { userMapping = { rcId: rcUser._id, - matrixId: `@${rcUser.username}:localhost`, + matrixId: `@${rcUser.username}:localhost`, // Create user on synapse } storage.users.push(userMapping) // Save new mapping log.debug('Mapping added:', userMapping) - // Add user to room mapping + // Add user to room mapping (specific to users) rcUser.__rooms.forEach((rcRoomId: string) => { const roomIndex = storage.rooms.findIndex( (e) => e.rcId === rcRoomId @@ -91,7 +91,7 @@ async function main() { await loadRcExport(Entities.Users) log.info('Done.') } catch (error) { - log.error(`Encountered an error booting up`) + log.error(`Encountered an error while booting up`) } } diff --git a/src/users.ts b/src/users.ts index 9da11f8..e85a5ce 100644 --- a/src/users.ts +++ b/src/users.ts @@ -1,3 +1,6 @@ +import { axios } from './synapse' +import { createHmac } from 'node:crypto' + export type RcUser = { username: string name: string @@ -5,3 +8,54 @@ export type RcUser = { _id: string __rooms: string[] } + +export type MatrixUser = { + user_id?: string + nonce?: string + username: string + displayname: string + password?: string + admin: boolean + mac?: string +} + +export function mapUser(rcUser: RcUser): MatrixUser { + return { + user_id: '', + username: rcUser.username, + displayname: rcUser.name, + password: '', + admin: rcUser.roles.includes('admin'), + } +} + +const registration_shared_secret = + 'vkq7zfBDt4A1NmMN6jJ*g+,G~.R:QuC_xI:~7~jQ_6kJ6O~JrG' + +function generateHmac(user: MatrixUser): string { + const hmac = createHmac('sha1', registration_shared_secret) + hmac.write( + `${user.nonce}\0${user.username}\0${user.password}\0${ + user.admin ? 'admin' : 'notadmin' + }` + ) + hmac.end() + return hmac.read().toString('hex') +} + +async function getUserRegistrationNonce(): Promise { + return (await axios.get('/_synapse/admin/v1/register')).data.nonce +} + +async function registerUser(user: MatrixUser): Promise { + return (await axios.post('/_synapse/admin/v1/register', user)).data.user_id +} + +export async function createUser(rcUser: RcUser): Promise { + const user = mapUser(rcUser) + user.nonce = await getUserRegistrationNonce() + user.mac = generateHmac(user) + user.user_id = await registerUser(user) + + return user +}