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:
parent
8719d110f3
commit
f7256a0c56
@ -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) {
|
public KintexPrincipal requireRole(KintexPrincipal principal, String eventId, EventRole... allowed) {
|
||||||
requireEventAccess(principal, eventId);
|
requireEventAccess(principal, eventId);
|
||||||
|
if (principal.isAdmin()) {
|
||||||
|
return principal;
|
||||||
|
}
|
||||||
EventRole role = principal.roleFor(eventId);
|
EventRole role = principal.roleFor(eventId);
|
||||||
Set<EventRole> allowedSet = Set.of(allowed);
|
Set<EventRole> allowedSet = Set.of(allowed);
|
||||||
if (role == null || !allowedSet.contains(role)) {
|
if (role == null || !allowedSet.contains(role)) {
|
||||||
|
|||||||
@ -42,12 +42,20 @@ public record KintexPrincipal(
|
|||||||
return "ADMIN".equalsIgnoreCase(roleCode);
|
return "ADMIN".equalsIgnoreCase(roleCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 해당 행사에서 사용자의 역할(없으면 null). 홀매니저·ADMIN은 항상 HALL_MANAGER로 간주. */
|
/**
|
||||||
|
* 해당 행사에서 사용자의 역할(없으면 null). 명시적 행사 멤버십 역할이 있으면 그것이 우선 —
|
||||||
|
* 홀매니저/ADMIN 플래그가 실제 멤버 역할(예: ORGANIZER)을 가려 역할 제한 엔드포인트에서
|
||||||
|
* 403이 나던 결함 수정(2026-07-14). 멤버십이 없을 때만 HALL_MANAGER로 간주.
|
||||||
|
*/
|
||||||
public EventRole roleFor(String eventId) {
|
public EventRole roleFor(String eventId) {
|
||||||
|
EventRole member = eventRoles == null ? null : eventRoles.get(eventId);
|
||||||
|
if (member != null) {
|
||||||
|
return member;
|
||||||
|
}
|
||||||
if (hallManager || isAdmin()) {
|
if (hallManager || isAdmin()) {
|
||||||
return EventRole.HALL_MANAGER;
|
return EventRole.HALL_MANAGER;
|
||||||
}
|
}
|
||||||
return eventRoles == null ? null : eventRoles.get(eventId);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasAccess(String eventId) {
|
public boolean hasAccess(String eventId) {
|
||||||
|
|||||||
@ -114,10 +114,10 @@ public class HallAssignController {
|
|||||||
return ApiResponse.ok(service.quote(req));
|
return ApiResponse.ok(service.quote(req));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 홀 배정 변경 권한 — 킨텍스 내부 홀매니저만(§2 최종 배정 확정은 킨텍스 내부 의사결정). */
|
/** 홀 배정 변경 권한 — 킨텍스 내부 홀매니저 + 전역 ADMIN(전권, 2026-07-14 소유자 방침). */
|
||||||
private void requireHallManager(KintexPrincipal principal) {
|
private void requireHallManager(KintexPrincipal principal) {
|
||||||
guard.require(principal);
|
guard.require(principal);
|
||||||
if (!principal.hallManager()) {
|
if (!principal.hallManager() && !principal.isAdmin()) {
|
||||||
throw new ApiException(ErrorCode.FORBIDDEN, "홀 배정은 킨텍스 홀매니저만 변경할 수 있습니다.");
|
throw new ApiException(ErrorCode.FORBIDDEN, "홀 배정은 킨텍스 홀매니저만 변경할 수 있습니다.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user