From c4d5bc03781b53a6af8574cd2073e819e5298275 Mon Sep 17 00:00:00 2001 From: Mathixx <147631380+Mathixx@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:14:32 +0400 Subject: [PATCH 1/9] fix: invite link idea --- .../src/invitation/index.ts | 10 ++++++++++ .../templates/3pidInvitation.tpl | 19 +++---------------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/packages/matrix-identity-server/src/invitation/index.ts b/packages/matrix-identity-server/src/invitation/index.ts index bb7d7a65..115af195 100644 --- a/packages/matrix-identity-server/src/invitation/index.ts +++ b/packages/matrix-identity-server/src/invitation/index.ts @@ -55,6 +55,14 @@ const preConfigureTemplate = ( ) } +const inviteLink = ( + method: 'matrix' | 'twake', + address: string, + name: string +): string => { + return `https://${medium}/${address}/${name}` +} + const mailBody = ( template: string, // eslint-disable-next-line @typescript-eslint/naming-convention @@ -81,6 +89,7 @@ const mailBody = ( .replace(/__room_name__/g, room_name ?? '') .replace(/__room_avatar__/g, room_avatar ?? '') .replace(/__room_type__/g, room_type ?? '') + .replace(/__link__/g, inviteLink('matrix', dst, room_name)) ) } @@ -134,6 +143,7 @@ const StoreInvit = ( return (req, res) => { idServer.authenticate(req, res, (_data, _id) => { jsonContent(req, res, idServer.logger, (obj) => { + // eslint-disable-next-line @typescript-eslint/no-misused-promises validateParameters(res, schema, obj, idServer.logger, async (obj) => { const _address = (obj as storeInvitationArgs).address const _medium = (obj as storeInvitationArgs).medium diff --git a/packages/matrix-identity-server/templates/3pidInvitation.tpl b/packages/matrix-identity-server/templates/3pidInvitation.tpl index 8f90a442..3903b0cb 100644 --- a/packages/matrix-identity-server/templates/3pidInvitation.tpl +++ b/packages/matrix-identity-server/templates/3pidInvitation.tpl @@ -12,8 +12,8 @@ Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Hello, -You have been invited to join a Matrix room by __inviter_name__. If you possess a Matrix account, please consider binding this email address to your account in order to accept the invitation. - +You have been invited to join a Matrix room by __inviter_name__. +Please click on the following link to accept the invitation: __link__ About Matrix: Matrix is an open standard for interoperable, decentralised, real-time communication over IP. It can be used to power Instant Messaging, VoIP/WebRTC signalling, Internet of Things communication - or anywhere you need a standard HTTP API for publishing and subscribing to data whilst tracking the conversation history. @@ -40,20 +40,8 @@ body {

Hello,

-

You have been invited to join a Matrix room by __inviter_name__. If you possess a Matrix account, please consider binding this email address to your account in order to accept the invitation.

- -

If your client requires a code, the code is __token__

+

You have been invited to join a Matrix room by __inviter_name__. Please click on the following link to accept the invitation: __link__

-
-

Invitation Details:

- - -

About Matrix:

Matrix is an open standard for interoperable, decentralised, real-time communication over IP. It can be used to power Instant Messaging, VoIP/WebRTC signalling, Internet of Things communication - or anywhere you need a standard HTTP API for publishing and subscribing to data whilst tracking the conversation history.

@@ -64,4 +52,3 @@ body { --__multipart_boundary__-- - From 1568a24747bb813879002470c406d66a76c62521 Mon Sep 17 00:00:00 2001 From: h1pp0X Date: Wed, 10 Jul 2024 15:51:47 +0400 Subject: [PATCH 2/9] feat : added invitationTokens table + an index on address (and reordered in alphabetic order) --- .../matrix-identity-server/src/db/index.ts | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/matrix-identity-server/src/db/index.ts b/packages/matrix-identity-server/src/db/index.ts index 14c34478..64c9ebf1 100644 --- a/packages/matrix-identity-server/src/db/index.ts +++ b/packages/matrix-identity-server/src/db/index.ts @@ -10,48 +10,51 @@ export type SupportedDatabases = 'sqlite' | 'pg' export type Collections = | 'accessTokens' - | 'oneTimeTokens' + | 'activeContacts' | 'attempts' - | 'keys' + | 'oneTimeTokens' | 'hashes' + | 'invitationTokens' + | 'keys' + | 'longTermKeypairs' + | 'mappings' | 'privateNotes' | 'roomTags' - | 'userHistory' - | 'userQuotas' - | 'mappings' - | 'longTermKeypairs' | 'shortTermKeypairs' + | 'userHistory' | 'userPolicies' - | 'activeContacts' + | 'userQuotas' const cleanByExpires: Collections[] = ['oneTimeTokens', 'attempts'] const tables: Record = { accessTokens: 'id varchar(64) PRIMARY KEY, data text', - oneTimeTokens: 'id varchar(64) PRIMARY KEY, expires int, data text', + activeContacts: 'userId text PRIMARY KEY, contacts text', attempts: 'email text PRIMARY KEY, expires int, attempt int', - keys: 'name varchar(32) PRIMARY KEY, data text', + oneTimeTokens: 'id varchar(64) PRIMARY KEY, expires int, data text', hashes: 'hash varchar(48) PRIMARY KEY, pepper varchar(32), type varchar(8), value text, active integer', + invitationTokens: 'id varchar(64) PRIMARY KEY, data text, address text', + keys: 'name varchar(32) PRIMARY KEY, data text', + longTermKeypairs: + 'name text PRIMARY KEY, keyID varchar(64), public text, private text', + mappings: + 'client_secret varchar(255) PRIMARY KEY, session_id varchar(12), medium varchar(8), valid integer, address text, submit_time integer, send_attempt integer', privateNotes: 'id varchar(64) PRIMARY KEY, authorId varchar(64), content text, targetId varchar(64)', roomTags: 'id varchar(64) PRIMARY KEY, authorId varchar(64), content text, roomId varchar(64)', - userHistory: 'address text PRIMARY KEY, active integer, timestamp integer', - userQuotas: 'user_id varchar(64) PRIMARY KEY, size int', - mappings: - 'client_secret varchar(255) PRIMARY KEY, session_id varchar(12), medium varchar(8), valid integer, address text, submit_time integer, send_attempt integer', - longTermKeypairs: - 'name text PRIMARY KEY, keyID varchar(64), public text, private text', shortTermKeypairs: 'keyID varchar(64) PRIMARY KEY, public text, private text, active integer', + userHistory: 'address text PRIMARY KEY, active integer, timestamp integer', userPolicies: 'user_id text, policy_name text, accepted integer', - activeContacts: 'userId text PRIMARY KEY, contacts text' + userQuotas: 'user_id varchar(64) PRIMARY KEY, size int' } const indexes: Partial> = { - oneTimeTokens: ['expires'], attempts: ['expires'], + invitationTokens: ['address'], + oneTimeTokens: ['expires'], userHistory: ['timestamp'] } From 2f32a239237858e094ea730e6731d66f7a5c8391 Mon Sep 17 00:00:00 2001 From: h1pp0X Date: Wed, 10 Jul 2024 16:45:19 +0400 Subject: [PATCH 3/9] feat : added new management of pending invitations - created invitationTokens --- .../src/db/index.test.ts | 25 +++++++ .../matrix-identity-server/src/db/index.ts | 49 ++++++++++++- .../src/ephemeral_signing/index.ts | 46 ++++++------ .../src/invitation/index.ts | 72 +++++++++++-------- 4 files changed, 134 insertions(+), 58 deletions(-) diff --git a/packages/matrix-identity-server/src/db/index.test.ts b/packages/matrix-identity-server/src/db/index.test.ts index 7e844dae..e3654deb 100644 --- a/packages/matrix-identity-server/src/db/index.test.ts +++ b/packages/matrix-identity-server/src/db/index.test.ts @@ -92,6 +92,31 @@ describe('Id Server DB', () => { .catch(done) }) + it('should provide verification-token', (done) => { + idDb = new IdDb(baseConf, logger) + idDb.ready + .then(() => { + idDb + .createInvitationToken('randomMailorPhone', { a: 1 }) + .then((token) => { + expect(token).toMatch(/^[a-zA-Z0-9]+$/) + idDb + .verifyInvitationToken(token) + .then((data) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error + // @ts-ignore + expect(data.a).toEqual(1) + clearTimeout(idDb.cleanJob) + idDb.close() + done() + }) + .catch((e) => done(e)) + }) + .catch((e) => done(e)) + }) + .catch((e) => done(e)) + }) + it('should provide match()', (done) => { idDb = new IdDb(baseConf, logger) idDb.ready diff --git a/packages/matrix-identity-server/src/db/index.ts b/packages/matrix-identity-server/src/db/index.ts index 64c9ebf1..3576f873 100644 --- a/packages/matrix-identity-server/src/db/index.ts +++ b/packages/matrix-identity-server/src/db/index.ts @@ -34,7 +34,7 @@ const tables: Record = { oneTimeTokens: 'id varchar(64) PRIMARY KEY, expires int, data text', hashes: 'hash varchar(48) PRIMARY KEY, pepper varchar(32), type varchar(8), value text, active integer', - invitationTokens: 'id varchar(64) PRIMARY KEY, data text, address text', + invitationTokens: 'id varchar(64) PRIMARY KEY, address text, data text', keys: 'name varchar(32) PRIMARY KEY, data text', longTermKeypairs: 'name text PRIMARY KEY, keyID varchar(64), public text, private text', @@ -566,6 +566,53 @@ class IdentityServerDb return this.createOneTimeToken(data, expires) } + // eslint-disable-next-line @typescript-eslint/promise-function-async + createInvitationToken(address: string, data: object): Promise { + /* istanbul ignore if */ + if (this.db == null) { + throw new Error('Wait for database to be ready') + } + const id = randomString(64) + return new Promise((resolve, reject) => { + this.db + .insert('invitationTokens', { + id, + address, + data: JSON.stringify(data) + }) + .then(() => { + resolve(id) + }) + .catch((err) => { + /* istanbul ignore next */ + this.logger.error('Failed to insert token', err) + }) + }) + } + + // eslint-disable-next-line @typescript-eslint/promise-function-async + verifyInvitationToken(id: string): Promise { + /* istanbul ignore if */ + if (this.db == null) { + throw new Error('Wait for database to be ready') + } + return new Promise((resolve, reject) => { + this.db + .get('invitationTokens', ['data', 'address'], { id }) + .then((rows) => { + /* istanbul ignore else */ + if (rows.length > 0) { + resolve(JSON.parse(rows[0].data as string)) + } else { + reject(new Error('Unknown token')) + } + }) + .catch((e) => { + reject(e) + }) + }) + } + // eslint-disable-next-line @typescript-eslint/promise-function-async verifyToken(id: string): Promise { /* istanbul ignore if */ diff --git a/packages/matrix-identity-server/src/ephemeral_signing/index.ts b/packages/matrix-identity-server/src/ephemeral_signing/index.ts index c0d600e9..b1624797 100644 --- a/packages/matrix-identity-server/src/ephemeral_signing/index.ts +++ b/packages/matrix-identity-server/src/ephemeral_signing/index.ts @@ -41,37 +41,31 @@ const SignEd25519 = ( send(res, 400, errMsg('invalidParam', 'invalid Matrix user ID')) } else { idServer.db - .get('oneTimeTokens', ['data'], { id: token }) - .then((rows) => { - if (rows.length === 0) { - send(res, 404, errMsg('invalidParam', 'token not found')) - } else { - const parsedData = JSON.parse(rows[0].data as string) - const sender = parsedData.sender - const newToken = randomString(64) - const identifier = nacl.randomBytes(8) - let identifierHex = naclUtil.encodeBase64(identifier) - identifierHex = toBase64Url(identifierHex) - send( - res, - 200, - signJson( - { mxid, sender, token: newToken }, - privateKey, - idServer.conf.server_name, - `ed25519:${identifierHex}` - ) + .verifyInvitationToken(token) + .then((data) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error + // @ts-ignore + const sender = data.sender as string + const newToken = randomString(64) + const identifier = nacl.randomBytes(8) + let identifierHex = naclUtil.encodeBase64(identifier) + identifierHex = toBase64Url(identifierHex) + send( + res, + 200, + signJson( + { mxid, sender, token: newToken }, + privateKey, + idServer.conf.server_name, + `ed25519:${identifierHex}` ) - } + ) }) .catch((err) => { /* istanbul ignore next */ - idServer.logger.error( - 'Error while fetching one-time token', - err - ) + idServer.logger.error('Token denied', err) /* istanbul ignore next */ - send(res, 400, errMsg('unknown', err)) + send(res, 404, errMsg('notFound', err)) }) } }) diff --git a/packages/matrix-identity-server/src/invitation/index.ts b/packages/matrix-identity-server/src/invitation/index.ts index 115af195..38da5015 100644 --- a/packages/matrix-identity-server/src/invitation/index.ts +++ b/packages/matrix-identity-server/src/invitation/index.ts @@ -55,12 +55,13 @@ const preConfigureTemplate = ( ) } +// TODO : don't forget to modify this : cf matrix.to or other method const inviteLink = ( - method: 'matrix' | 'twake', + method: 'matrix.org' | 'twake.org', address: string, name: string ): string => { - return `https://${medium}/${address}/${name}` + return `https://${method}/${address}/${name}` } const mailBody = ( @@ -86,15 +87,13 @@ const mailBody = ( .replace(/__date__/g, new Date().toUTCString()) // initialize message id .replace(/__messageid__/g, randomString(32)) - .replace(/__room_name__/g, room_name ?? '') - .replace(/__room_avatar__/g, room_avatar ?? '') - .replace(/__room_type__/g, room_type ?? '') - .replace(/__link__/g, inviteLink('matrix', dst, room_name)) + .replace(/__room_name__/g, room_name) + .replace(/__room_avatar__/g, room_avatar) + .replace(/__room_type__/g, room_type) + .replace(/__link__/g, inviteLink('matrix.org', dst, room_name)) ) } -const invitationDelay = 3155760000 // 100 years in seconds - // To complete if another 3PID is added for this endpoint const validMediums: string[] = ['email'] @@ -162,6 +161,7 @@ const StoreInvit = ( send(res, 400, errMsg('invalidEmail')) return } + // TODO : add phone number validation } // Call to the lookup API to check for any existing third-party identifiers try { @@ -203,23 +203,29 @@ const StoreInvit = ( ...(obj as storeInvitationArgs), key: ephemeralKey } - const _token = await idServer.db.createToken( - objWithKey, - invitationDelay + const _token = await idServer.db.createInvitationToken( + _address, + objWithKey ) - // send email - void transport.sendMail({ - to: _address, - raw: mailBody( - verificationTemplate, - (obj as storeInvitationArgs).sender_display_name ?? '*****', - _address, - (obj as storeInvitationArgs).room_name ?? '*****', - (obj as storeInvitationArgs).room_avatar_url ?? '*****', - (obj as storeInvitationArgs).room_type ?? '*****' - ) - }) - // send 200 response + // Send email/sms + switch (_medium) { + case 'email': + void transport.sendMail({ + to: _address, + raw: mailBody( + verificationTemplate, + (obj as storeInvitationArgs).sender_display_name ?? + '*****', + _address, + (obj as storeInvitationArgs).room_name ?? '*****', + (obj as storeInvitationArgs).room_avatar_url ?? '*****', + (obj as storeInvitationArgs).room_type ?? '*****' + ) + }) + break + // TODO : add sms sending + } + // Send 200 response const redactedAddress = redactAddress(_address) idServer.db .getKeys('current') @@ -240,16 +246,20 @@ const StoreInvit = ( } send(res, 200, responseBody) }) - .catch((e) => { + .catch((err) => { /* istanbul ignore next */ idServer.logger.debug( 'Error while getting the current key', - e + err ) /* istanbul ignore next */ - throw e + send(res, 500, errMsg('unknown', err)) }) } else { + /* istanbul ignore next */ + idServer.logger.error( + 'Unexpected response statusCode from the /_matrix/identity/v2/lookup API' + ) send( res, 500, @@ -259,14 +269,14 @@ const StoreInvit = ( ) ) } - } catch (e) { + } catch (err) { /* istanbul ignore next */ - idServer.logger.debug( + idServer.logger.error( 'Error while making a call to the lookup API (/_matrix/identity/v2/lookup)', - e + err ) /* istanbul ignore next */ - throw e + send(res, 500, errMsg('unknown', err as string)) } }) }) From 1e9047e4dbde82e6ddd5f24dc03d60550fbeeb97 Mon Sep 17 00:00:00 2001 From: h1pp0X Date: Thu, 11 Jul 2024 10:02:39 +0400 Subject: [PATCH 4/9] fix : added TODO concerning call to the onbind api --- packages/matrix-identity-server/src/3pid/bind.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/matrix-identity-server/src/3pid/bind.ts b/packages/matrix-identity-server/src/3pid/bind.ts index 11062501..f2651e3f 100644 --- a/packages/matrix-identity-server/src/3pid/bind.ts +++ b/packages/matrix-identity-server/src/3pid/bind.ts @@ -77,6 +77,9 @@ const bind = ( }) return } + + // TODO : hook for any pending invite and call the onbind api : https://spec.matrix.org/v1.11/client-server-api/#room-aliases + idServer.db .get('keys', ['data'], { name: 'pepper' }) .then(async (pepperRow) => { From 8a0dda1420ce10b60694d8aaab186a4a3e2e75f7 Mon Sep 17 00:00:00 2001 From: Mathixx <147631380+Mathixx@users.noreply.github.com> Date: Thu, 11 Jul 2024 10:34:41 +0400 Subject: [PATCH 5/9] fix: added link to invite message --- .../src/invitation/index.ts | 23 +++++++++++++------ .../templates/3pidInvitation.tpl | 4 ++-- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/matrix-identity-server/src/invitation/index.ts b/packages/matrix-identity-server/src/invitation/index.ts index 38da5015..3bfa93c9 100644 --- a/packages/matrix-identity-server/src/invitation/index.ts +++ b/packages/matrix-identity-server/src/invitation/index.ts @@ -57,11 +57,15 @@ const preConfigureTemplate = ( // TODO : don't forget to modify this : cf matrix.to or other method const inviteLink = ( - method: 'matrix.org' | 'twake.org', - address: string, - name: string + server: string, + senderId: string, + roomAlias?: string ): string => { - return `https://${method}/${address}/${name}` + if (roomAlias != null) { + return `https://${server}/#/${roomAlias}` + } else { + return `https://${server}/#/${senderId}` + } } const mailBody = ( @@ -69,13 +73,16 @@ const mailBody = ( // eslint-disable-next-line @typescript-eslint/naming-convention inviter_name: string, // eslint-disable-next-line @typescript-eslint/naming-convention + sender_user_id: string, dst: string, // eslint-disable-next-line @typescript-eslint/naming-convention room_name: string, // eslint-disable-next-line @typescript-eslint/naming-convention room_avatar: string, // eslint-disable-next-line @typescript-eslint/naming-convention - room_type: string + room_type: string, + // eslint-disable-next-line @typescript-eslint/naming-convention + room_alias?: string ): string => { return ( template @@ -90,7 +97,7 @@ const mailBody = ( .replace(/__room_name__/g, room_name) .replace(/__room_avatar__/g, room_avatar) .replace(/__room_type__/g, room_type) - .replace(/__link__/g, inviteLink('matrix.org', dst, room_name)) + .replace(/__link__/g, inviteLink('matrix.to', sender_user_id, room_alias)) ) } @@ -216,10 +223,12 @@ const StoreInvit = ( verificationTemplate, (obj as storeInvitationArgs).sender_display_name ?? '*****', + (obj as storeInvitationArgs).sender, _address, (obj as storeInvitationArgs).room_name ?? '*****', (obj as storeInvitationArgs).room_avatar_url ?? '*****', - (obj as storeInvitationArgs).room_type ?? '*****' + (obj as storeInvitationArgs).room_type ?? '*****', + (obj as storeInvitationArgs).room_alias ) }) break diff --git a/packages/matrix-identity-server/templates/3pidInvitation.tpl b/packages/matrix-identity-server/templates/3pidInvitation.tpl index 3903b0cb..55725e2d 100644 --- a/packages/matrix-identity-server/templates/3pidInvitation.tpl +++ b/packages/matrix-identity-server/templates/3pidInvitation.tpl @@ -12,7 +12,7 @@ Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Hello, -You have been invited to join a Matrix room by __inviter_name__. +You have been invited to join the __room_name__ Matrix room by __inviter_name__. Please click on the following link to accept the invitation: __link__ About Matrix: @@ -40,7 +40,7 @@ body {

Hello,

-

You have been invited to join a Matrix room by __inviter_name__. Please click on the following link to accept the invitation: __link__

+

You have been invited to join the __room_name__ Matrix room by __inviter_name__. Please click on the following link to accept the invitation: __link__

About Matrix:

From 0724eb7c314dce479e930d296cd8d0ac408752a1 Mon Sep 17 00:00:00 2001 From: h1pp0X Date: Fri, 12 Jul 2024 15:05:00 +0400 Subject: [PATCH 6/9] feat : added msisdn in the suppported media for store-invite --- .../matrix-identity-server/src/index.test.ts | 104 +++++++++++++----- .../src/invitation/index.ts | 84 +++++++++----- 2 files changed, 133 insertions(+), 55 deletions(-) diff --git a/packages/matrix-identity-server/src/index.test.ts b/packages/matrix-identity-server/src/index.test.ts index edbbec65..64ee5e88 100644 --- a/packages/matrix-identity-server/src/index.test.ts +++ b/packages/matrix-identity-server/src/index.test.ts @@ -759,7 +759,7 @@ describe('Use configuration file', () => { describe('/_matrix/identity/v2/3pid/bind', () => { it('should find the 3pid - matrixID association after binding', async () => { - const response_request_token = await request(app) + const responseRequestToken = await request(app) .post('/_matrix/identity/v2/validate/email/requestToken') .set('Authorization', `Bearer ${validToken}`) .set('Accept', 'application/json') @@ -769,22 +769,22 @@ describe('Use configuration file', () => { next_link: 'http://localhost:8090', send_attempt: 1 }) - expect(response_request_token.statusCode).toBe(200) + expect(responseRequestToken.statusCode).toBe(200) expect(sendMailMock.mock.calls[0][0].to).toBe('ab@abc.fr') expect(sendMailMock.mock.calls[0][0].raw).toMatch( /token=([a-zA-Z0-9]{64})&client_secret=mysecret2&sid=([a-zA-Z0-9]{64})/ ) - const bind_token = RegExp.$1 - const bind_sid = RegExp.$2 - const response_submit_token = await request(app) + const bindToken = RegExp.$1 + const bindSid = RegExp.$2 + const responseSubmitToken = await request(app) .post('/_matrix/identity/v2/validate/email/submitToken') .send({ - token: bind_token, + token: bindToken, client_secret: 'mysecret2', - sid: bind_sid + sid: bindSid }) .set('Accept', 'application/json') - expect(response_submit_token.statusCode).toBe(200) + expect(responseSubmitToken.statusCode).toBe(200) const longKeyPair: { publicKey: string privateKey: string @@ -795,17 +795,17 @@ describe('Use configuration file', () => { public: longKeyPair.publicKey, private: longKeyPair.privateKey }) - const response_bind = await request(app) + const responseBind = await request(app) .post('/_matrix/identity/v2/3pid/bind') .set('Authorization', `Bearer ${validToken}`) .set('Accept', 'application/json') .send({ client_secret: 'mysecret2', - sid: bind_sid, + sid: bindSid, mxid: '@ab:abc.fr' }) - expect(response_bind.statusCode).toBe(200) - expect(response_bind.body).toHaveProperty('signatures') + expect(responseBind.statusCode).toBe(200) + expect(responseBind.body).toHaveProperty('signatures') await idServer.cronTasks?.ready const response = await request(app) .get('/_matrix/identity/v2/hash_details') @@ -817,7 +817,7 @@ describe('Use configuration file', () => { const hash = new Hash() await hash.ready const computedHash = hash.sha256(`ab@abc.fr mail ${pepper}`) - const response_lookup = await request(app) + const responseLookup = await request(app) .post('/_matrix/identity/v2/lookup') .send({ addresses: [computedHash], @@ -826,8 +826,8 @@ describe('Use configuration file', () => { }) .set('Authorization', `Bearer ${validToken}`) .set('Accept', 'application/json') - expect(response_lookup.statusCode).toBe(200) - expect(response_lookup.body.mappings).toEqual({ + expect(responseLookup.statusCode).toBe(200) + expect(responseLookup.body.mappings).toEqual({ [computedHash]: '@ab:abc.fr' }) }) @@ -962,7 +962,7 @@ describe('Use configuration file', () => { expect(response.statusCode).toBe(400) }) it('should refuse incompatible session_id and client_secret', async () => { - const response_request_token = await request(app) + const responseRequestToken = await request(app) .post('/_matrix/identity/v2/validate/email/requestToken') .set('Authorization', `Bearer ${validToken}`) .set('Accept', 'application/json') @@ -971,15 +971,15 @@ describe('Use configuration file', () => { email: 'unbind@unbind.fr', send_attempt: 1 }) - expect(response_request_token.statusCode).toBe(200) + expect(responseRequestToken.statusCode).toBe(200) expect(sendMailMock).toHaveBeenCalled() expect(sendMailMock.mock.calls[0][0].to).toBe('unbind@unbind.fr') expect(sendMailMock.mock.calls[0][0].raw).toMatch( /token=([a-zA-Z0-9]{64})&client_secret=mysecret4&sid=([a-zA-Z0-9]{64})/ ) token4 = RegExp.$1 - sid4 = response_request_token.body.sid - const response_submit_token = await request(app) + sid4 = responseRequestToken.body.sid + const responseSubmitToken = await request(app) .post('/_matrix/identity/v2/validate/email/submitToken') .send({ token: token4, @@ -987,8 +987,8 @@ describe('Use configuration file', () => { sid: sid4 }) .set('Accept', 'application/json') - expect(response_submit_token.statusCode).toBe(200) - const response_bind = await request(app) + expect(responseSubmitToken.statusCode).toBe(200) + const responseBind = await request(app) .post('/_matrix/identity/v2/3pid/bind') .set('Authorization', `Bearer ${validToken}`) .set('Accept', 'application/json') @@ -997,7 +997,7 @@ describe('Use configuration file', () => { sid: sid4, mxid: '@unbind:unbind.fr' }) - expect(response_bind.statusCode).toBe(200) + expect(responseBind.statusCode).toBe(200) const response = await request(app) .post('/_matrix/identity/v2/3pid/unbind') .set('Authorization', `Bearer ${validToken}`) @@ -1213,7 +1213,21 @@ describe('Use configuration file', () => { sender: '@dwho:matrix.org' }) expect(response.statusCode).toBe(400) - expect(response.body.errcode).toEqual('M_INVALID_EMAIL') + expect(response.body.errcode).toEqual('M_INVALID_PARAM') + }) + it('should reject an invalid phone number', async () => { + const response = await request(app) + .post('/_matrix/identity/v2/store-invite') + .set('Authorization', `Bearer ${validToken}`) + .set('Accept', 'application/json') + .send({ + address: '+1234', + medium: 'msisdn', + room_id: '!room:matrix.org', + sender: '@dwho:matrix.org' + }) + expect(response.statusCode).toBe(400) + expect(response.body.errcode).toEqual('M_INVALID_PARAM') }) it('should alert if the lookup API did not behave as expected', async () => { const mockResponse = Promise.resolve({ @@ -1271,7 +1285,7 @@ describe('Use configuration file', () => { expect(response.statusCode).toBe(400) expect(response.body.errcode).toBe('M_THREEPID_IN_USE') }) - it('should accept a valid request', async () => { + it('should accept a valid email request', async () => { const mockResponse = Promise.resolve({ ok: false, status: 400, @@ -1304,6 +1318,38 @@ describe('Use configuration file', () => { expect(response.body).toHaveProperty('token') expect(response.body.token).toMatch(/^[a-zA-Z0-9]{64}$/) }) + it('should accept a valid phone number request', async () => { + const mockResponse = Promise.resolve({ + ok: false, + status: 400, + json: () => { + return { + errcode: 'M_INVALID_PEPPER', + error: 'Unknown or invalid pepper - has it been rotated?' + } + } + }) + // @ts-expect-error mock is unknown + fetch.mockImplementation(async () => await mockResponse) + await mockResponse + const response = await request(app) + .post('/_matrix/identity/v2/store-invite') + .set('Authorization', `Bearer ${validToken}`) + .set('Accept', 'application/json') + .send({ + address: '+33612345678', + medium: 'msisdn', + room_id: '!room:matrix.org', + sender: '@dwho:matrix.org' + }) + expect(response.statusCode).toBe(200) + // TODO : add call to smsMock when it will be implemented + expect(response.body).toHaveProperty('display_name') + expect(response.body.display_name).not.toBe('+33612345678') + expect(response.body).toHaveProperty('public_keys') + expect(response.body).toHaveProperty('token') + expect(response.body.token).toMatch(/^[a-zA-Z0-9]{64}$/) + }) }) describe('/_matrix/identity/v2/sign-ed25519 ', () => { @@ -1346,7 +1392,7 @@ describe('Use configuration file', () => { // @ts-expect-error mock is unknown fetch.mockImplementation(async () => await mockResponse) await mockResponse - const response_store_invit = await request(app) + const responseStoreInvite = await request(app) .post('/_matrix/identity/v2/store-invite') .set('Authorization', `Bearer ${validToken}`) .set('Accept', 'application/json') @@ -1356,8 +1402,8 @@ describe('Use configuration file', () => { room_id: '!room:matrix.org', sender: '@dwho:matrix.org' }) - expect(response_store_invit.statusCode).toBe(200) - token = response_store_invit.body.token + expect(responseStoreInvite.statusCode).toBe(200) + token = responseStoreInvite.body.token const response = await request(app) .post('/_matrix/identity/v2/sign-ed25519') .set('Authorization', `Bearer ${validToken}`) @@ -1365,7 +1411,7 @@ describe('Use configuration file', () => { .send({ mxid: 'invalid_mxid', private_key: keyPair.privateKey, - token: token + token }) expect(response.statusCode).toBe(400) }) @@ -1401,7 +1447,7 @@ describe('Use configuration file', () => { .send({ mxid: '@test:matrix.org', private_key: keyPair.privateKey, - token: token + token }) expect(response.statusCode).toBe(200) expect(response.body).toHaveProperty('signatures') diff --git a/packages/matrix-identity-server/src/invitation/index.ts b/packages/matrix-identity-server/src/invitation/index.ts index 3bfa93c9..7df665b6 100644 --- a/packages/matrix-identity-server/src/invitation/index.ts +++ b/packages/matrix-identity-server/src/invitation/index.ts @@ -55,7 +55,7 @@ const preConfigureTemplate = ( ) } -// TODO : don't forget to modify this : cf matrix.to or other method +// TODO : modify this if necessary const inviteLink = ( server: string, senderId: string, @@ -102,39 +102,63 @@ const mailBody = ( } // To complete if another 3PID is added for this endpoint -const validMediums: string[] = ['email'] +const validMediums: string[] = ['email', 'msisdn'] // Regular expressions for different mediums const validEmailRe = /^\w[+.-\w]*\w@\w[.-\w]*\w\.\w{2,6}$/ +const validPhoneRe = /^(\+[1-9]\d{0,2})?\d{4,14}$/ -const redactAddress = (address: string): string => { - // Assuming that the address is a valid email address - const atIndex = address.indexOf('@') - const localPart = address.slice(0, atIndex) - const domainPart = address.slice(atIndex + 1) +const redactAddress = (medium: string, address: string): string => { + switch (medium) { + case 'email': { + const atIndex = address.indexOf('@') + const localPart = address.slice(0, atIndex) + const domainPart = address.slice(atIndex + 1) - const replaceRandomCharacters = ( - str: string, - redactionRatio: number - ): string => { - const chars = str.split('') - const redactionCount = Math.ceil(chars.length * redactionRatio) + const redactedLocalPart = replaceLastCharacters(localPart) + const redactedDomainPart = replaceLastCharacters(domainPart) - for (let i = 0; i < redactionCount; i++) { - const index = i * Math.floor(chars.length / redactionCount) - chars[index] = '*' + return `${redactedLocalPart}@${redactedDomainPart}` } - - return chars.join('') + case 'msisdn': + return replaceLastCharacters(address) + /* istanbul ignore next : call to redactAddress is done after checking if the medium was valid */ + default: + return address } +} + +const replaceLastCharacters = ( + str: string, + redactionRatio: number = 0.4 +): string => { + const chars = str.split('') + const redactionCount = Math.ceil(chars.length * redactionRatio) - const redactionRatio = 0.3 // Redact 30% of the characters - const redactedLocalPart = replaceRandomCharacters(localPart, redactionRatio) - const redactedDomainPart = replaceRandomCharacters(domainPart, redactionRatio) + // Replace the last `redactionCount` characters with '*' + for (let i = chars.length - redactionCount; i < chars.length; i++) { + chars[i] = '*' + } - return `${redactedLocalPart}@${redactedDomainPart}` + return chars.join('') } +// const redactEmailAddress = (address: string): string => { +// // Assuming that the address is a valid email address +// const atIndex = address.indexOf('@') +// const localPart = address.slice(0, atIndex) +// const domainPart = address.slice(atIndex + 1) + +// const redactedLocalPart = replaceLastCharacters(localPart) +// const redactedDomainPart = replaceLastCharacters(domainPart) + +// return `${redactedLocalPart}@${redactedDomainPart}` +// } + +// const redactPhoneNumber = (phoneNumber: string): string => { +// return replaceLastCharacters(phoneNumber) +// } + const StoreInvit = ( idServer: MatrixIdentityServer ): expressAppHandler => { @@ -165,10 +189,16 @@ const StoreInvit = ( switch (_medium) { case 'email': if (!validEmailRe.test(_address)) { - send(res, 400, errMsg('invalidEmail')) + send(res, 400, errMsg('invalidParam', 'Invalid email address.')) return } - // TODO : add phone number validation + break + case 'msisdn': + if (!validPhoneRe.test(_address)) { + send(res, 400, errMsg('invalidParam', 'Invalid phone number.')) + return + } + break } // Call to the lookup API to check for any existing third-party identifiers try { @@ -232,10 +262,12 @@ const StoreInvit = ( ) }) break - // TODO : add sms sending + case 'msisdn': + // TO DO implement smsSender + break } // Send 200 response - const redactedAddress = redactAddress(_address) + const redactedAddress = redactAddress(_medium, _address) idServer.db .getKeys('current') .then((keys) => { From 241ec9ecc026dc4ad5a8914af1f1679753000586 Mon Sep 17 00:00:00 2001 From: h1pp0X Date: Tue, 16 Jul 2024 16:28:46 +0400 Subject: [PATCH 7/9] fix : added a field phone --- .../matrix-identity-server/src/db/index.ts | 4 ++ .../src/ephemeral_signing/index.ts | 2 - .../matrix-identity-server/src/index.test.ts | 7 ++- .../src/invitation/index.ts | 60 ++++++++----------- .../src/invitation/invitation.md | 15 +++++ 5 files changed, 47 insertions(+), 41 deletions(-) create mode 100644 packages/matrix-identity-server/src/invitation/invitation.md diff --git a/packages/matrix-identity-server/src/db/index.ts b/packages/matrix-identity-server/src/db/index.ts index 3576f873..a6d75b10 100644 --- a/packages/matrix-identity-server/src/db/index.ts +++ b/packages/matrix-identity-server/src/db/index.ts @@ -581,11 +581,13 @@ class IdentityServerDb data: JSON.stringify(data) }) .then(() => { + this.logger.info(`Invitation token created for ${address}`) resolve(id) }) .catch((err) => { /* istanbul ignore next */ this.logger.error('Failed to insert token', err) + reject(err) }) }) } @@ -608,6 +610,8 @@ class IdentityServerDb } }) .catch((e) => { + /* istanbul ignore next */ + this.logger.error('Failed to get token', e) reject(e) }) }) diff --git a/packages/matrix-identity-server/src/ephemeral_signing/index.ts b/packages/matrix-identity-server/src/ephemeral_signing/index.ts index b1624797..f3f13ce1 100644 --- a/packages/matrix-identity-server/src/ephemeral_signing/index.ts +++ b/packages/matrix-identity-server/src/ephemeral_signing/index.ts @@ -62,9 +62,7 @@ const SignEd25519 = ( ) }) .catch((err) => { - /* istanbul ignore next */ idServer.logger.error('Token denied', err) - /* istanbul ignore next */ send(res, 404, errMsg('notFound', err)) }) } diff --git a/packages/matrix-identity-server/src/index.test.ts b/packages/matrix-identity-server/src/index.test.ts index 64ee5e88..1b039301 100644 --- a/packages/matrix-identity-server/src/index.test.ts +++ b/packages/matrix-identity-server/src/index.test.ts @@ -1221,7 +1221,7 @@ describe('Use configuration file', () => { .set('Authorization', `Bearer ${validToken}`) .set('Accept', 'application/json') .send({ - address: '+1234', + phone: '123', medium: 'msisdn', room_id: '!room:matrix.org', sender: '@dwho:matrix.org' @@ -1337,15 +1337,16 @@ describe('Use configuration file', () => { .set('Authorization', `Bearer ${validToken}`) .set('Accept', 'application/json') .send({ - address: '+33612345678', + phone: '33612345678', medium: 'msisdn', room_id: '!room:matrix.org', sender: '@dwho:matrix.org' }) + console.log(response.body) expect(response.statusCode).toBe(200) // TODO : add call to smsMock when it will be implemented expect(response.body).toHaveProperty('display_name') - expect(response.body.display_name).not.toBe('+33612345678') + expect(response.body.display_name).not.toBe('33612345678') expect(response.body).toHaveProperty('public_keys') expect(response.body).toHaveProperty('token') expect(response.body.token).toMatch(/^[a-zA-Z0-9]{64}$/) diff --git a/packages/matrix-identity-server/src/invitation/index.ts b/packages/matrix-identity-server/src/invitation/index.ts index 7df665b6..6e0d271e 100644 --- a/packages/matrix-identity-server/src/invitation/index.ts +++ b/packages/matrix-identity-server/src/invitation/index.ts @@ -14,6 +14,7 @@ import Mailer from '../utils/mailer' interface storeInvitationArgs { address: string + phone: string medium: string room_alias?: string room_avatar_url?: string @@ -27,7 +28,8 @@ interface storeInvitationArgs { } const schema = { - address: true, + address: false, + phone: false, medium: true, room_alias: false, room_avatar_url: false, @@ -106,7 +108,7 @@ const validMediums: string[] = ['email', 'msisdn'] // Regular expressions for different mediums const validEmailRe = /^\w[+.-\w]*\w@\w[.-\w]*\w\.\w{2,6}$/ -const validPhoneRe = /^(\+[1-9]\d{0,2})?\d{4,14}$/ +const validPhoneRe = /^\d{4,16}$/ const redactAddress = (medium: string, address: string): string => { switch (medium) { @@ -143,22 +145,6 @@ const replaceLastCharacters = ( return chars.join('') } -// const redactEmailAddress = (address: string): string => { -// // Assuming that the address is a valid email address -// const atIndex = address.indexOf('@') -// const localPart = address.slice(0, atIndex) -// const domainPart = address.slice(atIndex + 1) - -// const redactedLocalPart = replaceLastCharacters(localPart) -// const redactedDomainPart = replaceLastCharacters(domainPart) - -// return `${redactedLocalPart}@${redactedDomainPart}` -// } - -// const redactPhoneNumber = (phoneNumber: string): string => { -// return replaceLastCharacters(phoneNumber) -// } - const StoreInvit = ( idServer: MatrixIdentityServer ): expressAppHandler => { @@ -175,9 +161,8 @@ const StoreInvit = ( jsonContent(req, res, idServer.logger, (obj) => { // eslint-disable-next-line @typescript-eslint/no-misused-promises validateParameters(res, schema, obj, idServer.logger, async (obj) => { - const _address = (obj as storeInvitationArgs).address - const _medium = (obj as storeInvitationArgs).medium - if (!validMediums.includes(_medium)) { + const medium = (obj as storeInvitationArgs).medium + if (!validMediums.includes(medium)) { send( res, 400, @@ -185,19 +170,22 @@ const StoreInvit = ( ) return } + const address = (obj as storeInvitationArgs).address + const phone = (obj as storeInvitationArgs).phone + let mediumAddress: string = '' // Check the validity of the media - switch (_medium) { + switch (medium) { case 'email': - if (!validEmailRe.test(_address)) { + if (address == null || !validEmailRe.test(address)) { send(res, 400, errMsg('invalidParam', 'Invalid email address.')) return - } + } else mediumAddress = address break case 'msisdn': - if (!validPhoneRe.test(_address)) { + if (phone == null || !validPhoneRe.test(phone)) { send(res, 400, errMsg('invalidParam', 'Invalid phone number.')) return - } + } else mediumAddress = phone break } // Call to the lookup API to check for any existing third-party identifiers @@ -217,13 +205,12 @@ const StoreInvit = ( 'Content-Type': 'application/json' }, body: JSON.stringify({ - addresses: [_address], + addresses: [mediumAddress], algorithm: 'sha256', pepper: _pepper }) } ) - if (response.status === 200) { send(res, 400, { errcode: 'M_THREEPID_IN_USE', @@ -232,6 +219,7 @@ const StoreInvit = ( mxid: (obj as storeInvitationArgs).sender }) } else if (response.status === 400) { + // Create invitation token const ephemeralKey = await idServer.db.createKeypair( 'shortTerm', 'curve25519' @@ -240,21 +228,21 @@ const StoreInvit = ( ...(obj as storeInvitationArgs), key: ephemeralKey } - const _token = await idServer.db.createInvitationToken( - _address, + const token = await idServer.db.createInvitationToken( + mediumAddress, objWithKey ) // Send email/sms - switch (_medium) { + switch (medium) { case 'email': void transport.sendMail({ - to: _address, + to: address, raw: mailBody( verificationTemplate, (obj as storeInvitationArgs).sender_display_name ?? '*****', (obj as storeInvitationArgs).sender, - _address, + address, (obj as storeInvitationArgs).room_name ?? '*****', (obj as storeInvitationArgs).room_avatar_url ?? '*****', (obj as storeInvitationArgs).room_type ?? '*****', @@ -263,11 +251,11 @@ const StoreInvit = ( }) break case 'msisdn': - // TO DO implement smsSender + // TODO implement smsSender break } // Send 200 response - const redactedAddress = redactAddress(_medium, _address) + const redactedAddress = redactAddress(medium, mediumAddress) idServer.db .getKeys('current') .then((keys) => { @@ -283,7 +271,7 @@ const StoreInvit = ( public_key: ephemeralKey.privateKey } ], - token: _token + token } send(res, 200, responseBody) }) diff --git a/packages/matrix-identity-server/src/invitation/invitation.md b/packages/matrix-identity-server/src/invitation/invitation.md new file mode 100644 index 00000000..1aea6821 --- /dev/null +++ b/packages/matrix-identity-server/src/invitation/invitation.md @@ -0,0 +1,15 @@ +# Extension of the Matrix specification v1.11 : adding phone ('msisdn') to valid 3pid invitation media + +- the parameter media now accepts two values : 'email' and 'msisdn' +- a parameter phone is added to the request body +- a new scheme for request body parameters is adopted : + +----------------------------------------------- +| | address : REQUIRED | +| medium === 'email' | | +| | phone : OPTIONAL | +----------------------------------------------- +| | address : OPTIONAL | +| medium === 'msisdn' | | +| | phone : REQUIRED | +----------------------------------------------- From 3553be72bc5b60b98a165b5cb8170a126b35cf0c Mon Sep 17 00:00:00 2001 From: Mathixx <147631380+Mathixx@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:41:58 +0400 Subject: [PATCH 8/9] fix: invitation link is now created using link designated in server conf + update of all confs necessary --- .../matrix-client-server/src/__testData__/loginConf.json | 1 + .../src/__testData__/matrixDbTestConf.json | 1 + .../src/__testData__/presenceConf.json | 1 + .../src/__testData__/registerConf.json | 1 + .../src/__testData__/registerConfRoom.json | 1 + .../src/__testData__/requestTokenConf.json | 1 + .../matrix-client-server/src/__testData__/termsConf.json | 1 + .../src/__testData__/registerConf.json | 1 + .../src/__testData__/termsConf.json | 1 + packages/matrix-identity-server/src/config.json | 1 + packages/matrix-identity-server/src/invitation/index.ts | 8 +++++++- packages/matrix-identity-server/src/types.ts | 1 + 12 files changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/matrix-client-server/src/__testData__/loginConf.json b/packages/matrix-client-server/src/__testData__/loginConf.json index 91531f26..46c8c087 100644 --- a/packages/matrix-client-server/src/__testData__/loginConf.json +++ b/packages/matrix-client-server/src/__testData__/loginConf.json @@ -5,6 +5,7 @@ "matrix_database_engine": "sqlite", "matrix_database_host": "./src/__testData__/testMatrixLogin.db", "database_vacuum_delay": 7200, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-client-server/src/__testData__/matrixDbTestConf.json b/packages/matrix-client-server/src/__testData__/matrixDbTestConf.json index 38f4c717..7dcfdaa9 100644 --- a/packages/matrix-client-server/src/__testData__/matrixDbTestConf.json +++ b/packages/matrix-client-server/src/__testData__/matrixDbTestConf.json @@ -4,6 +4,7 @@ "database_engine": "sqlite", "database_host": "./src/__testData__/test.db", "database_vacuum_delay": 7200, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-client-server/src/__testData__/presenceConf.json b/packages/matrix-client-server/src/__testData__/presenceConf.json index e1b055b2..71bf370f 100644 --- a/packages/matrix-client-server/src/__testData__/presenceConf.json +++ b/packages/matrix-client-server/src/__testData__/presenceConf.json @@ -5,6 +5,7 @@ "matrix_database_engine": "sqlite", "matrix_database_host": "./src/__testData__/testMatrixPresence.db", "database_vacuum_delay": 7200, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-client-server/src/__testData__/registerConf.json b/packages/matrix-client-server/src/__testData__/registerConf.json index 7ca11647..6c99bb3f 100644 --- a/packages/matrix-client-server/src/__testData__/registerConf.json +++ b/packages/matrix-client-server/src/__testData__/registerConf.json @@ -5,6 +5,7 @@ "matrix_database_engine": "sqlite", "matrix_database_host": "./src/__testData__/testMatrix.db", "database_vacuum_delay": 7200, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-client-server/src/__testData__/registerConfRoom.json b/packages/matrix-client-server/src/__testData__/registerConfRoom.json index 8a3ba065..d01084f4 100644 --- a/packages/matrix-client-server/src/__testData__/registerConfRoom.json +++ b/packages/matrix-client-server/src/__testData__/registerConfRoom.json @@ -5,6 +5,7 @@ "matrix_database_engine": "sqlite", "matrix_database_host": "./src/__testData__/testMatrixRoom.db", "database_vacuum_delay": 7200, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-client-server/src/__testData__/requestTokenConf.json b/packages/matrix-client-server/src/__testData__/requestTokenConf.json index 95d59c25..fba04ce8 100644 --- a/packages/matrix-client-server/src/__testData__/requestTokenConf.json +++ b/packages/matrix-client-server/src/__testData__/requestTokenConf.json @@ -5,6 +5,7 @@ "matrix_database_engine": "sqlite", "matrix_database_host": "./src/__testData__/testMatrixRequestToken.db", "database_vacuum_delay": 7200, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-client-server/src/__testData__/termsConf.json b/packages/matrix-client-server/src/__testData__/termsConf.json index ab914823..f46c77ea 100644 --- a/packages/matrix-client-server/src/__testData__/termsConf.json +++ b/packages/matrix-client-server/src/__testData__/termsConf.json @@ -3,6 +3,7 @@ "database_engine": "sqlite", "database_host": "./src/__testData__/terms.db", "database_vacuum_delay": 7200, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-identity-server/src/__testData__/registerConf.json b/packages/matrix-identity-server/src/__testData__/registerConf.json index 6b39715d..9c24b50d 100644 --- a/packages/matrix-identity-server/src/__testData__/registerConf.json +++ b/packages/matrix-identity-server/src/__testData__/registerConf.json @@ -3,6 +3,7 @@ "database_engine": "sqlite", "database_host": "./src/__testData__/test.db", "database_vacuum_delay": 7200, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-identity-server/src/__testData__/termsConf.json b/packages/matrix-identity-server/src/__testData__/termsConf.json index ab914823..f46c77ea 100644 --- a/packages/matrix-identity-server/src/__testData__/termsConf.json +++ b/packages/matrix-identity-server/src/__testData__/termsConf.json @@ -3,6 +3,7 @@ "database_engine": "sqlite", "database_host": "./src/__testData__/terms.db", "database_vacuum_delay": 7200, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-identity-server/src/config.json b/packages/matrix-identity-server/src/config.json index 015c75d4..278cdcf7 100644 --- a/packages/matrix-identity-server/src/config.json +++ b/packages/matrix-identity-server/src/config.json @@ -12,6 +12,7 @@ "database_vacuum_delay": 3600, "federated_identity_services": null, "hashes_rate_limit": 100, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-identity-server/src/invitation/index.ts b/packages/matrix-identity-server/src/invitation/index.ts index 6e0d271e..9d688b32 100644 --- a/packages/matrix-identity-server/src/invitation/index.ts +++ b/packages/matrix-identity-server/src/invitation/index.ts @@ -84,6 +84,8 @@ const mailBody = ( // eslint-disable-next-line @typescript-eslint/naming-convention room_type: string, // eslint-disable-next-line @typescript-eslint/naming-convention + server_name_creating_invitation: string, + // eslint-disable-next-line @typescript-eslint/naming-convention room_alias?: string ): string => { return ( @@ -99,7 +101,10 @@ const mailBody = ( .replace(/__room_name__/g, room_name) .replace(/__room_avatar__/g, room_avatar) .replace(/__room_type__/g, room_type) - .replace(/__link__/g, inviteLink('matrix.to', sender_user_id, room_alias)) + .replace( + /__link__/g, + inviteLink(server_name_creating_invitation, sender_user_id, room_alias) + ) ) } @@ -246,6 +251,7 @@ const StoreInvit = ( (obj as storeInvitationArgs).room_name ?? '*****', (obj as storeInvitationArgs).room_avatar_url ?? '*****', (obj as storeInvitationArgs).room_type ?? '*****', + idServer.conf.invitation_server_name, (obj as storeInvitationArgs).room_alias ) }) diff --git a/packages/matrix-identity-server/src/types.ts b/packages/matrix-identity-server/src/types.ts index bbd3fde3..a4856230 100644 --- a/packages/matrix-identity-server/src/types.ts +++ b/packages/matrix-identity-server/src/types.ts @@ -18,6 +18,7 @@ export interface Config { database_vacuum_delay: number federated_identity_services?: string[] | null hashes_rate_limit?: number + invitation_server_name: string is_federated_identity_service: boolean key_delay: number keys_depth: number From 4a60f3a721de8a3e921f6085945c60c7407ff22e Mon Sep 17 00:00:00 2001 From: Mathixx <147631380+Mathixx@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:35:51 +0400 Subject: [PATCH 9/9] fix: put invitation_server_name parameter as optional --- packages/matrix-client-server/src/config.json | 1 + packages/matrix-identity-server/src/invitation/index.ts | 2 +- packages/matrix-identity-server/src/types.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/matrix-client-server/src/config.json b/packages/matrix-client-server/src/config.json index a3ccf4d6..7c530dc0 100644 --- a/packages/matrix-client-server/src/config.json +++ b/packages/matrix-client-server/src/config.json @@ -12,6 +12,7 @@ "database_vacuum_delay": 3600, "federated_identity_services": null, "hashes_rate_limit": 100, + "invitation_server_name": "matrix.to", "is_federated_identity_service": false, "key_delay": 3600, "keys_depth": 5, diff --git a/packages/matrix-identity-server/src/invitation/index.ts b/packages/matrix-identity-server/src/invitation/index.ts index 9d688b32..1d9a5a04 100644 --- a/packages/matrix-identity-server/src/invitation/index.ts +++ b/packages/matrix-identity-server/src/invitation/index.ts @@ -251,7 +251,7 @@ const StoreInvit = ( (obj as storeInvitationArgs).room_name ?? '*****', (obj as storeInvitationArgs).room_avatar_url ?? '*****', (obj as storeInvitationArgs).room_type ?? '*****', - idServer.conf.invitation_server_name, + idServer.conf.invitation_server_name ?? 'matrix.to', (obj as storeInvitationArgs).room_alias ) }) diff --git a/packages/matrix-identity-server/src/types.ts b/packages/matrix-identity-server/src/types.ts index a4856230..491d97d6 100644 --- a/packages/matrix-identity-server/src/types.ts +++ b/packages/matrix-identity-server/src/types.ts @@ -18,7 +18,7 @@ export interface Config { database_vacuum_delay: number federated_identity_services?: string[] | null hashes_rate_limit?: number - invitation_server_name: string + invitation_server_name?: string is_federated_identity_service: boolean key_delay: number keys_depth: number