From c26ea595cd7f45e2859d77f3ef3b19c8016e54a9 Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Tue, 16 Apr 2024 21:09:57 +0700 Subject: [PATCH] UBERF-6577: Fix invite link with null mask (#5372) --- .../src/components/InviteSetting.svelte | 2 +- server/account/package.json | 1 + server/account/src/index.ts | 24 ++++++++++++++----- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/plugins/setting-resources/src/components/InviteSetting.svelte b/plugins/setting-resources/src/components/InviteSetting.svelte index 5d51890e40..2674f4e842 100644 --- a/plugins/setting-resources/src/components/InviteSetting.svelte +++ b/plugins/setting-resources/src/components/InviteSetting.svelte @@ -25,7 +25,7 @@ const client = getClient() let expTime: number = 48 - let mask: string + let mask: string = '' let limit: number = -1 let noLimit: boolean = true let existingInviteSettings: InviteSettings[] diff --git a/server/account/package.json b/server/account/package.json index 36cb2aca06..c132be166b 100644 --- a/server/account/package.json +++ b/server/account/package.json @@ -45,6 +45,7 @@ "@hcengineering/server-backup": "^0.6.0", "@hcengineering/server-tool": "^0.6.0", "@hcengineering/server-token": "^0.6.7", + "@hcengineering/analytics": "^0.6.0", "@hcengineering/model-all": "^0.6.0", "node-fetch": "^2.6.6" } diff --git a/server/account/src/index.ts b/server/account/src/index.ts index 94b4595801..34fb689864 100644 --- a/server/account/src/index.ts +++ b/server/account/src/index.ts @@ -13,6 +13,7 @@ // limitations under the f. // +import { Analytics } from '@hcengineering/analytics' import contact, { AvatarType, buildGravatarId, @@ -262,6 +263,7 @@ async function getAccountInfoByToken ( try { email = decodeToken(token)?.email } catch (err: any) { + Analytics.handleError(err) await ctx.error('Invalid token', { token }) throw new PlatformError(new Status(Severity.ERROR, platform.status.Unauthorized, {})) } @@ -306,6 +308,7 @@ export async function login ( await ctx.info('login success', { email, productId }) return result } catch (err: any) { + Analytics.handleError(err) await ctx.error('login failed', { email, productId, _email, err }) throw err } @@ -395,14 +398,20 @@ export async function getInvite (db: Db, inviteId: ObjectId): Promise { +export async function checkInvite (ctx: MeasureContext, invite: Invite | null, email: string): Promise { if (invite === null || invite.limit === 0) { + void ctx.error('invite', { email, state: 'no invite or limit exceed' }) + Analytics.handleError(new Error(`no invite or invite limit exceed ${email}`)) throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {})) } if (invite.exp < Date.now()) { + void ctx.error('invite', { email, state: 'link expired' }) + Analytics.handleError(new Error(`invite link expired ${invite._id.toString()} ${email}`)) throw new PlatformError(new Status(Severity.ERROR, platform.status.ExpiredLink, {})) } - if (!new RegExp(invite.emailMask).test(email)) { + if (invite.emailMask != null && invite.emailMask.trim().length > 0 && !new RegExp(invite.emailMask).test(email)) { + void ctx.error('invite', { email, state: 'mask to match', mask: invite.emailMask }) + Analytics.handleError(new Error(`invite link mask failed ${invite._id.toString()} ${email} ${invite.emailMask}`)) throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {})) } @@ -429,7 +438,7 @@ export async function join ( ): Promise { const email = cleanEmail(_email) const invite = await getInvite(db, inviteId) - const workspace = await checkInvite(invite, email) + const workspace = await checkInvite(ctx, invite, email) await ctx.info(`join attempt:${email}, ${workspace.name}`) const ws = await assignWorkspace(ctx, db, productId, email, workspace.name) @@ -540,7 +549,7 @@ export async function signUpJoin ( const email = cleanEmail(_email) console.log(`signup join:${email} ${first} ${last}`) const invite = await getInvite(db, inviteId) - const workspace = await checkInvite(invite, email) + const workspace = await checkInvite(ctx, invite, email) const sesURL = getMetadata(accountPlugin.metadata.SES_URL) await createAcc( ctx, @@ -929,6 +938,7 @@ export async function createWorkspace ( ) } } catch (err: any) { + Analytics.handleError(err) return { workspaceInfo, err, client: null as any } } // Workspace is created, we need to clear disabled flag. @@ -1281,6 +1291,7 @@ export async function assignWorkspace ( const email = cleanEmail(_email) const initWS = getMetadata(toolPlugin.metadata.InitWorkspace) if (initWS !== undefined && initWS === workspaceId) { + Analytics.handleError(new Error(`assign-workspace failed ${email} ${workspaceId}`)) await ctx.error('assign-workspace failed', { email, workspaceId, reason: 'initWs === workspaceId' }) throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {})) } @@ -1616,7 +1627,7 @@ export async function checkJoin ( ): Promise { const { email } = decodeToken(token) const invite = await getInvite(db, inviteId) - const workspace = await checkInvite(invite, email) + const workspace = await checkInvite(ctx, invite, email) const ws = await getWorkspaceById(db, productId, workspace.name) if (ws === null) { await ctx.error('workspace not found', { name: workspace.name, email, inviteId }) @@ -1826,6 +1837,7 @@ function wrap ( ? err.status : new Status(Severity.ERROR, platform.status.InternalServerError, {}) if (status.code === platform.status.InternalServerError) { + Analytics.handleError(err) void ctx.error('error', { status, err }) } else { void ctx.error('error', { status }) @@ -1849,7 +1861,7 @@ export async function joinWithProvider ( ): Promise { const email = cleanEmail(_email) const invite = await getInvite(db, inviteId) - const workspace = await checkInvite(invite, email) + const workspace = await checkInvite(ctx, invite, email) if (last == null) { last = '' }