--- Dev AdminUIRoleMenu
+++ Dev AdminUIRoleMenu
@@ -1,46 +1,50 @@
= [Dev] Admin UI 권한별 메뉴
전체Admin과 SiteAdmin의 권한에 따라 `/Admin` 네비게이션 메뉴를 다르게 표시한다.
== 네비게이션 구조
[[[#!text
+[전체 관리] ← 전체Admin만 표시. Sites 블록보다 위에 온다
+ Dashboard
+ User
+ RecentChanges
+ AccessLog
+ Crawler Cache
+ S3 Browser
+ API Keys
+ Nickname Requests
+
[Sites]
- ▼ AhaWiki (#1) ← 현재 사이트: 자동 펼침 + 강조 표시
- Meta목록
+ ▼ AhaWiki (#1) ← 현재 사이트(request.host): 자동 펼침. 강조(filled)는 URL 의 site seq 를 따른다
Config
+ Page
Cache
Permission
- AccessLog
+ AccessLog ← 전체Admin만 표시
SiteAdmins ← 전체Admin만 표시
▶ OtherSite (#2) ← 전체Admin만 표시 (접힌 상태)
-
-[전체 관리] ← 전체Admin만 표시
- Dashboard
- User
- RecentChange
- AccessLog
- Cache (Crawler)
- S3 Browser
]]]
+이 그림은 `app/assets/js/admin/navigation.jsx` 를 옮긴 것이다. 항목을 더하거나 이름을 바꾸면 여기도 바꾼다 — 2026-05-24 이후 넉 달 동안 이 그림은 없어진 "Meta목록" 을 그리고 있었고, 나중에 붙은 API Keys·Nickname Requests 는 없었다.
+
* 현재 사이트는 `request.host`로 판별 (`/api/me`의 `currentSiteSeq` 활용)
* SiteAdmin에게는 담당 사이트만 표시, 전체Admin은 전체 표시
== 구현 결과
=== Backend
- * `GET /api/me` 추가: `seq`, `nickname`, `isAdmin`, `siteAdminSeqs`, `currentSiteSeq` 반환
+ * `GET /api/me` 추가: `loggedIn`, `seq`, `nickname`, `loginEmail`, `profileImageUrl`, `isAdmin`, `siteAdminSeqs`, `currentSiteSeq` 반환. 로그아웃 상태면 `{"loggedIn": false}` 만 돌려주고, 내비게이션은 `loggedIn` 이 참일 때만 site 목록을 가져온다
* `SiteAdmin.selectByUser(userSeq)` 추가
* `/api/Admin/Sites`: SiteAdmin은 담당 사이트만 반환하도록 수정
* `Admin.scala`: `isAdmin || isSiteAdmin` 기준으로 접근 허용
=== Frontend
* `AdminLayout`에서 `me` fetch 후 `Navigation`에는 prop으로, 각 페이지에는 `AdminContext.Provider`로 전달
* `SiteNavItem` 컴포넌트 분리로 사이트별 서브메뉴 재사용
- * `me.isAdmin`이 false이면 전체Admin 전용 페이지 접근 시 접근 불가 메시지 표시
+ * `me.isAdmin`이 false 이면 Dashboard 는 담당 사이트 목록만 보여준다. 전체Admin 전용 페이지는 프론트에서 막지 않는다 — API 의 403 이 `HTTP 403` 오류 문구로 보이거나(S3 Browser·API Keys·Nickname Requests) 빈 화면으로 남는다(User·RecentChanges·AccessLog·Crawler Cache). 2026-05-24 에 넣었던 접근 불가 메시지는 같은 날 뺐다
* Me API 로딩 중 네비게이션 skeleton 표시
== 설계 결정
실제 보안은 API 레벨(`isAdmin` / `isSiteAdmin`)에서 처리한다. 프론트 메뉴 분기는 UX 목적으로만 사용한다.