From 56c573ebf32d2573adb247c3fe5e7641bc25083b Mon Sep 17 00:00:00 2001 From: darkskygit Date: Thu, 12 Dec 2024 10:01:13 +0000 Subject: [PATCH] fix(server): accept invite condition (#9124) --- .../backend/server/src/core/permission/service.ts | 11 +++++++++-- .../src/core/workspaces/resolvers/workspace.ts | 9 +++++++++ packages/backend/server/tests/team.e2e.ts | 14 +++++++++++++- .../frontend/i18n/src/i18n-completenesses.json | 2 +- 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/backend/server/src/core/permission/service.ts b/packages/backend/server/src/core/permission/service.ts index 2bc26b0bc7..bf7bb86c5a 100644 --- a/packages/backend/server/src/core/permission/service.ts +++ b/packages/backend/server/src/core/permission/service.ts @@ -323,16 +323,23 @@ export class PermissionService { }); if (data) { + const toBeOwner = permission === Permission.Owner; if (data.accepted && data.status === WorkspaceMemberStatus.Accepted) { const [p] = await this.prisma.$transaction( [ this.prisma.workspaceUserPermission.update({ - where: { workspaceId_userId: { workspaceId: ws, userId: user } }, + where: { + workspaceId_userId: { workspaceId: ws, userId: user }, + // only update permission: + // 1. if the new permission is owner and original permission is admin + // 2. if the original permission is not owner + type: toBeOwner ? Permission.Admin : { not: Permission.Owner }, + }, data: { type: permission }, }), // If the new permission is owner, we need to revoke old owner - permission === Permission.Owner + toBeOwner ? this.prisma.workspaceUserPermission.updateMany({ where: { workspaceId: ws, diff --git a/packages/backend/server/src/core/workspaces/resolvers/workspace.ts b/packages/backend/server/src/core/workspaces/resolvers/workspace.ts index c3c35314d2..7f72993992 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/workspace.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/workspace.ts @@ -15,6 +15,7 @@ import GraphQLUpload from 'graphql-upload/GraphQLUpload.mjs'; import type { FileUpload } from '../../../fundamentals'; import { + AlreadyInSpace, Cache, CantChangeSpaceOwner, DocNotFound, @@ -528,6 +529,14 @@ export class WorkspaceResolver { } if (user) { + const status = await this.permissions.getWorkspaceMemberStatus( + workspaceId, + user.id + ); + if (status === WorkspaceMemberStatus.Accepted) { + throw new AlreadyInSpace({ spaceId: workspaceId }); + } + // invite link const invite = await this.cache.get<{ inviteId: string }>( `workspace:inviteLink:${workspaceId}` diff --git a/packages/backend/server/tests/team.e2e.ts b/packages/backend/server/tests/team.e2e.ts index 61125fbffc..6c85226689 100644 --- a/packages/backend/server/tests/team.e2e.ts +++ b/packages/backend/server/tests/team.e2e.ts @@ -120,6 +120,9 @@ const init = async (app: INestApplication, memberLimit = 10) => { await acceptInviteById(app, ws.id, inviteId, false, member.token.token); return member; }, + async (token: string) => { + await acceptInviteById(app, ws.id, inviteId, false, token); + }, ] as const; }; @@ -259,7 +262,7 @@ test('should be able to leave workspace', async t => { test('should be able to invite by link', async t => { const { app, permissions, quotaManager } = t.context; const { createInviteLink, owner, ws } = await init(app, 4); - const [inviteId, invite] = await createInviteLink(); + const [inviteId, invite, acceptInvite] = await createInviteLink(); { // check invite link @@ -311,5 +314,14 @@ test('should be able to invite by link', async t => { WorkspaceMemberStatus.UnderReview, 'should not change status' ); + + { + const message = `You have already joined in Space ${ws.id}.`; + await t.throwsAsync( + acceptInvite(owner.token.token), + { message }, + 'should throw error if member already in workspace' + ); + } } }); diff --git a/packages/frontend/i18n/src/i18n-completenesses.json b/packages/frontend/i18n/src/i18n-completenesses.json index 0118a4d98b..8496850ee1 100644 --- a/packages/frontend/i18n/src/i18n-completenesses.json +++ b/packages/frontend/i18n/src/i18n-completenesses.json @@ -7,7 +7,7 @@ "en": 100, "es-AR": 13, "es-CL": 14, - "es": 13, + "es": 12, "fr": 61, "hi": 2, "it-IT": 1,