Skip to content

Commit 46ffbe9

Browse files
authored
Merge pull request #236 from CSE-Shaco/develop
feat(user-admin): 사용자 삭제 메서드 추가 (Controller 및 Service 계층)
2 parents e850fd1 + d77532f commit 46ffbe9

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

src/main/java/inha/gdgoc/domain/user/controller/UserAdminController.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,12 @@ public ResponseEntity<ApiResponse<Void, Void>> updateUserRole(@AuthenticationPri
5353
userAdminService.updateUserRoleWithRules(me, userId, req.role());
5454
return ResponseEntity.ok(ApiResponse.ok("USER_ROLE_UPDATED"));
5555
}
56+
57+
@Operation(summary = "사용자 삭제", security = {@SecurityRequirement(name = "BearerAuth")})
58+
@PreAuthorize("hasAnyRole('LEAD', 'ORGANIZER', 'ADMIN')")
59+
@DeleteMapping("/{userId}")
60+
public ResponseEntity<ApiResponse<Void, Void>> deleteUser(@AuthenticationPrincipal CustomUserDetails me, @PathVariable Long userId) {
61+
userAdminService.deleteUserWithRules(me, userId);
62+
return ResponseEntity.ok(ApiResponse.ok("USER_DELETED"));
63+
}
5664
}

src/main/java/inha/gdgoc/domain/user/service/UserAdminService.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,63 @@ public void updateUserRoleWithRules(CustomUserDetails me, Long targetUserId, Use
164164
userRepository.save(target);
165165
}
166166

167+
@Transactional
168+
public void deleteUserWithRules(CustomUserDetails me, Long targetUserId) {
169+
User editor = userRepository.findById(me.getUserId())
170+
.orElseThrow(() -> new BusinessException(GlobalErrorCode.UNAUTHORIZED_USER));
171+
172+
User target = userRepository.findById(targetUserId)
173+
.orElseThrow(() -> new BusinessException(GlobalErrorCode.RESOURCE_NOT_FOUND));
174+
175+
// 자기 자신 삭제 금지
176+
if (Objects.equals(editor.getId(), target.getId())) {
177+
throw new BusinessException(GlobalErrorCode.FORBIDDEN_USER, "자기 자신은 삭제할 수 없습니다.");
178+
}
179+
180+
UserRole editorRole = editor.getUserRole();
181+
TeamType editorTeam = editor.getTeam();
182+
183+
UserRole targetRole = target.getUserRole();
184+
TeamType targetTeam = target.getTeam();
185+
186+
// 공통: '나'는 대상의 현재 role보다 "엄격히" 높아야 함
187+
if (!(editorRole.rank() > targetRole.rank())) {
188+
throw new BusinessException(GlobalErrorCode.FORBIDDEN_USER, "동급/상급 사용자는 삭제할 수 없습니다.");
189+
}
190+
191+
switch (editorRole) {
192+
case ADMIN -> {
193+
// ADMIN: 모두 삭제 가능(단, 자기 자신은 위에서 금지)
194+
// 추가 보호가 필요하면 여기서 ADMIN→ADMIN 삭제 금지도 가능
195+
}
196+
case ORGANIZER -> {
197+
// ORGANIZER: ADMIN 삭제 불가(공통 검사로 이미 걸러짐). 그 외 삭제 가능
198+
if (targetRole == UserRole.ADMIN) {
199+
throw new BusinessException(GlobalErrorCode.FORBIDDEN_USER, "ADMIN 사용자는 삭제할 수 없습니다.");
200+
}
201+
}
202+
case LEAD -> {
203+
// LEAD: MEMBER/CORE만 삭제 가능
204+
if (!(targetRole == UserRole.MEMBER || targetRole == UserRole.CORE)) {
205+
throw new BusinessException(GlobalErrorCode.FORBIDDEN_USER, "LEAD는 MEMBER/CORE만 삭제할 수 있습니다.");
206+
}
207+
208+
// HR-LEAD 특례: 본인 제외 누구든 팀 무관 삭제 가능
209+
if (editorTeam == TeamType.HR) {
210+
// 자기 자신은 위에서 이미 금지
211+
} else {
212+
// 일반 LEAD: 같은 팀만 삭제 가능
213+
if (editorTeam == null || targetTeam != editorTeam) {
214+
throw new BusinessException(GlobalErrorCode.FORBIDDEN_USER, "다른 팀 사용자는 삭제할 수 없습니다.");
215+
}
216+
}
217+
}
218+
default -> throw new BusinessException(GlobalErrorCode.FORBIDDEN_USER);
219+
}
220+
221+
userRepository.delete(target);
222+
}
223+
167224
/**
168225
* 실제 반영 (역할 변경 후 역할 정책에 따라 팀도 정리)
169226
*/

0 commit comments

Comments
 (0)