feat(admin): 슈퍼관리자가 admin 의 개별 프로그램 접근 제어

기존엔 admin 역할이면 모든 모듈을 무조건 전체 ON+잠금이라 슈퍼관리자도
admin 의 특정 프로그램 접근을 끌 수 없었다.

- _normalize_modules: admin 강제 전체 ON 덮어쓰기 제거 → 저장된 칩 상태 존중
- has_module: admin 단축 통과 제거, 슈퍼관리자만 항상 전체. admin 은 칩 따름
- admin.html: admin 칩 잠금 해제(슈퍼관리자만 잠금), 역할→admin 전환 시
  편의상 전체 ON(잠금 아님)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-25 12:15:51 +09:00
parent 4008eee088
commit ef7f76821d
2 changed files with 16 additions and 8 deletions
+6 -4
View File
@@ -82,14 +82,14 @@ class UserStore:
@staticmethod
def _normalize_modules(modules: dict[str, Any] | None, *, is_admin: bool) -> dict[str, bool]:
# 신규(modules 미지정) 사용자는 역할 기본값(admin=전체ON / user=전체OFF)으로 시작.
# 기존 값이 있으면 그대로 존중한다 — admin 이라도 슈퍼관리자가 개별 모듈을
# 끌 수 있다(예전엔 admin 을 무조건 전체 ON 으로 덮어썼다).
base = UserStore._default_modules(is_admin)
if isinstance(modules, dict):
for key in MODULE_KEYS:
if key in modules:
base[key] = bool(modules[key])
if is_admin:
for key in MODULE_KEYS:
base[key] = True
return base
def get(self, email: str) -> dict[str, Any] | None:
@@ -230,7 +230,9 @@ def is_admin(user_rec: dict[str, Any] | None) -> bool:
def has_module(user_rec: dict[str, Any] | None, module: str) -> bool:
if not user_rec:
return False
if is_admin(user_rec):
# 슈퍼관리자는 항상 전체 접근. 일반 admin 은 칩(modules) 상태를 따른다 —
# 슈퍼관리자가 admin 의 개별 프로그램 접근을 제어할 수 있도록.
if user_rec.get("is_super_admin"):
return True
mods = user_rec.get("modules") or {}
if mods.get(module):