fix(auth): global ADMIN has full permissions; member role no longer masked by hm flag

Owner: 'admin은 모든 권한'. requireRole(ORGANIZER)-style endpoints 403'd for
admin because roleFor() returned HALL_MANAGER (hm/ADMIN flag) even when the
user held an explicit ORGANIZER membership.
- EventAccessGuard.requireRole: isAdmin() bypasses the allowed-role set
  (tenant boundary still enforced)
- KintexPrincipal.roleFor: explicit event membership role wins; HALL_MANAGER
  only as fallback
- HallAssignController: ADMIN allowed alongside hall manager

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
zio 2026-07-14 21:52:34 +09:00
parent 8719d110f3
commit f7256a0c56
3 changed files with 20 additions and 5 deletions

View File

@ -58,9 +58,16 @@ public class EventAccessGuard {
}
}
/** 해당 행사에서 허용된 역할 중 하나여야 함. 없으면 403. */
/**
* 해당 행사에서 허용된 역할 하나여야 . 없으면 403.
* 전역 시스템관리자(role_code=ADMIN) 역할 집합과 무관하게 전권(2026-07-14 소유자 방침
* "admin은 모든 권한") 테넌트 경계(assertTenantOwnsEvent) 그대로 적용된다.
*/
public KintexPrincipal requireRole(KintexPrincipal principal, String eventId, EventRole... allowed) {
requireEventAccess(principal, eventId);
if (principal.isAdmin()) {
return principal;
}
EventRole role = principal.roleFor(eventId);
Set<EventRole> allowedSet = Set.of(allowed);
if (role == null || !allowedSet.contains(role)) {

View File

@ -42,12 +42,20 @@ public record KintexPrincipal(
return "ADMIN".equalsIgnoreCase(roleCode);
}
/** 해당 행사에서 사용자의 역할(없으면 null). 홀매니저·ADMIN은 항상 HALL_MANAGER로 간주. */
/**
* 해당 행사에서 사용자의 역할(없으면 null). 명시적 행사 멤버십 역할이 있으면 그것이 우선
* 홀매니저/ADMIN 플래그가 실제 멤버 역할(: ORGANIZER) 가려 역할 제한 엔드포인트에서
* 403이 나던 결함 수정(2026-07-14). 멤버십이 없을 때만 HALL_MANAGER로 간주.
*/
public EventRole roleFor(String eventId) {
EventRole member = eventRoles == null ? null : eventRoles.get(eventId);
if (member != null) {
return member;
}
if (hallManager || isAdmin()) {
return EventRole.HALL_MANAGER;
}
return eventRoles == null ? null : eventRoles.get(eventId);
return null;
}
public boolean hasAccess(String eventId) {

View File

@ -114,10 +114,10 @@ public class HallAssignController {
return ApiResponse.ok(service.quote(req));
}
/** 홀 배정 변경 권한 — 킨텍스 내부 홀매니저만(§2 최종 배정 확정은 킨텍스 내부 의사결정). */
/** 홀 배정 변경 권한 — 킨텍스 내부 홀매니저 + 전역 ADMIN(전권, 2026-07-14 소유자 방침). */
private void requireHallManager(KintexPrincipal principal) {
guard.require(principal);
if (!principal.hallManager()) {
if (!principal.hallManager() && !principal.isAdmin()) {
throw new ApiException(ErrorCode.FORBIDDEN, "홀 배정은 킨텍스 홀매니저만 변경할 수 있습니다.");
}
}