diff --git a/services/calendar/pod-calendar/src/auth.ts b/services/calendar/pod-calendar/src/auth.ts index 8ac14bca33..16d66b2992 100644 --- a/services/calendar/pod-calendar/src/auth.ts +++ b/services/calendar/pod-calendar/src/auth.ts @@ -31,11 +31,11 @@ import { Credentials, OAuth2Client } from 'google-auth-library' import { calendar_v3, google } from 'googleapis' import { encode64 } from './base64' import { getClient } from './client' -import { addUserByEmail, removeUserByEmail, setSyncHistory } from './kvsUtils' +import { setSyncHistory } from './kvsUtils' import { lock } from './mutex' import { IncomingSyncManager } from './sync' import { CALENDAR_INTEGRATION, GoogleEmail, SCOPES, State, Token, User } from './types' -import { getGoogleClient, removeIntegrationSecret } from './utils' +import { addUserByEmail, getGoogleClient, removeIntegrationSecret, removeUserByEmail } from './utils' import { WatchController } from './watch' interface AuthResult { @@ -122,7 +122,7 @@ export class AuthController { if (integration !== undefined) { await this.client.remove(integration) } - await removeUserByEmail(this.user, value) + removeUserByEmail(this.user, value) const data = { kind: CALENDAR_INTEGRATION, workspaceUuid: this.user.workspace, @@ -283,7 +283,7 @@ export class AuthController { } else { await this.accountClient.addIntegrationSecret(data) } - await addUserByEmail(_token, email) + addUserByEmail(_token, email) } catch (err) { this.ctx.error('update token error', { workspace: this.user.workspace, user: this.user.userId, err }) } diff --git a/services/calendar/pod-calendar/src/calendar.ts b/services/calendar/pod-calendar/src/calendar.ts index efeb27e012..ec0a1a5450 100644 --- a/services/calendar/pod-calendar/src/calendar.ts +++ b/services/calendar/pod-calendar/src/calendar.ts @@ -20,7 +20,6 @@ import { areEqualMarkups, htmlToMarkup, isEmptyMarkup, jsonToHTML, markupToJSON import { deepEqual } from 'fast-equals' import { OAuth2Client } from 'google-auth-library' import { calendar_v3 } from 'googleapis' -import { removeUserByEmail } from './kvsUtils' import { getRateLimitter, RateLimiter } from './rateLimiter' import { CALENDAR_INTEGRATION, type Token } from './types' import { @@ -32,6 +31,7 @@ import { parseEventDate, parseRecurrenceStrings, removeIntegrationSecret, + removeUserByEmail, setCredentials } from './utils' import type { WorkspaceClient } from './workspaceClient' @@ -66,7 +66,7 @@ export class CalendarClient { const calendarClient = new CalendarClient(ctx, accountClient, user, client, workspace) const authSucces = await setCredentials(calendarClient.oAuth2Client, user) if (!authSucces) { - await removeUserByEmail(user, user.email) + removeUserByEmail(user, user.email) await removeIntegrationSecret(ctx, calendarClient.accountClient, { socialId: user.userId, kind: CALENDAR_INTEGRATION, diff --git a/services/calendar/pod-calendar/src/calendarController.ts b/services/calendar/pod-calendar/src/calendarController.ts index 639b7a9634..cbaa72e07e 100644 --- a/services/calendar/pod-calendar/src/calendarController.ts +++ b/services/calendar/pod-calendar/src/calendarController.ts @@ -25,7 +25,6 @@ import { import config from './config' import { getIntegrations } from './integrations' import { WorkspaceClient } from './workspaceClient' -import { cleanUserByEmail } from './kvsUtils' interface WorkspaceStateInfo { shouldStart: boolean @@ -72,7 +71,6 @@ export class CalendarController { } private async runAll (groups: Map): Promise { - await cleanUserByEmail() const ids = [...groups.keys()] if (ids.length === 0) return const limiter = new RateLimiter(config.InitLimit) diff --git a/services/calendar/pod-calendar/src/kvsUtils.ts b/services/calendar/pod-calendar/src/kvsUtils.ts index 8c7dbc13ce..b79155124f 100644 --- a/services/calendar/pod-calendar/src/kvsUtils.ts +++ b/services/calendar/pod-calendar/src/kvsUtils.ts @@ -1,7 +1,7 @@ import { WorkspaceUuid } from '@hcengineering/core' import { KeyValueClient, getClient as getKeyValueClient } from '@hcengineering/kvs-client' import config from './config' -import { CALENDAR_INTEGRATION, GoogleEmail, Token, User } from './types' +import { CALENDAR_INTEGRATION, GoogleEmail, User } from './types' import { getServiceToken } from './utils' let keyValueClient: KeyValueClient | undefined @@ -59,42 +59,3 @@ export async function setEventHistory ( const client = getKvsClient() await client.setValue(eventHistoryKey(user, email, calendarId), historyId) } - -export async function getUserByEmail (email: GoogleEmail): Promise { - const client = getKvsClient() - const key = `${CALENDAR_INTEGRATION}:users:${email}` - return (await client.getValue(key)) ?? [] -} - -export async function addUserByEmail (user: Token, email: GoogleEmail): Promise { - const client = getKvsClient() - const key = `${CALENDAR_INTEGRATION}:users:${email}` - const curr = (await client.getValue(key)) ?? [] - const exists = curr.find((p) => p.userId === user.userId && p.workspace === user.workspace) - if (exists !== undefined) { - return - } - curr.push(user) - await client.setValue(key, curr) -} - -export async function removeUserByEmail (user: User, email: GoogleEmail): Promise { - const client = getKvsClient() - const key = `${CALENDAR_INTEGRATION}:users:${email}` - const curr = (await client.getValue(key)) ?? [] - const newCurr = curr.filter((p) => p.userId !== user.userId || p.workspace !== user.workspace) - if (newCurr.length === 0) { - await client.deleteKey(key) - } else { - await client.setValue(key, newCurr) - } -} - -export async function cleanUserByEmail (): Promise { - const client = getKvsClient() - const keys = await client.listKeys(`${CALENDAR_INTEGRATION}:users:`) - if (keys?.keys == null) return - for (const key of keys.keys) { - await client.deleteKey(key) - } -} diff --git a/services/calendar/pod-calendar/src/outcomingClient.ts b/services/calendar/pod-calendar/src/outcomingClient.ts index ac13d00dd9..52bdd66136 100644 --- a/services/calendar/pod-calendar/src/outcomingClient.ts +++ b/services/calendar/pod-calendar/src/outcomingClient.ts @@ -22,7 +22,7 @@ import { deepEqual } from 'fast-equals' import { OAuth2Client } from 'google-auth-library' import { calendar_v3 } from 'googleapis' import { getClient } from './client' -import { removeUserByEmail, setSyncHistory } from './kvsUtils' +import { setSyncHistory } from './kvsUtils' import { lock, synced } from './mutex' import { getRateLimitter, RateLimiter } from './rateLimiter' import { CALENDAR_INTEGRATION, Token } from './types' @@ -35,6 +35,7 @@ import { parseEventDate, parseRecurrenceStrings, removeIntegrationSecret, + removeUserByEmail, setCredentials } from './utils' @@ -417,7 +418,7 @@ export class OutcomingClient { workspace: user.workspace, email: user.email }) - await removeUserByEmail(user, user.email) + removeUserByEmail(user, user.email) await removeIntegrationSecret(ctx, accountClient, { socialId: user.userId, kind: CALENDAR_INTEGRATION, diff --git a/services/calendar/pod-calendar/src/pushHandler.ts b/services/calendar/pod-calendar/src/pushHandler.ts index 50b4c353fc..328b0e237f 100644 --- a/services/calendar/pod-calendar/src/pushHandler.ts +++ b/services/calendar/pod-calendar/src/pushHandler.ts @@ -16,10 +16,9 @@ import { AccountClient } from '@hcengineering/account-client' import { MeasureContext, TxOperations } from '@hcengineering/core' import { getClient } from './client' -import { getUserByEmail, removeUserByEmail } from './kvsUtils' import { IncomingSyncManager } from './sync' import { CALENDAR_INTEGRATION, GoogleEmail, Token } from './types' -import { getGoogleClient, removeIntegrationSecret, setCredentials } from './utils' +import { getGoogleClient, getUserByEmail, removeIntegrationSecret, removeUserByEmail, setCredentials } from './utils' export class PushHandler { constructor ( @@ -37,7 +36,7 @@ export class PushHandler { const res = getGoogleClient() const authSuccess = await setCredentials(res.auth, token) if (!authSuccess) { - await removeUserByEmail(token, token.email) + removeUserByEmail(token, token.email) await removeIntegrationSecret(this.ctx, this.accountClient, { kind: CALENDAR_INTEGRATION, workspaceUuid: token.workspace, @@ -63,7 +62,7 @@ export class PushHandler { } async push (email: GoogleEmail, mode: 'events' | 'calendar', calendarId?: string): Promise { - const tokens = await getUserByEmail(email) + const tokens = getUserByEmail(email) this.ctx.info('push', { email, mode, calendarId, tokens: tokens.length }) for (const token of tokens) { await this.sync(token, mode === 'events' ? calendarId ?? null : null) diff --git a/services/calendar/pod-calendar/src/sync.ts b/services/calendar/pod-calendar/src/sync.ts index ea51fd565b..02e791b539 100644 --- a/services/calendar/pod-calendar/src/sync.ts +++ b/services/calendar/pod-calendar/src/sync.ts @@ -43,13 +43,7 @@ import { htmlToMarkup } from '@hcengineering/text' import { deepEqual } from 'fast-equals' import { calendar_v3 } from 'googleapis' import { getClient } from './client' -import { - getCalendarsSyncHistory, - getEventHistory, - removeUserByEmail, - setCalendarsSyncHistory, - setEventHistory -} from './kvsUtils' +import { getCalendarsSyncHistory, getEventHistory, setCalendarsSyncHistory, setEventHistory } from './kvsUtils' import { lock } from './mutex' import { getRateLimitter, RateLimiter } from './rateLimiter' import { CALENDAR_INTEGRATION, GoogleEmail, Token, User } from './types' @@ -58,6 +52,7 @@ import { parseEventDate, parseRecurrenceStrings, removeIntegrationSecret, + removeUserByEmail, setCredentials } from './utils' import { WatchController } from './watch' @@ -104,7 +99,7 @@ export class IncomingSyncManager { try { const authSucces = await setCredentials(google.auth, user) if (!authSucces) { - await removeUserByEmail(user, user.email) + removeUserByEmail(user, user.email) await removeIntegrationSecret(ctx, accountClient, { socialId: user.userId, kind: CALENDAR_INTEGRATION, diff --git a/services/calendar/pod-calendar/src/utils.ts b/services/calendar/pod-calendar/src/utils.ts index 5b21c9a7d0..868e5f945c 100644 --- a/services/calendar/pod-calendar/src/utils.ts +++ b/services/calendar/pod-calendar/src/utils.ts @@ -29,7 +29,7 @@ import { generateToken } from '@hcengineering/server-token' import { Credentials, OAuth2Client } from 'google-auth-library' import { calendar_v3, google } from 'googleapis' import config from './config' -import { CALENDAR_INTEGRATION, ReccuringData, State, type Token, type User } from './types' +import { CALENDAR_INTEGRATION, GoogleEmail, ReccuringData, State, type Token, type User } from './types' export class DeferredPromise { public readonly promise: Promise @@ -363,3 +363,29 @@ export function parseEventDate (date: calendar_v3.Schema$EventDateTime | undefin } return 0 } + +const users = new Map() + +export function getUserByEmail (email: GoogleEmail): Token[] { + return users.get(email) ?? [] +} + +export function addUserByEmail (user: Token, email: GoogleEmail): void { + const curr = getUserByEmail(email) + const exists = curr.find((p) => p.userId === user.userId && p.workspace === user.workspace) + if (exists !== undefined) { + return + } + curr.push(user) + users.set(email, curr) +} + +export function removeUserByEmail (user: User, email: GoogleEmail): void { + const curr = getUserByEmail(email) + const newCurr = curr.filter((p) => p.userId !== user.userId || p.workspace !== user.workspace) + if (newCurr.length === 0) { + users.delete(email) + } else { + users.set(email, newCurr) + } +} diff --git a/services/calendar/pod-calendar/src/workspaceClient.ts b/services/calendar/pod-calendar/src/workspaceClient.ts index 43e2dd0256..2ec17bdda3 100644 --- a/services/calendar/pod-calendar/src/workspaceClient.ts +++ b/services/calendar/pod-calendar/src/workspaceClient.ts @@ -27,11 +27,12 @@ import core, { import { CalendarClient } from './calendar' import { getClient } from './client' import config from './config' -import { addUserByEmail, getSyncHistory, setSyncHistory } from './kvsUtils' +import { getSyncHistory, setSyncHistory } from './kvsUtils' import { synced } from './mutex' import { IncomingSyncManager } from './sync' import { getWorkspaceTokens } from './tokens' import { GoogleEmail, Token } from './types' +import { addUserByEmail } from './utils' export class WorkspaceClient { private readonly clients = new Map() @@ -89,7 +90,7 @@ export class WorkspaceClient { for (const token of tokens) { if (token.workspaceUuid === null) continue const parsedToken = JSON.parse(token.secret) - await addUserByEmail(parsedToken, token.key as GoogleEmail) + addUserByEmail(parsedToken, token.key as GoogleEmail) await this.createCalendarClient(parsedToken) } const limiter = new RateLimiter(config.InitLimit)