Skip to content

Commit

Permalink
Merge pull request #113 from linagora/fix-store-invite
Browse files Browse the repository at this point in the history
Fix store invite
  • Loading branch information
h1ppox99 authored Jul 17, 2024
2 parents 2ab3001 + 4a60f3a commit 40128c0
Show file tree
Hide file tree
Showing 20 changed files with 342 additions and 152 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions packages/matrix-client-server/src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions packages/matrix-identity-server/src/3pid/bind.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ const bind = <T extends string = never>(
})
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) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions packages/matrix-identity-server/src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
25 changes: 25 additions & 0 deletions packages/matrix-identity-server/src/db/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
88 changes: 71 additions & 17 deletions packages/matrix-identity-server/src/db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Collections, string> = {
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, address text, data 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<Record<Collections, string[]>> = {
oneTimeTokens: ['expires'],
attempts: ['expires'],
invitationTokens: ['address'],
oneTimeTokens: ['expires'],
userHistory: ['timestamp']
}

Expand Down Expand Up @@ -563,6 +566,57 @@ class IdentityServerDb<T extends string = never>
return this.createOneTimeToken(data, expires)
}

// eslint-disable-next-line @typescript-eslint/promise-function-async
createInvitationToken(address: string, data: object): Promise<string> {
/* 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(() => {
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)
})
})
}

// eslint-disable-next-line @typescript-eslint/promise-function-async
verifyInvitationToken(id: string): Promise<object> {
/* 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) => {
/* istanbul ignore next */
this.logger.error('Failed to get token', e)
reject(e)
})
})
}

// eslint-disable-next-line @typescript-eslint/promise-function-async
verifyToken(id: string): Promise<object> {
/* istanbul ignore if */
Expand Down
48 changes: 20 additions & 28 deletions packages/matrix-identity-server/src/ephemeral_signing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,37 +41,29 @@ const SignEd25519 = <T extends string = never>(
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
)
/* istanbul ignore next */
send(res, 400, errMsg('unknown', err))
idServer.logger.error('Token denied', err)
send(res, 404, errMsg('notFound', err))
})
}
})
Expand Down
Loading

0 comments on commit 40128c0

Please sign in to comment.