- Implemented OAuthClientsController for CRUD operations on OAuth clients. - Added SecurityController to manage security settings. - Created SubscriptionsController for handling subscriptions with export functionality. - Developed TenantsController for tenant management including create, edit, and delete operations. - Added views for each controller to facilitate user interaction. - Introduced layout and shared views for consistent admin UI. - Implemented model classes for handling data in views. - Added validation and error handling in forms.
261 lines
9.5 KiB
Markdown
261 lines
9.5 KiB
Markdown
# Admin / Client UI 拆分工作計劃
|
||
|
||
## 目標
|
||
|
||
- 在同一個 `MemberCenter.Web` 專案中,將會員端與管理端 UI 明確分區。
|
||
- 保持單一登入入口與單一帳號系統。
|
||
- 讓具有 `admin` 權限的帳號同時可使用會員功能與管理功能。
|
||
- 將目前偏向後台的共用介面,調整為 client-first 的會員中心體驗。
|
||
- 補齊會員註冊、Google 第三方登入與訂閱資料銜接流程。
|
||
|
||
## 已確認決策
|
||
|
||
### 帳號與登入
|
||
|
||
- `Admin` 與 `Client` 共用同一個登入入口。
|
||
- `Admin` 帳號同時也是會員帳號,可使用會員介面功能。
|
||
- 不拆成兩套認證系統,不建立獨立 admin login。
|
||
|
||
### UI 與導覽
|
||
|
||
- 會員端為主介面。
|
||
- 功能選單採分組方式呈現。
|
||
- 一般會員只看到會員功能。
|
||
- 具有 `admin` role 的帳號,額外看到 `Admin` 功能分類。
|
||
- `Admin` 分類展開後顯示管理功能連結。
|
||
- 目前先以 `admin` role 做整包顯示,不先做細權限切分。
|
||
|
||
### 未授權存取
|
||
|
||
- 非 admin 使用者存取 `/admin/*` 時,回應 `404`。
|
||
- 不使用 `403` 頁面暴露後台存在。
|
||
|
||
## 目標範圍
|
||
|
||
### 本次要做
|
||
|
||
- 調整 `MemberCenter.Web` 路由與結構,將管理端移入 `Areas/Admin`。
|
||
- 將現有共用 layout 改為 client-first 導覽。
|
||
- 將 admin 功能從全站共用導覽中抽離,改成 role-based 顯示。
|
||
- 建立 admin 路由未授權時回 `404` 的處理方式。
|
||
- 補上會員註冊、第三方登入與訂閱綁定的工作規劃。
|
||
|
||
### 本次不做
|
||
|
||
- 細粒度權限模型,例如依功能模組拆 `tenant.read`、`audit.read`。
|
||
- 獨立的 `AdminWeb` / `ClientWeb` 專案拆分。
|
||
- 大幅重做視覺設計。
|
||
- API 權限模型重構。
|
||
- 註冊確認信寄送實作。
|
||
|
||
## 實作策略
|
||
|
||
### 策略原則
|
||
|
||
- 先切 UI 邊界,再保留既有 Identity 與 role policy。
|
||
- 先做低風險結構重整,不同時引入細權限與大幅 UI redesign。
|
||
- 保持既有 URL 慣例,避免不必要的 route breakage。
|
||
|
||
### 預期結構
|
||
|
||
```text
|
||
src/MemberCenter.Web/
|
||
├── Areas/
|
||
│ └── Admin/
|
||
│ ├── Controllers/
|
||
│ └── Views/
|
||
├── Controllers/ # client only
|
||
├── Views/
|
||
│ ├── Shared/
|
||
│ │ ├── _Layout.cshtml # client-first layout
|
||
│ │ └── ...
|
||
│ └── ...
|
||
```
|
||
|
||
## 分階段計劃
|
||
|
||
### Phase 0: 會員註冊與帳號銜接規格補齊
|
||
|
||
狀態:已完成
|
||
|
||
目標:先將會員建立、第三方登入與訂閱資料綁定的規則固定,避免後續 UI 與 auth 重構互相衝突。
|
||
|
||
#### 需求規則
|
||
|
||
- 會員帳號以 `email` 為主要識別。
|
||
- `UserName` 強制等於 `Email`。
|
||
- 不提供獨立 username。
|
||
- 本地註冊完成後,帳號標記為未認證。
|
||
- 本階段先不寄送確認信。
|
||
- 未認證帳號仍可登入。
|
||
- 後續功能完整後,未認證帳號將可被限制部分功能;本階段先保留此狀態與擴充空間。
|
||
- 支援 Google 作為第一個第三方登入/註冊 provider。
|
||
- Google 第一次登入時,若系統已存在相同 email 的本地帳號,直接 auto-link。
|
||
- Google 回傳 email 即使未驗證,仍允許建立帳號或連接既有帳號。
|
||
- 使用者若先以本地帳號註冊,之後再以 Google 同 email 登入,應連接到同一個帳號,不建立第二個 user。
|
||
- 註冊成功後,若系統中已有相同 email 的訂閱資料,需將相關 `newsletter_subscriptions.user_id` 補上。
|
||
- 訂閱綁定時必須保留既有訂閱狀態與偏好,不可覆蓋。
|
||
- 訂閱綁定完成後需補一筆 audit log。
|
||
- 後續若導入事件,保留發送 `subscription.linked_to_user` 的擴充空間。
|
||
|
||
#### 子工作
|
||
|
||
- 已完成:定義本地註冊後的帳號狀態與登入規則。
|
||
- 已完成:定義 Google external login / register / auto-link 流程。
|
||
- 已完成:定義訂閱資料綁定與 audit log 寫入時機。
|
||
- 已完成:將上述規則同步反映到目前的 Web / API 實作階段。
|
||
- 已完成:`subscription.linked_to_user` 事件發送。
|
||
- 註記:未認證帳號的功能限制屬後續能力擴充,不阻擋本 phase 完成。
|
||
- 註記:Google 實際整合驗證仍需提供 Google OAuth 設定,屬外部驗證條件,不阻擋本 phase 完成。
|
||
|
||
完成條件:
|
||
|
||
- 註冊、Google 登入、同 email 帳號連接、訂閱綁定規則均有明確定義。
|
||
- 後續 Phase 1 之後的 UI 與 auth 重構可直接依規則實作。
|
||
|
||
### Phase 1: Route 與目錄切分
|
||
|
||
狀態:已完成
|
||
|
||
目標:先建立清楚的 UI 邊界。
|
||
|
||
- 將現有 `Controllers/Admin/*` 移入 `Areas/Admin/Controllers/*`。
|
||
- 將現有 `Views/Admin/*` 移入 `Areas/Admin/Views/*`。
|
||
- 調整 route 設定,讓 `/admin/*` 由 area route 處理。
|
||
- 確認既有 admin URL 可維持不變。
|
||
|
||
完成條件:
|
||
|
||
- 所有 admin 頁面由 `Areas/Admin` 提供。
|
||
- 會員端 controller 不再與 admin controller 混在同一層。
|
||
|
||
### Phase 2: Layout 與導覽切分
|
||
|
||
狀態:已完成
|
||
|
||
目標:把 UI 改成 client-first,不再全站露出後台功能。
|
||
|
||
- 重構共用 layout,移除固定顯示的 admin 連結。
|
||
- 建立 client-first 功能選單。
|
||
- 若使用者具 `admin` role,顯示 `Admin` 功能分類。
|
||
- `Admin` 分類底下先列出既有管理功能:
|
||
- Tenants
|
||
- Newsletter Lists
|
||
- Subscriptions
|
||
- OAuth Clients
|
||
- Audit Logs
|
||
- Security
|
||
- Blacklist
|
||
|
||
完成條件:
|
||
|
||
- 一般會員不會在主選單看到 admin 連結。
|
||
- admin 使用者可從同一套主介面展開進入管理功能。
|
||
|
||
### Phase 3: Admin 畫面容器整理
|
||
|
||
狀態:已完成
|
||
|
||
目標:讓進入 admin 區後有明確上下文。
|
||
|
||
- 規劃 admin area 是否使用獨立 layout。
|
||
- 若使用獨立 layout,保留回會員區入口。
|
||
- 若先共用 layout,至少在 admin 頁面標示目前位於管理區。
|
||
|
||
建議:
|
||
|
||
- 第一版可先採用共用主殼 + admin 區塊標示。
|
||
- 若後續 admin 功能持續增長,再抽 `_AdminLayout`。
|
||
|
||
目前進度:
|
||
|
||
- 已完成:獨立 `Admin` area layout。
|
||
- 已完成:保留回會員區入口。
|
||
- 已完成:admin shell 基礎結構整理(top bar、side nav、active state、區域標示)。
|
||
- 已完成:補上可替換的基礎樣式 hooks,避免後續設計重做時需要拆 route 或 view 結構。
|
||
- 註記:後續若需進一步整理 admin/client 的整體體驗、內容層級、表格與表單版型,視為 UI/UX refinement,不阻擋本 phase 完成。
|
||
|
||
完成條件:
|
||
|
||
- 使用者進入 admin 頁面時,有清楚的區域辨識。
|
||
|
||
### Phase 4: 未授權存取改為 404
|
||
|
||
狀態:已完成
|
||
|
||
目標:保留授權檢查,同時隱藏 admin surface。
|
||
|
||
- 保留 `[Authorize(Policy = "Admin")]`。
|
||
- 增加 admin 未授權時的統一處理,避免顯示預設 `403`。
|
||
- 確認未登入與已登入但非 admin 的行為符合預期。
|
||
|
||
已定案:
|
||
|
||
- 未登入進 `/admin/*`:直接回 `404`
|
||
- 已登入但非 admin 進 `/admin/*`:直接回 `404`
|
||
|
||
目前進度:
|
||
|
||
- 已完成:保留 `[Authorize(Policy = "Admin")]`。
|
||
- 已完成:admin 未授權時不顯示預設 `403`,改為 `404`。
|
||
- 已完成:目前實作上,未登入與非 admin 存取 `/admin/*` 均回 `404`。
|
||
- 已完成:將「未登入也回 `404`」正式定案並同步到工作計劃。
|
||
|
||
### Phase 5: 驗證與文件更新
|
||
|
||
狀態:已完成
|
||
|
||
目標:確保重構後行為可驗證、文件一致。
|
||
|
||
- 驗證會員端主要頁面仍可正常使用。
|
||
- 驗證 admin 帳號可以:
|
||
- 使用會員功能
|
||
- 看見 `Admin` 選單
|
||
- 進入 admin 各頁
|
||
- 驗證非 admin 帳號無法看見 admin 選單,且直接進 admin URL 會得到 `404`
|
||
- 更新 README / UI 文件中的 web 結構描述
|
||
|
||
目前進度:
|
||
|
||
- 已完成:`dotnet build MemberCenter.sln -m:1`
|
||
- 已完成:會員端主要頁面可用性驗證(首頁 / login / register)。
|
||
- 已完成:admin 帳號操作驗證(可登入、可進 member profile、可進 admin route)。
|
||
- 已完成:一般會員登入驗證(可登入、可進 profile、首頁不顯示 admin 群組)。
|
||
- 已完成:非 admin / 未登入情境驗證(匿名打 `/admin/*` 回 `404`)。
|
||
- 已完成:計劃文件、README、UI / Flow / Use Case / Design / OpenAPI 相關文件更新。
|
||
- 註記:Google 真實 round-trip 驗證需提供 Google OAuth 設定,屬外部條件,不阻擋本 phase 完成。
|
||
|
||
## 影響檔案預估
|
||
|
||
- `src/MemberCenter.Web/Program.cs`
|
||
- `src/MemberCenter.Web/Views/Shared/_Layout.cshtml`
|
||
- `src/MemberCenter.Web/Controllers/Admin/*`
|
||
- `src/MemberCenter.Web/Views/Admin/*`
|
||
- 新增 `src/MemberCenter.Web/Areas/Admin/...`
|
||
- 視需要更新 `docs/UI.md`
|
||
|
||
## 風險與注意事項
|
||
|
||
- Area 導入後,view 路徑與 route mapping 容易有小錯誤,需要逐頁驗證。
|
||
- 若直接共用同一個 layout,需避免 client 與 admin 的語意混亂。
|
||
- `404` 偽裝策略要搭配真正的 authorization,不能只靠 route 隱藏。
|
||
- 若未登入也直接回 `404`,可能會讓合法 admin 使用者失去登入引導;這點需明確決策。
|
||
|
||
## 建議執行順序
|
||
|
||
1. 先完成 Phase 0,確認註冊、Google 登入與訂閱綁定規則。
|
||
2. 再完成 Phase 1,做純結構重整。
|
||
3. 接著做 Phase 2,修正選單與角色顯示。
|
||
4. 然後決定 Phase 3 要共用 layout 還是抽 admin layout。
|
||
5. 再做 Phase 4,補齊 `404` 授權行為。
|
||
6. 最後做 Phase 5 的驗證與文件更新。
|
||
|
||
## 本次文件用途
|
||
|
||
這份計劃作為後續逐步實作的工作底稿。後續每一步都應以「單一階段可驗證完成」為原則,避免一次改太多導致 routing、授權與 UI 問題混在一起。
|
||
|
||
## 目前總結
|
||
|
||
- 已完成:Phase 0、Phase 1、Phase 2、Phase 3、Phase 4、Phase 5
|
||
- 部分完成:Phase 5
|