diff --git a/packages/backend/server/src/__tests__/e2e/workspace/invite.spec.ts b/packages/backend/server/src/__tests__/e2e/workspace/invite.spec.ts index 4024df5436..280d4e4962 100644 --- a/packages/backend/server/src/__tests__/e2e/workspace/invite.spec.ts +++ b/packages/backend/server/src/__tests__/e2e/workspace/invite.spec.ts @@ -402,3 +402,55 @@ e2e('should get invite link info with status', async t => { t.truthy(getInviteInfo3, 'failed to get invite info'); t.is(getInviteInfo3.status, WorkspaceMemberStatus.UnderReview); }); + +e2e( + 'should accept invitation by link directly if status is pending', + async t => { + const owner = await app.create(Mockers.User); + const member = await app.create(Mockers.User); + + const workspace = await app.create(Mockers.Workspace, { + owner: { id: owner.id }, + }); + + await app.login(owner); + // create a pending invitation + const invite = await app.gql({ + query: inviteByEmailMutation, + variables: { + email: member.email, + workspaceId: workspace.id, + }, + }); + t.truthy(invite, 'failed to create invitation'); + + const { createInviteLink } = await app.gql({ + query: createInviteLinkMutation, + variables: { + workspaceId: workspace.id, + expireTime: WorkspaceInviteLinkExpireTime.OneDay, + }, + }); + t.truthy(createInviteLink, 'failed to create invite link'); + const link = createInviteLink.link; + const inviteLinkId = link.split('/').pop()!; + + // member accept invitation by link + await app.login(member); + await app.gql({ + query: acceptInviteByInviteIdMutation, + variables: { + inviteId: inviteLinkId, + workspaceId: workspace.id, + }, + }); + + const { getInviteInfo } = await app.gql({ + query: getInviteInfoQuery, + variables: { + inviteId: invite.invite, + }, + }); + t.is(getInviteInfo.status, WorkspaceMemberStatus.Accepted); + } +); diff --git a/packages/backend/server/src/core/workspaces/resolvers/workspace.ts b/packages/backend/server/src/core/workspaces/resolvers/workspace.ts index ddcd96ee6e..3cca032465 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/workspace.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/workspace.ts @@ -628,9 +628,13 @@ export class WorkspaceResolver { } } + await this.acceptInviteByInviteId(inviteId); + return true; + } + + private async acceptInviteByInviteId(inviteId: string) { await this.models.workspaceUser.accept(inviteId); await this.workspaceService.sendInvitationAcceptedNotification(inviteId); - return true; } private async acceptInviteByLink(user: CurrentUser, workspaceId: string) { @@ -642,6 +646,11 @@ export class WorkspaceResolver { WorkspaceRole.Collaborator, WorkspaceMemberStatus.UnderReview ); + // if status is pending, should accept the invite directly + if (role.status === WorkspaceMemberStatus.Pending) { + await this.acceptInviteByInviteId(role.id); + return; + } await this.workspaceService.sendReviewRequestNotification(role.id); return; }