member_center/docs/ADMIN_CLIENT_SPLIT_PLAN.md
warrenchen 75e235b8e3 Add admin area controllers and views for managing OAuth clients, security settings, subscriptions, and tenants
- 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.
2026-04-01 17:40:45 +09:00

9.5 KiB
Raw Blame History

Admin / Client UI 拆分工作計劃

目標

  • 在同一個 MemberCenter.Web 專案中,將會員端與管理端 UI 明確分區。
  • 保持單一登入入口與單一帳號系統。
  • 讓具有 admin 權限的帳號同時可使用會員功能與管理功能。
  • 將目前偏向後台的共用介面,調整為 client-first 的會員中心體驗。
  • 補齊會員註冊、Google 第三方登入與訂閱資料銜接流程。

已確認決策

帳號與登入

  • AdminClient 共用同一個登入入口。
  • 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.readaudit.read
  • 獨立的 AdminWeb / ClientWeb 專案拆分。
  • 大幅重做視覺設計。
  • API 權限模型重構。
  • 註冊確認信寄送實作。

實作策略

策略原則

  • 先切 UI 邊界,再保留既有 Identity 與 role policy。
  • 先做低風險結構重整,不同時引入細權限與大幅 UI redesign。
  • 保持既有 URL 慣例,避免不必要的 route breakage。

預期結構

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