diff --git a/packages/account-client/src/client.ts b/packages/account-client/src/client.ts index 2ce390315a..479cae39b2 100644 --- a/packages/account-client/src/client.ts +++ b/packages/account-client/src/client.ts @@ -26,7 +26,9 @@ import { WorkspaceMode, concatLink, type WorkspaceUserOperation, - WorkspaceUuid + type WorkspaceUuid, + type PersonId, + type SocialIdType } from '@hcengineering/core' import platform, { PlatformError, Severity, Status } from '@hcengineering/platform' import type { LoginInfo, OtpInfo, WorkspaceLoginInfo, RegionInfo, WorkspaceOperation } from './types' @@ -109,6 +111,12 @@ export interface AccountClient { assignWorkspace: (email: string, workspaceUuid: string, role: AccountRole) => Promise updateBackupInfo: (info: BackupStatus) => Promise updateWorkspaceRoleBySocialId: (socialKey: string, targetRole: AccountRole) => Promise + ensurePerson: ( + socialType: SocialIdType, + socialValue: string, + firstName: string, + lastName: string + ) => Promise<{ uuid: PersonUuid, socialId: PersonId }> setCookie: () => Promise deleteCookie: () => Promise @@ -592,6 +600,20 @@ class AccountClientImpl implements AccountClient { await this.rpc(request) } + async ensurePerson ( + socialType: SocialIdType, + socialValue: string, + firstName: string, + lastName: string + ): Promise<{ uuid: PersonUuid, socialId: PersonId }> { + const request = { + method: 'ensurePerson' as const, + params: { socialType, socialValue, firstName, lastName } + } + + return await this.rpc(request) + } + async setCookie (): Promise { const url = concatLink(this.url, '/cookie') const response = await fetch(url, { ...this.request, method: 'PUT' }) diff --git a/server/account/src/operations.ts b/server/account/src/operations.ts index b2ff02bf1c..0133b9809d 100644 --- a/server/account/src/operations.ts +++ b/server/account/src/operations.ts @@ -1657,6 +1657,43 @@ export async function assignWorkspace ( } } +export async function ensurePerson ( + ctx: MeasureContext, + db: AccountDB, + branding: Branding | null, + token: string, + params: { + socialType: SocialIdType + socialValue: string + firstName: string + lastName: string + } +): Promise<{ uuid: PersonUuid, socialId: PersonId }> { + const { extra } = decodeTokenVerbose(ctx, token) + verifyAllowedServices(['schedule'], extra) + + const { socialType, socialValue, firstName, lastName } = params + + if ( + !Object.values(SocialIdType).includes(socialType) || + firstName.length === 0 || + lastName.length === 0 || + socialValue.length === 0 + ) { + throw new PlatformError(new Status(Severity.ERROR, platform.status.BadRequest, {})) + } + + const socialId = await db.socialId.findOne({ type: socialType, value: socialValue }) + if (socialId != null) { + return { uuid: socialId.personUuid, socialId: socialId.key } + } + + const personUuid = await db.person.insertOne({ firstName, lastName }) + const newSocialId = await db.socialId.insertOne({ type: socialType, value: socialValue, personUuid }) + + return { uuid: personUuid, socialId: newSocialId } +} + export type AccountMethods = | 'login' | 'loginOtp' @@ -1698,6 +1735,7 @@ export type AccountMethods = | 'findPerson' | 'performWorkspaceOperation' | 'updateWorkspaceRoleBySocialId' + | 'ensurePerson' /** * @public @@ -1748,7 +1786,8 @@ export function getMethods (hasSignUp: boolean = true): Partial