forked from alterminal/alterminal
3.0 KiB
3.0 KiB
實作 create-account CLI 子指令
背景
alterminal(Go + chi + GORM + PostgreSQL 的 OIDC 服務)目前 User 模型(user.go)與 argon2id 密碼雜湊已完成,但沒有任何建立帳號的入口。要在二進位檔加入 CLI 子指令:./alterminal create-account ...,不帶參數時行為不變(啟動 HTTP 伺服器)。
指令介面
alterminal create-account -username alice -email alice@example.com [-name "Alice"] [-email-verified] [-password secret]
-username(必填):登入帳號,限制^[A-Za-z0-9._-]+$、長度 ≤ 64-email(必填):以net/mail.ParseAddress驗證格式,長度 ≤ 255-name(選填):顯示名稱,長度 ≤ 255-email-verified(選填,預設 false):設定 OIDCemail_verifiedclaim-password(選填):密碼,最小長度 8(OWASP 建議)。省略時以互動式無回顯提示輸入兩次(用golang.org/x/term.ReadPassword),兩次不一致則報錯;非終端機環境(管線)未提供旗標時直接報錯提示改用-password
檔案變更
- 新增依賴:
go get golang.org/x/term(與既有 x/crypto 同屬 golang.org/x) - main.go:在
main()開頭加入子指令分派——len(os.Args) > 1時交給runCommand(os.Args[1:]),否則照常啟動伺服器;伺服器部分程式碼不動 - 新增
createaccount.go(沿用根目錄、package main的現有風格):runCommand:分派子指令;僅有create-account,未知子指令印用法後離開runCreateAccount(args):flag.NewFlagSet("create-account", flag.ExitOnError)解析旗標,欄位strings.TrimSpacevalidateAccountInput驗證 username/email/name(可單元測試的純函式)resolvePassword:旗標優先,否則互動輸入兩次- 重用
openDB()(含 AutoMigrate,確保資料表存在) - 建立
User並呼叫現有的SetPassword(argon2id) - 重複檢查:先以查詢提供友善錯誤(帳號已存在 / Email 已存在),
db.Create再以gorm.ErrDuplicatedRows兜底(並發保護) - 成功輸出
帳號建立成功:id=1 username=alice email=alice@example.com(不印密碼);失敗經log.Fatal("create-account: ", err)離開(與現有 main 錯誤風格一致)
- 使用者面向訊息採繁體中文(與 README、程式註解一致)
- 新增
createaccount_test.go:仿照user_test.go的 table-driven 純邏輯測試——validateAccountInput各種非法輸入、密碼長度檢查(不含需要 DB 或 TTY 的部分,專案目前無 DB 測試基礎設施) - README.md:在「快速開始」加入「建立使用者帳號」小節(指令、旗標、互動輸入說明);Roadmap 的「使用者系統」僅完成一環,維持未勾選
驗證
go build ./...、go vet ./...、go test ./...- 煙霧測試:若本機 PostgreSQL 有啟動,執行
go run . create-account -username smoke -email smoke@example.com -password testpass1,確認成功輸出、重複執行收到「已存在」錯誤、CheckPassword可驗證;無 DB 時以單元測試與建置結果為準