mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-27 03:54:57 +02:00
UBERF-9764: Adjust gmail for new accounts (#8681)
Signed-off-by: Artem Savchenko <armisav@gmail.com>
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
import {
|
||||
type AccountUuid,
|
||||
type PersonId,
|
||||
type SocialId,
|
||||
type WorkspaceInfoWithStatus,
|
||||
type WorkspaceUuid,
|
||||
buildSocialIdString,
|
||||
systemAccountUuid
|
||||
} from '@hcengineering/core'
|
||||
import { getAccountClient } from '@hcengineering/server-client'
|
||||
import { getClient as getKvsClient } from '@hcengineering/kvs-client'
|
||||
import { generateToken } from '@hcengineering/server-token'
|
||||
import { getSocialKeyByOldEmail } from '@hcengineering/model-core'
|
||||
import type { Db } from 'mongodb'
|
||||
|
||||
// Old token and history types
|
||||
interface Credentials {
|
||||
refresh_token?: string | null
|
||||
expiry_date?: number | null
|
||||
access_token?: string | null
|
||||
token_type?: string | null
|
||||
id_token?: string | null
|
||||
scope?: string
|
||||
}
|
||||
|
||||
interface User {
|
||||
userId: string
|
||||
workspace: WorkspaceUuid
|
||||
token: string
|
||||
}
|
||||
|
||||
type History = User & {
|
||||
historyId: string
|
||||
}
|
||||
|
||||
// Updated token and history types
|
||||
interface UserV2 {
|
||||
userId: AccountUuid
|
||||
email?: string
|
||||
socialId: SocialId
|
||||
workspace: WorkspaceUuid
|
||||
token: string
|
||||
}
|
||||
|
||||
export type TokenV2 = UserV2 & Credentials
|
||||
|
||||
export type HistoryV2 = UserV2 & {
|
||||
historyId: string
|
||||
}
|
||||
|
||||
type Token = User & Credentials
|
||||
|
||||
interface WorkspaceInfoProvider {
|
||||
getWorkspaceInfo: (workspaceUuid: WorkspaceUuid) => Promise<WorkspaceInfoWithStatus | undefined>
|
||||
}
|
||||
|
||||
const GMAIL_INTEGRATION = 'gmail'
|
||||
const TOKEN_TYPE = 'token'
|
||||
|
||||
export async function performGmailAccountMigrations (db: Db, region: string | null, kvsUrl: string): Promise<void> {
|
||||
console.log('Start Gmail migrations')
|
||||
const token = generateToken(systemAccountUuid, '' as WorkspaceUuid, { service: 'admin', admin: 'true' })
|
||||
const accountClient = getAccountClient(token)
|
||||
|
||||
const allWorkpaces = await accountClient.listWorkspaces(region)
|
||||
const byId = new Map(allWorkpaces.map((it) => [it.uuid, it]))
|
||||
const oldNewIds = new Map(allWorkpaces.map((it) => [it.dataId ?? it.uuid, it]))
|
||||
const workspaceProvider: WorkspaceInfoProvider = {
|
||||
getWorkspaceInfo: async (workspaceUuid: WorkspaceUuid) => {
|
||||
const ws = oldNewIds.get(workspaceUuid as any) ?? byId.get(workspaceUuid as any)
|
||||
if (ws == null) {
|
||||
console.error('No workspace found for token', workspaceUuid)
|
||||
return undefined
|
||||
}
|
||||
return ws
|
||||
}
|
||||
}
|
||||
|
||||
await migrateGmailIntegrations(db, token, workspaceProvider)
|
||||
|
||||
await migrateGmailHistory(db, token, kvsUrl, workspaceProvider)
|
||||
console.log('Finished Gmail migrations')
|
||||
}
|
||||
|
||||
async function migrateGmailIntegrations (
|
||||
db: Db,
|
||||
token: string,
|
||||
workspaceProvider: WorkspaceInfoProvider
|
||||
): Promise<void> {
|
||||
try {
|
||||
console.log('Start Gmail account migrations')
|
||||
const gmailToken = generateToken(systemAccountUuid, '' as WorkspaceUuid, { service: 'gmail' })
|
||||
const accountClient = getAccountClient(token)
|
||||
|
||||
const gmailAccountClient = getAccountClient(gmailToken)
|
||||
|
||||
const tokens = db.collection<Token>('tokens')
|
||||
|
||||
const allTokens = await tokens.find({}).toArray()
|
||||
|
||||
for (const token of allTokens) {
|
||||
try {
|
||||
const ws = await workspaceProvider.getWorkspaceInfo(token.workspace as any)
|
||||
if (ws == null) {
|
||||
continue
|
||||
}
|
||||
token.workspace = ws.uuid
|
||||
|
||||
const socialKey = buildSocialIdString(getSocialKeyByOldEmail(token.userId))
|
||||
const socialId =
|
||||
socialKey !== undefined ? await accountClient.findFullSocialIdBySocialKey(socialKey) : undefined
|
||||
if (socialId == null) {
|
||||
console.error('No socialId found for token', token)
|
||||
continue
|
||||
}
|
||||
// Check/create integration in account
|
||||
const existing = await gmailAccountClient.getIntegration({
|
||||
kind: GMAIL_INTEGRATION,
|
||||
workspaceUuid: ws?.uuid,
|
||||
socialId: socialId._id
|
||||
})
|
||||
|
||||
if (existing == null) {
|
||||
await gmailAccountClient.createIntegration({
|
||||
kind: GMAIL_INTEGRATION,
|
||||
workspaceUuid: ws?.uuid,
|
||||
socialId: socialId._id
|
||||
})
|
||||
}
|
||||
|
||||
const existingToken = await gmailAccountClient.getIntegrationSecret({
|
||||
key: TOKEN_TYPE,
|
||||
kind: GMAIL_INTEGRATION,
|
||||
socialId: socialId._id,
|
||||
workspaceUuid: ws?.uuid
|
||||
})
|
||||
const newToken: TokenV2 = {
|
||||
...token,
|
||||
workspace: ws?.uuid,
|
||||
email: token.userId,
|
||||
userId: socialId.personUuid as AccountUuid,
|
||||
socialId
|
||||
}
|
||||
if (existingToken == null) {
|
||||
await gmailAccountClient.addIntegrationSecret({
|
||||
key: TOKEN_TYPE,
|
||||
kind: GMAIL_INTEGRATION,
|
||||
socialId: socialId._id,
|
||||
secret: JSON.stringify(newToken),
|
||||
workspaceUuid: token.workspace
|
||||
})
|
||||
} else {
|
||||
const updatedToken = {
|
||||
...existingToken,
|
||||
...newToken
|
||||
}
|
||||
await gmailAccountClient.updateIntegrationSecret({
|
||||
key: TOKEN_TYPE,
|
||||
kind: GMAIL_INTEGRATION,
|
||||
socialId: socialId._id,
|
||||
secret: JSON.stringify(updatedToken),
|
||||
workspaceUuid: token.workspace
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error migrating token', token, e)
|
||||
}
|
||||
}
|
||||
console.log('Gmail integrations migrations done, integration count:', allTokens.length)
|
||||
} catch (e) {
|
||||
console.error('Error migrating tokens', e)
|
||||
}
|
||||
}
|
||||
|
||||
async function migrateGmailHistory (
|
||||
db: Db,
|
||||
token: string,
|
||||
kvsUrl: string,
|
||||
workspaceProvider: WorkspaceInfoProvider
|
||||
): Promise<void> {
|
||||
try {
|
||||
console.log('Start Gmail history migrations')
|
||||
const accountClient = getAccountClient(token)
|
||||
const history = db.collection<History>('histories')
|
||||
const allHistories = await history.find({}).toArray()
|
||||
|
||||
const kvsClient = getKvsClient(kvsUrl, token)
|
||||
|
||||
for (const history of allHistories) {
|
||||
try {
|
||||
const socialKey = buildSocialIdString(getSocialKeyByOldEmail(history.userId))
|
||||
const socialId =
|
||||
socialKey !== undefined ? await accountClient.findFullSocialIdBySocialKey(socialKey) : undefined
|
||||
if (socialId == null) {
|
||||
console.error('No socialId found for history', history)
|
||||
continue
|
||||
}
|
||||
// Update/create history in KVS
|
||||
const ws = await workspaceProvider.getWorkspaceInfo(history.workspace as any)
|
||||
if (ws == null) {
|
||||
continue
|
||||
}
|
||||
const historyKey = getHistoryKey(ws.uuid, socialId._id)
|
||||
const existingHistory = await kvsClient.getValue<HistoryV2>(historyKey)
|
||||
const updatedHistory: HistoryV2 = {
|
||||
...(existingHistory ?? history),
|
||||
email: history.userId,
|
||||
workspace: ws.uuid,
|
||||
userId: socialId.personUuid as AccountUuid,
|
||||
socialId
|
||||
}
|
||||
await kvsClient.setValue(historyKey, updatedHistory)
|
||||
} catch (e) {
|
||||
console.error('Error migrating history', history, e)
|
||||
}
|
||||
}
|
||||
console.log('Finished migrating gmail history, count:', allHistories.length)
|
||||
} catch (e) {
|
||||
console.error('Error migrating gmail history', e)
|
||||
}
|
||||
}
|
||||
|
||||
function getHistoryKey (workspace: WorkspaceUuid, userId: PersonId): string {
|
||||
return `history:${workspace}:${userId}`
|
||||
}
|
||||
Reference in New Issue
Block a user