# 安裝流程(Installer + 管理者帳號) 此文件定義「首次安裝」與「既有環境管理」兩種情境,並以 EF Core Code First 為主。 ## 目標 - 透過 EF Core migrations 建立/更新 DB schema - 建立或更新 superuser 帳號 - 已設定 DB 連線時,可重複執行(不重建 schema) ## 安裝模式 ### A. 首次安裝(Init) 1) 輸入 DB 連線資訊 2) 連線檢查與版本檢查 3) 建立/更新 schema(EF Core migrations) 4) 建立 superuser(預設帳號 admin,可自訂) 5) 建立必要 seed(roles 等) ### B. 既有環境(管理) - 建立額外 superuser - 強制重設 superuser 密碼 - 只執行 migration(差異安裝),不重建 schema ## CLI 指令規格(實作) ### 通用參數 - `--connection-string `: DB 連線字串 - `--appsettings `: 設定檔路徑(讀/寫 `ConnectionStrings:Default`) - `--no-prompt`: 不使用互動輸入(CI/CD) - `--verbose`: 詳細輸出 ### 環境變數(建議用於部署) - `ConnectionStrings__Default`: 主要連線字串(優先) - `MEMBERCENTER_CONNECTION`: 備用連線字串 若在開發環境(`ASPNETCORE_ENVIRONMENT=Development` 或 `DOTNET_ENVIRONMENT=Development`), 可以建立 `.env` 檔案,installer 與 API 會在啟動時讀取(僅限開發環境)。 建議在 `.env` 內加入: ``` ASPNETCORE_ENVIRONMENT=Development ConnectionStrings__Default=Host=localhost;Database=member_center;Username=postgres;Password=postgres Auth__Issuer=http://localhost:7850/ Auth__WebLoginUrl=http://localhost:5080/account/login Auth__AllowedLoginReturnUrlPrefixes=http://localhost:7850/ Auth__AllowedLogoutReturnUrlPrefixes=http://localhost:5243/ Auth__Resources__MemberCenter__Audience=member_center_api Auth__Resources__SendEngine__Audience=send_engine_api Auth__Resources__FileAccess__Audience=file_access_api SendEngine__BaseUrl=http://localhost:6060 SendEngine__WebhookSecret=change-me ``` 相容性說明: - 現行程式已優先使用 resource registry 與目標型態: - `Auth__Resources__MemberCenter__Audience` - `Auth__Resources__SendEngine__Audience` - `Auth__Resources__FileAccess__Audience` - 舊 key 仍保留相容讀取: - `Auth__MemberCenterAudience` - `Auth__SendEngineAudience` - 規劃上將收斂為 DB resource registry;`.env` 僅作為初始 seed / 部署覆寫來源,不應再為每個新服務新增平行 hardcoded key。 - `File Access` 已直接採用 resource registry 形式,不新增第三組硬編碼 audience 判斷。 OIDC / Redirect login 設定說明: - `Auth__WebLoginUrl`: API `/oauth/authorize` 未登入時導向的 Web login URL。 - `Auth__AllowedLoginReturnUrlPrefixes`: Web login 成功後允許 redirect 回去的 URL prefix,通常填 API issuer/base URL。 - `Auth__AllowedLogoutReturnUrlPrefixes`: Web logout 後允許 redirect 的 URL prefix。 - Identity cookie 固定使用 `SameSite=None`、`Secure=Always`、`Path=/`,因此 stage/prod 必須使用 HTTPS。 `SendEngine` 設定說明: - `SendEngine__BaseUrl`: Send Engine API base URL - `SendEngine__WebhookSecret`: 與 Send Engine `Webhook:Secrets:member_center` 一致 - tenant 對應 `X-Client-Id` 改由 DB 管理(Tenant 設定) - 可透過管理 UI 設定,或由 Send Engine 呼叫 `POST /integrations/send-engine/webhook-clients/upsert` 自動回填 測試旗標(TEST-ONLY): - `Testing__DisableSubscriptionDryRunNoDb=true` - 作用:`POST /subscriptions/disable` 完全不做 DB read/write,只寫 log(含預計執行的 DB 動作) - 用途:SES/Send Engine 串接初次測試,避免測試資料污染 - 測試結束請改回 `false` ### 1) `installer init` 用途:首次安裝(含 migrations + seed + superuser) 參數: - `--admin-email `: 預設 `admin@example.com` - `--admin-password `: 預設需互動輸入 - `--admin-display-name `: 可選 - `--force`: 若偵測已初始化,仍強制執行 流程: 1) 解析連線字串(參數或 appsettings) - 若提供 `--connection-string`,會寫入 appsettings - 若 appsettings 中缺少連線字串,會互動式詢問並寫入 - 若設定環境變數,會優先使用環境變數(不寫入 appsettings) 2) 執行 migrations(不 Drop) 3) 建立 roles(superuser, admin, support) 4) 建立使用者(不存在才建立)並加入 `superuser` 角色 5) 寫入安裝鎖定(DB flag: `system_flags` / `installed=true`) ### 2) `installer add-superuser` 用途:新增或提升 superuser 參數: - `--admin-email ` - `--admin-password ` - `--admin-display-name ` 流程: 1) 解析連線字串 2) 建立使用者並指派 `superuser` 角色 相容性: - 舊指令 `installer add-admin` 仍保留為 alias,目前語意等同 `installer add-superuser` ### 3) `installer reset-superuser-password` 用途:重設指定 superuser 密碼 參數: - `--admin-email ` - `--admin-password ` 流程: 1) 解析連線字串 2) 更新密碼(強制) 相容性: - 舊指令 `installer reset-admin-password` 仍保留為 alias,目前語意等同 `installer reset-superuser-password` ### 4) `installer migrate` 用途:只執行 migrations 參數: - `--target `: 指定遷移(可選) 流程: 1) 解析連線字串 2) 執行 migrations(可指定 target) ## 安全注意 - 密碼必須符合強度規則 - 初次安裝完成後,禁用安裝入口或限內網 - 安裝過程需紀錄 audit log ## Docker / 部署建議 - 建議用環境變數提供連線字串(避免重建 container 後設定遺失) - 範例: ```yaml environment: ConnectionStrings__Default: "Host=postgres;Database=member_center;Username=postgres;Password=postgres" ``` - 若仍要用 `appsettings.json`,請用 volume 維持設定檔