Skip to content

Commit 020691e

Browse files
feat: 워크스페이스 권한 업데이트, 권한 체크 구현
1 parent d9c7d16 commit 020691e

File tree

3 files changed

+74
-30
lines changed

3 files changed

+74
-30
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
import { IsIn, IsString } from 'class-validator';
3+
4+
export class GetWorkspaceAccessResponseDto {
5+
@ApiProperty({
6+
example: 'OO 생성에 성공했습니다.',
7+
description: 'api 요청 결과 메시지',
8+
})
9+
@IsString()
10+
message: string;
11+
12+
@ApiProperty({
13+
example: 'owner',
14+
description:
15+
'워크스페이스에서의 사용자의 권한 (owner, guest, public, forbidden)',
16+
})
17+
@IsIn(['owner', 'guest', 'public', 'forbidden'])
18+
acccess: 'owner' | 'guest' | 'public' | 'forbidden';
19+
}

apps/backend/src/workspace/workspace.controller.ts

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ import { CreateWorkspaceDto } from './dtos/createWorkspace.dto';
1919
import { CreateWorkspaceResponseDto } from './dtos/createWorkspaceResponse.dto';
2020
import { GetUserWorkspacesResponseDto } from './dtos/getUserWorkspacesResponse.dto';
2121
import { CreateWorkspaceInviteUrlDto } from './dtos/createWorkspaceInviteUrl.dto';
22+
import { GetWorkspaceAccessResponseDto } from './dtos/getWorkspaceAccessResponse.dto';
2223

2324
export enum WorkspaceResponseMessage {
2425
WORKSPACE_CREATED = '워크스페이스를 생성했습니다.',
2526
WORKSPACE_DELETED = '워크스페이스를 삭제했습니다.',
2627
WORKSPACES_RETURNED = '사용자가 참여하고 있는 모든 워크스페이스들을 가져왔습니다.',
2728
WORKSPACE_INVITED = '워크스페이스 게스트 초대 링크가 생성되었습니다.',
2829
WORKSPACE_JOINED = '워크스페이스에 게스트로 등록되었습니다.',
30+
WORKSPACE_ACCESS_CHECKED = '워크스페이스에 대한 사용자의 권한을 확인하였습니다.',
2931
}
3032

3133
@Controller('workspace')
@@ -117,7 +119,7 @@ export class WorkspaceController {
117119
type: MessageResponseDto,
118120
})
119121
@ApiOperation({
120-
summary: '워크스페이스초대 링크에 접속해 권한을 업데이트합니다.',
122+
summary: '워크스페이스 초대 링크에 접속해 권한을 업데이트합니다.',
121123
})
122124
@Get('/join')
123125
@UseGuards(JwtAuthGuard) // 로그인 인증
@@ -129,40 +131,24 @@ export class WorkspaceController {
129131
return { message: WorkspaceResponseMessage.WORKSPACE_INVITED };
130132
}
131133

132-
@ApiOperation({
133-
summary: '특정 워크스페이스에 대한 사용자의 권한을 확인합니다.',
134-
})
135134
@ApiResponse({
136-
status: HttpStatus.OK,
137-
description: '사용자의 권한이 확인되었습니다.',
138-
schema: {
139-
example: {
140-
role: 'owner',
141-
},
142-
},
135+
type: GetWorkspaceAccessResponseDto,
143136
})
144-
@Get('/check-role')
137+
@ApiOperation({
138+
summary: '워크스페이스에 대한 사용자의 권한을 확인합니다.',
139+
})
140+
@Get('/:workspaceId/:userId')
145141
@HttpCode(HttpStatus.OK)
146-
async checkUserRole(
147-
@Request() req,
148-
@Query('workspaceId') workspaceId: string,
149-
): Promise<{ role: 'owner' | 'guest' }> {
150-
const userId = req.user.sub; // 현재 인증된 사용자의 ID
151-
152-
const role = await this.workspaceService.getUserRoleInWorkspace(
153-
userId,
154-
workspaceId,
155-
);
156-
157-
if (!role) {
158-
throw new ForbiddenException(
159-
'해당 워크스페이스에 접근할 권한이 없습니다.',
160-
);
161-
}
142+
async checkWorkspaceAccess(
143+
@Param('workspaceId') workspaceId: string,
144+
@Param('userId') userId: string | 'null', // 로그인되지 않은 경우 'null'
145+
) {
146+
// workspaceId, userId 둘 다 snowflakeId
147+
const access = await this.workspaceService.checkAccess(userId, workspaceId);
162148

163149
return {
164-
workspaceId,
165-
role,
150+
message: WorkspaceResponseMessage.WORKSPACE_ACCESS_CHECKED,
151+
access,
166152
};
167153
}
168154
}

apps/backend/src/workspace/workspace.service.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ export class WorkspaceService {
134134
});
135135

136136
// 이미 워크스페이스에 등록된 경우
137+
// TODO: 워크스페이스 관련 에러 구현
137138
if (existingRole) {
138139
throw new Error('이미 워크스페이스에 가입된 사용자입니다.');
139140
}
@@ -145,4 +146,42 @@ export class WorkspaceService {
145146
role: role,
146147
});
147148
}
149+
150+
async checkAccess(
151+
userId: string | null,
152+
workspaceId: string,
153+
): Promise<'public' | 'owner' | 'guest' | 'forbidden'> {
154+
// workspace가 존재하는지 확인
155+
const workspace = await this.workspaceRepository.findOne({
156+
where: { snowflakeId: workspaceId },
157+
});
158+
159+
if (!workspace) {
160+
throw new WorkspaceNotFoundException();
161+
}
162+
163+
if (workspace.visibility === 'public') {
164+
return 'public';
165+
}
166+
167+
if (userId !== null) {
168+
// user이 존재하는지 확인
169+
const user = await this.userRepository.findOneBy({
170+
snowflakeId: userId,
171+
});
172+
if (!user) {
173+
throw new UserNotFoundException();
174+
}
175+
// workspace + user => role 있는지 확인
176+
const role = await this.roleRepository.findOne({
177+
where: { userId: user.id, workspaceId: workspace.id },
178+
});
179+
180+
if (role) {
181+
return role.role as 'owner' | 'guest';
182+
}
183+
}
184+
185+
return 'forbidden';
186+
}
148187
}

0 commit comments

Comments
 (0)