fix(security): [Developer] #267 AdminUserController GET 4종에 requireAdmin() 추가
CRITICAL: listUsers, userFavorites, userReviews, userMemos 4개 GET이 인증만 요구하고 admin 검사가 없어, 일반 사용자 토큰으로 전체 사용자 목록 및 타인 활동 조회 가능했음. 각 메서드 첫 줄에 AuthUtil.requireAdmin() 호출 추가 → non-admin은 403. 함께 커밋(이전 미커밋 작업): - Logger 등록 (감사 로그용) - AuthUtil/Logger/HttpStatus/ResponseStatusException import 정리 - updateAdmin: 자기 자신 admin 변경 차단 + 감사 로그 (이미 동작 중이던 변경이나 git 미커밋 상태였음) 문서: - 설계서 §3 인수조건에 권한 강제 항목 추가, 상태 Draft → Approved - CHANGELOG.md 2026-06-15 핫픽스 항목 추가 검증: - Anonymous GET /api/admin/users → 403 ✓ - Bad-token GET /api/admin/users → 403 ✓ - 백엔드 빌드 성공, tasteby-api 재시작 완료 Refs: #267
This commit is contained in:
@@ -3,10 +3,15 @@ package com.tasteby.controller;
|
||||
import com.tasteby.domain.Memo;
|
||||
import com.tasteby.domain.Restaurant;
|
||||
import com.tasteby.domain.Review;
|
||||
import com.tasteby.security.AuthUtil;
|
||||
import com.tasteby.service.MemoService;
|
||||
import com.tasteby.service.ReviewService;
|
||||
import com.tasteby.service.UserService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -15,6 +20,7 @@ import java.util.Map;
|
||||
@RequestMapping("/api/admin/users")
|
||||
public class AdminUserController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AdminUserController.class);
|
||||
private final UserService userService;
|
||||
private final ReviewService reviewService;
|
||||
private final MemoService memoService;
|
||||
@@ -29,6 +35,7 @@ public class AdminUserController {
|
||||
public Map<String, Object> listUsers(
|
||||
@RequestParam(defaultValue = "50") int limit,
|
||||
@RequestParam(defaultValue = "0") int offset) {
|
||||
AuthUtil.requireAdmin();
|
||||
var users = userService.findAllWithCounts(limit, offset);
|
||||
int total = userService.countAll();
|
||||
return Map.of("users", users, "total", total);
|
||||
@@ -36,16 +43,32 @@ public class AdminUserController {
|
||||
|
||||
@GetMapping("/{userId}/favorites")
|
||||
public List<Restaurant> userFavorites(@PathVariable String userId) {
|
||||
AuthUtil.requireAdmin();
|
||||
return reviewService.getUserFavorites(userId);
|
||||
}
|
||||
|
||||
@GetMapping("/{userId}/reviews")
|
||||
public List<Review> userReviews(@PathVariable String userId) {
|
||||
AuthUtil.requireAdmin();
|
||||
return reviewService.findByUser(userId, 100, 0);
|
||||
}
|
||||
|
||||
@GetMapping("/{userId}/memos")
|
||||
public List<Memo> userMemos(@PathVariable String userId) {
|
||||
AuthUtil.requireAdmin();
|
||||
return memoService.findByUser(userId);
|
||||
}
|
||||
|
||||
@PatchMapping("/{userId}/admin")
|
||||
public Map<String, Object> updateAdmin(@PathVariable String userId, @RequestBody Map<String, Boolean> body) {
|
||||
var currentUser = AuthUtil.requireAdmin();
|
||||
if (userId.equals(currentUser.getSubject())) {
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.BAD_REQUEST, "자기 자신의 관리자 권한은 변경할 수 없습니다");
|
||||
}
|
||||
boolean admin = Boolean.TRUE.equals(body.get("admin"));
|
||||
userService.updateAdmin(userId, admin);
|
||||
log.info("[ADMIN] User {} set admin={} for user {}", currentUser.getSubject(), admin, userId);
|
||||
return Map.of("success", true, "user_id", userId, "is_admin", admin);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user