Skip to content

Commit

Permalink
fix: guard now checks if user is deactivated
Browse files Browse the repository at this point in the history
  • Loading branch information
apsantiso committed Jul 22, 2024
1 parent 6d748ec commit 1c52d7c
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 2 deletions.
66 changes: 66 additions & 0 deletions src/modules/workspaces/guards/workspaces.guard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ describe('WorkspaceGuard', () => {

it('When Team does not exist, then throw', async () => {
const user = newUser();
const workspaceMember = newWorkspaceUser({ memberId: user.uuid });

jest.spyOn(reflector, 'get').mockReturnValue({
requiredRole: WorkspaceRole.MANAGER,
accessContext: AccessContext.TEAM,
Expand All @@ -276,6 +278,8 @@ describe('WorkspaceGuard', () => {
teamUser: null,
});

workspaceUseCases.findUserInWorkspace.mockResolvedValue(workspaceMember);

const context = createMockExecutionContext(user, {
params: { teamId: v4() },
query: {},
Expand All @@ -290,11 +294,20 @@ describe('WorkspaceGuard', () => {
it('When user is team member, then grant access', async () => {
const user = newUser();
const workspace = newWorkspace({ owner: user });
const workspaceMember = newWorkspaceUser({
memberId: user.uuid,
workspaceId: workspace.id,
});
const team = newWorkspaceTeam({
workspaceId: workspace.id,
manager: user,
});

workspaceUseCases.findUserAndWorkspace.mockResolvedValue({
workspace,
workspaceUser: workspaceMember,
});

jest.spyOn(reflector, 'get').mockReturnValue({
requiredRole: WorkspaceRole.MEMBER,
accessContext: AccessContext.TEAM,
Expand All @@ -318,13 +331,22 @@ describe('WorkspaceGuard', () => {
const member = newUser();
const team = newWorkspaceTeam({ manager });
const workspace = newWorkspace();
const workspaceMember = newWorkspaceUser({
memberId: member.uuid,
workspaceId: workspace.id,
});

jest.spyOn(reflector, 'get').mockReturnValue({
requiredRole: WorkspaceRole.MANAGER,
accessContext: AccessContext.TEAM,
idSource: 'params',
});

workspaceUseCases.findUserAndWorkspace.mockResolvedValue({
workspace,
workspaceUser: workspaceMember,
});

workspaceUseCases.findUserInTeam.mockResolvedValue({
team,
teamUser: {} as WorkspaceTeamUser,
Expand All @@ -344,13 +366,22 @@ describe('WorkspaceGuard', () => {
const nonMemberUser = newUser();
const team = newWorkspaceTeam();
const workspace = newWorkspace();
const workspaceMember = newWorkspaceUser({
memberId: nonMemberUser.uuid,
workspaceId: workspace.id,
});

jest.spyOn(reflector, 'get').mockReturnValue({
requiredRole: WorkspaceRole.MEMBER,
accessContext: AccessContext.TEAM,
idSource: 'params',
});

workspaceUseCases.findUserAndWorkspace.mockResolvedValue({
workspace,
workspaceUser: workspaceMember,
});

workspaceUseCases.findById.mockResolvedValue(workspace);
workspaceUseCases.findUserInTeam.mockResolvedValue({
team,
Expand All @@ -366,16 +397,51 @@ describe('WorkspaceGuard', () => {
);
});

it('When user is deactivated, it should throw', async () => {
const nonMemberUser = newUser();
const team = newWorkspaceTeam();
const workspace = newWorkspace();
const workspaceMember = newWorkspaceUser({
memberId: nonMemberUser.uuid,
workspaceId: workspace.id,
attributes: { deactivated: true },
});

jest.spyOn(reflector, 'get').mockReturnValue({
requiredRole: WorkspaceRole.MEMBER,
accessContext: AccessContext.TEAM,
idSource: 'params',
});

workspaceUseCases.findUserAndWorkspace.mockResolvedValue({
workspace,
workspaceUser: workspaceMember,
});
const context = createMockExecutionContext(nonMemberUser, {
params: { teamId: team.id },
});

await expect(guard.canActivate(context)).rejects.toThrow(
ForbiddenException,
);
});

it('When team workspace does not exist, then throw', async () => {
const nonMemberUser = newUser();
const team = newWorkspaceTeam();
const workspaceMember = newWorkspaceUser();

jest.spyOn(reflector, 'get').mockReturnValue({
requiredRole: WorkspaceRole.MEMBER,
accessContext: AccessContext.TEAM,
idSource: 'params',
});

workspaceUseCases.findUserAndWorkspace.mockResolvedValue({
workspace: null,
workspaceUser: workspaceMember,
});

workspaceUseCases.findById.mockResolvedValue(null);
workspaceUseCases.findUserInTeam.mockResolvedValue({
team,
Expand Down
16 changes: 14 additions & 2 deletions src/modules/workspaces/guards/workspaces.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@ export class WorkspaceGuard implements CanActivate {
role === WorkspaceRole.OWNER && !workspace.isUserOwner(user);
const isWorkspaceNotSetupAndUserNotOwner =
!workspace.isWorkspaceReady() && !workspace.isUserOwner(user);
const isUserDeactivated = workspaceUser?.deactivated;

if (
!isUserPartOfWorkspace ||
isOwnerRoleRequiredButNotMet ||
isWorkspaceNotSetupAndUserNotOwner
isWorkspaceNotSetupAndUserNotOwner ||
isUserDeactivated
) {
Logger.log(
`[WORKSPACES/GUARD]: Access denied. ID: ${workspaceId}, User UUID: ${user.uuid}`,
Expand All @@ -114,12 +116,22 @@ export class WorkspaceGuard implements CanActivate {
throw new NotFoundException('Team not found');
}

const workspace = await this.workspaceUseCases.findById(team.workspaceId);
const { workspace, workspaceUser } =
await this.workspaceUseCases.findUserAndWorkspace(
user.uuid,
team.workspaceId,
);

if (!workspace) {
throw new NotFoundException('Workspace not found');
}

if (!workspaceUser || workspaceUser?.deactivated) {
throw new ForbiddenException(
'You do not have the required access to this workspace.',
);
}

if (workspace.isUserOwner(user)) {
return true;
}
Expand Down
10 changes: 10 additions & 0 deletions src/modules/workspaces/workspaces.usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2084,6 +2084,16 @@ export class WorkspacesUsecases {
return this.teamRepository.getTeamUserAndTeamByTeamId(userUuid, teamId);
}

findUserInWorkspace(
userUuid: User['uuid'],
workspaceId: Workspace['id'],
): Promise<WorkspaceUser | null> {
return this.workspaceRepository.findWorkspaceUser({
workspaceId,
memberId: userUuid,
});
}

async deleteWorkspaceContent(
workspaceId: Workspace['id'],
user: User,
Expand Down

0 comments on commit 1c52d7c

Please sign in to comment.