feat!: Implement Cloud communication reliability (#32856)
parent
f63d8e2092
commit
b338807d76
@ -0,0 +1,9 @@ |
||||
--- |
||||
"@rocket.chat/meteor": major |
||||
"@rocket.chat/core-typings": major |
||||
"@rocket.chat/model-typings": major |
||||
"@rocket.chat/models": major |
||||
--- |
||||
|
||||
Adds a new collection to store all the workspace cloud tokens to defer the race condition management to MongoDB instead of having to handle it within the settings cache. |
||||
Removes the Cloud_Workspace_Access_Token & Cloud_Workspace_Access_Token_Expires_At settings since they are not going to be used anymore. |
||||
@ -0,0 +1,6 @@ |
||||
import { registerModel } from '@rocket.chat/models'; |
||||
|
||||
import { db } from '../../../server/database/utils'; |
||||
import { WorkspaceCredentialsRaw } from './raw/WorkspaceCredentials'; |
||||
|
||||
registerModel('IWorkspaceCredentialsModel', new WorkspaceCredentialsRaw(db)); |
||||
@ -0,0 +1,68 @@ |
||||
import type { IWorkspaceCredentials } from '@rocket.chat/core-typings'; |
||||
import type { IWorkspaceCredentialsModel } from '@rocket.chat/model-typings'; |
||||
import type { Db, DeleteResult, Filter, IndexDescription, UpdateResult } from 'mongodb'; |
||||
|
||||
import { BaseRaw } from '../../../../server/models/raw/BaseRaw'; |
||||
|
||||
export class WorkspaceCredentialsRaw extends BaseRaw<IWorkspaceCredentials> implements IWorkspaceCredentialsModel { |
||||
constructor(db: Db) { |
||||
super(db, 'workspace_credentials'); |
||||
} |
||||
|
||||
protected modelIndexes(): IndexDescription[] { |
||||
return [{ key: { scopes: 1, expirationDate: 1, accessToken: 1 }, unique: true }]; |
||||
} |
||||
|
||||
getCredentialByScope(scope = ''): Promise<IWorkspaceCredentials | null> { |
||||
const query: Filter<IWorkspaceCredentials> = { |
||||
scopes: { |
||||
$all: [scope], |
||||
$size: 1, |
||||
}, |
||||
}; |
||||
|
||||
return this.findOne(query); |
||||
} |
||||
|
||||
unsetCredentialByScope(scope = ''): Promise<DeleteResult> { |
||||
const query: Filter<IWorkspaceCredentials> = { |
||||
scopes: { |
||||
$all: [scope], |
||||
$size: 1, |
||||
}, |
||||
}; |
||||
|
||||
return this.deleteOne(query); |
||||
} |
||||
|
||||
updateCredentialByScope({ |
||||
scope, |
||||
accessToken, |
||||
expirationDate, |
||||
}: { |
||||
scope: string; |
||||
accessToken: string; |
||||
expirationDate: Date; |
||||
}): Promise<UpdateResult> { |
||||
const record = { |
||||
$set: { |
||||
scopes: [scope], |
||||
accessToken, |
||||
expirationDate, |
||||
}, |
||||
}; |
||||
|
||||
const query: Filter<IWorkspaceCredentials> = { |
||||
scopes: { |
||||
$all: [scope], |
||||
$size: 1, |
||||
}, |
||||
}; |
||||
|
||||
return this.updateOne(query, record, { upsert: true }); |
||||
} |
||||
|
||||
removeAllCredentials(): Promise<DeleteResult> { |
||||
return this.col.deleteMany({}); |
||||
} |
||||
} |
||||
@ -0,0 +1,31 @@ |
||||
import { Settings, WorkspaceCredentials } from '@rocket.chat/models'; |
||||
|
||||
import { addMigration } from '../../lib/migrations'; |
||||
|
||||
addMigration({ |
||||
version: 316, |
||||
name: 'Remove Cloud_Workspace_Access_Token and Cloud_Workspace_Access_Token_Expires_At from the settings collection and add to the WorkspaceCredentials collection', |
||||
async up() { |
||||
const workspaceCredentials = await WorkspaceCredentials.getCredentialByScope(); |
||||
if (workspaceCredentials) { |
||||
return; |
||||
} |
||||
|
||||
const accessToken = ((await Settings.getValueById('Cloud_Workspace_Access_Token')) as string) || ''; |
||||
const expirationDate = ((await Settings.getValueById('Cloud_Workspace_Access_Token_Expires_At')) as Date) || new Date(0); |
||||
|
||||
if (accessToken) { |
||||
await Settings.removeById('Cloud_Workspace_Access_Token'); |
||||
} |
||||
|
||||
if (expirationDate) { |
||||
await Settings.removeById('Cloud_Workspace_Access_Token_Expires_At'); |
||||
} |
||||
|
||||
await WorkspaceCredentials.updateCredentialByScope({ |
||||
scope: '', |
||||
accessToken, |
||||
expirationDate, |
||||
}); |
||||
}, |
||||
}); |
||||
@ -0,0 +1,8 @@ |
||||
import type { IRocketChatRecord } from '../IRocketChatRecord'; |
||||
|
||||
export interface IWorkspaceCredentials extends IRocketChatRecord { |
||||
_id: string; |
||||
scopes: string[]; |
||||
expirationDate: Date; |
||||
accessToken: string; |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
import type { IWorkspaceCredentials } from '@rocket.chat/core-typings'; |
||||
import type { DeleteResult, UpdateResult } from 'mongodb'; |
||||
|
||||
import type { IBaseModel } from './IBaseModel'; |
||||
|
||||
export interface IWorkspaceCredentialsModel extends IBaseModel<IWorkspaceCredentials> { |
||||
getCredentialByScope(scope?: string): Promise<IWorkspaceCredentials | null>; |
||||
unsetCredentialByScope(scope?: string): Promise<DeleteResult>; |
||||
updateCredentialByScope(credentials: { scope: string; accessToken: string; expirationDate: Date }): Promise<UpdateResult>; |
||||
removeAllCredentials(): Promise<DeleteResult>; |
||||
} |
||||
Loading…
Reference in new issue