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