template-monorepo/generate/api/member.api

411 lines
13 KiB
Plaintext
Raw Normal View History

2026-05-20 23:51:22 +00:00
syntax = "v1"
type (
MemberMeData {
TenantID string `json:"tenant_id"`
UID string `json:"uid"`
ZitadelEmail string `json:"zitadel_email,omitempty"`
DisplayName string `json:"display_name,omitempty"`
Avatar string `json:"avatar,omitempty"`
Phone string `json:"phone,omitempty"`
Language string `json:"language,omitempty"`
Currency string `json:"currency,omitempty"`
Status string `json:"status"`
Origin string `json:"origin"`
BusinessEmail string `json:"business_email,omitempty"`
BusinessEmailVerified bool `json:"business_email_verified"`
BusinessPhone string `json:"business_phone,omitempty"`
BusinessPhoneVerified bool `json:"business_phone_verified"`
TOTPEnrolled bool `json:"totp_enrolled"`
CreateAt int64 `json:"create_at"`
UpdateAt int64 `json:"update_at"`
}
UpdateMemberMeReq {
DisplayName string `json:"display_name,optional"` // 顯示名稱(可選)
Avatar string `json:"avatar,optional"` // 頭像 URL可選
Language string `json:"language,optional"` // 語系代碼,如 zh-TW / en可選
Currency string `json:"currency,optional"` // 幣別代碼,如 TWD / USD可選
Phone string `json:"phone,optional"` // 聯絡電話 E.164 格式(可選)
2026-05-20 23:51:22 +00:00
}
VerificationStartReq {
Target string `json:"target"` // 驗證目標email 地址或 E.164 手機號(依端點而定)
2026-05-20 23:51:22 +00:00
}
VerificationStartData {
ChallengeID string `json:"challenge_id"`
ExpiresIn int `json:"expires_in"`
}
VerificationConfirmReq {
ChallengeID string `json:"challenge_id"` // 驗證流程的 OTP challenge ID由 /start 端點回傳)
Code string `json:"code"` // 6 位數 OTP 驗證碼
2026-05-20 23:51:22 +00:00
}
TOTPStatusData {
Enrolled bool `json:"enrolled"`
EnrolledAt int64 `json:"enrolled_at,omitempty"`
BackupCodesRemaining int `json:"backup_codes_remaining"`
Digits int `json:"digits,omitempty"`
PeriodSeconds int `json:"period_seconds,omitempty"`
}
TOTPEnrollStartData {
OtpauthURL string `json:"otpauth_url"`
Issuer string `json:"issuer"`
Account string `json:"account"`
Digits int `json:"digits"`
PeriodSec int `json:"period_seconds"`
ExpiresIn int `json:"expires_in"`
}
TOTPEnrollConfirmReq {
Code string `json:"code"` // Google Authenticator 顯示的 6 位數 TOTP 碼
2026-05-20 23:51:22 +00:00
}
TOTPEnrollConfirmData {
BackupCodes []string `json:"backup_codes"`
}
TOTPVerifyReq {
Code string `json:"code"` // TOTP 6 位數碼,或 8 位數備援碼
2026-05-20 23:51:22 +00:00
}
TOTPBackupCodesData {
BackupCodes []string `json:"backup_codes"`
}
// 文件用:成功回應 envelopeHTTP 200, code=102000, message=SUCCESS
MemberMeOKStatus {
Code int64 `json:"code"`
Message string `json:"message"`
Data MemberMeData `json:"data"`
}
VerificationStartOKStatus {
Code int64 `json:"code"`
Message string `json:"message"`
Data VerificationStartData `json:"data"`
}
TOTPStatusOKStatus {
Code int64 `json:"code"`
Message string `json:"message"`
Data TOTPStatusData `json:"data"`
}
TOTPEnrollStartOKStatus {
Code int64 `json:"code"`
Message string `json:"message"`
Data TOTPEnrollStartData `json:"data"`
}
TOTPEnrollConfirmOKStatus {
Code int64 `json:"code"`
Message string `json:"message"`
Data TOTPEnrollConfirmData `json:"data"`
}
TOTPBackupCodesOKStatus {
Code int64 `json:"code"`
Message string `json:"message"`
Data TOTPBackupCodesData `json:"data"`
}
2026-05-20 23:51:22 +00:00
)
@server(
refactor(middleware): wire AuthJWT + CasbinRBAC via .api middleware directive Stop relying on a global server.Use(CloudEPJWT) that was invisible from the .api source. Protected routes now declare middleware explicitly in each @server block and goctl chains them into routes.go — the .api file is the single source of truth for "who needs Bearer / who needs RBAC". Concretely: - Rewrite middleware to go-zero's standard struct + Handle() pattern. AuthJWT becomes strict: missing/invalid Bearer returns 28501000 (was soft passthrough). CasbinRBAC stays nil-tolerant so dev/test boots without a policy. - Files renamed to goctl's stringx convention (authjwt_middleware.go, casbinrbac_middleware.go) so future `make gen-api` runs see them as already-generated and skip the empty stub. - Move actor context helpers (Actor, WithActor, ActorFromContext) into internal/library/actor so middleware and BOTH logic packages share one context key. Previously each logic package had its own private actorKey struct{}, so an actor injected for member was invisible to permission — the permission RBAC chain would always see "missing actor". member/permission actor.go are now thin type-alias shims. - .api files declare middleware per group: auth.api (public) → no middleware (register/login/token/...) auth.api (logout) → middleware: AuthJWT member.api → middleware: AuthJWT permission.api (catalog,me) → middleware: AuthJWT permission.api (admin ops) → middleware: AuthJWT,CasbinRBAC normal.api (/health) → no middleware - ServiceContext exposes AuthJWT / CasbinRBAC as rest.Middleware; the global server.Use(...) in gateway.go is removed. - Document the pattern in AGENTS.md (cross-agent rules) and generate/api/README.md (detailed examples + filename rules) so any future AI agent or human follows the same convention. make gen-api / gen-doc / lint / build all pass. Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-21 09:30:50 +00:00
group: member
prefix: /api/v1/members
middleware: AuthJWT
tags: "Member - 會員"
summary: "Profile / 業務 Email 與 Phone 驗證 / TOTP MFA需 Bearer"
2026-05-20 23:51:22 +00:00
)
service gateway {
@doc "取得當前會員 profileBearer JWT本機 dev 可 fallback X-Tenant-ID + X-UID"
/*
@respdoc-200 (MemberMeOKStatus) // 成功code=102000
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-404 (
29301000: (APIErrorStatus) member 不存在
) // 資源不存在
@respdoc-500 (
29201000: (APIErrorStatus) 資料庫錯誤
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler getMemberMe
get /me returns (MemberMeData)
@doc "更新當前會員 profile"
/*
@respdoc-200 (MemberMeOKStatus) // 成功code=102000
@respdoc-400 (
10101000: (APIErrorStatus) 參數格式錯誤
) // 參數錯誤
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-404 (
29301000: (APIErrorStatus) member 不存在
) // 資源不存在
@respdoc-500 (
29201000: (APIErrorStatus) 資料庫錯誤
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler updateMemberMe
patch /me (UpdateMemberMeReq) returns (MemberMeData)
@doc "開始業務 email 驗證"
/*
@respdoc-200 (VerificationStartOKStatus) // 成功code=102000
@respdoc-400 (
10101000: (APIErrorStatus) 參數格式錯誤
29104000: (APIErrorStatus) target 必填Member scope
) // 參數錯誤
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-429 (
29604000: (APIErrorStatus) OTP 重送冷卻
29310000: (APIErrorStatus) 每日驗證上限
) // 請求過於頻繁
@respdoc-500 (
29201000: (APIErrorStatus) 資料庫錯誤
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler startEmailVerification
post /me/verifications/email/start (VerificationStartReq) returns (VerificationStartData)
@doc "確認業務 email 驗證"
/*
@respdoc-200 (EmptyOKStatus) // 成功code=102000
@respdoc-400 (
10101000: (APIErrorStatus) 參數格式錯誤
29104000: (APIErrorStatus) challenge_id / code 必填Member scope
) // 參數錯誤
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-403 (
29505000: (APIErrorStatus) OTP 無效 / challenge tenant 或 purpose 不符
) // 禁止存取
@respdoc-404 (
29301000: (APIErrorStatus) OTP challenge / member 不存在
) // 資源不存在
@respdoc-409 (
29309000: (APIErrorStatus) OTP challenge 鎖定
) // 資源狀態衝突
@respdoc-500 (
29201000: (APIErrorStatus) 資料庫錯誤
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler confirmEmailVerification
post /me/verifications/email/confirm (VerificationConfirmReq)
@doc "開始業務 phone 驗證"
/*
@respdoc-200 (VerificationStartOKStatus) // 成功code=102000
@respdoc-400 (
10101000: (APIErrorStatus) 參數格式錯誤
29104000: (APIErrorStatus) target 必填Member scope
) // 參數錯誤
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-429 (
29604000: (APIErrorStatus) OTP 重送冷卻
29310000: (APIErrorStatus) 每日驗證上限
) // 請求過於頻繁
@respdoc-500 (
29201000: (APIErrorStatus) 資料庫錯誤
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler startPhoneVerification
post /me/verifications/phone/start (VerificationStartReq) returns (VerificationStartData)
@doc "確認業務 phone 驗證"
/*
@respdoc-200 (EmptyOKStatus) // 成功code=102000
@respdoc-400 (
10101000: (APIErrorStatus) 參數格式錯誤
29104000: (APIErrorStatus) challenge_id / code 必填Member scope
) // 參數錯誤
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-403 (
29505000: (APIErrorStatus) OTP 無效 / challenge tenant 或 purpose 不符
) // 禁止存取
@respdoc-404 (
29301000: (APIErrorStatus) OTP challenge / member 不存在
) // 資源不存在
@respdoc-409 (
29309000: (APIErrorStatus) OTP challenge 鎖定
) // 資源狀態衝突
@respdoc-500 (
29201000: (APIErrorStatus) 資料庫錯誤
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler confirmPhoneVerification
post /me/verifications/phone/confirm (VerificationConfirmReq)
@doc "TOTP 狀態"
/*
@respdoc-200 (TOTPStatusOKStatus) // 成功code=102000
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-500 (
29201000: (APIErrorStatus) 資料庫錯誤
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler getTOTPStatus
get /me/totp returns (TOTPStatusData)
@doc "開始 TOTP 綁定"
/*
@respdoc-200 (TOTPEnrollStartOKStatus) // 成功code=102000
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-409 (
29303000: (APIErrorStatus) TOTP 已綁定
) // 資源衝突
@respdoc-500 (
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler startTOTPEnroll
post /me/totp/enroll-start returns (TOTPEnrollStartData)
@doc "確認 TOTP 綁定"
/*
@respdoc-200 (TOTPEnrollConfirmOKStatus) // 成功code=102000
@respdoc-400 (
10101000: (APIErrorStatus) 參數格式錯誤
29104000: (APIErrorStatus) code 必填Member scope
) // 參數錯誤
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-403 (
29505000: (APIErrorStatus) TOTP 碼無效
) // 禁止存取
@respdoc-404 (
29301000: (APIErrorStatus) enroll session / member 不存在
) // 資源不存在
@respdoc-409 (
29303000: (APIErrorStatus) TOTP 已綁定
) // 資源衝突
@respdoc-500 (
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler confirmTOTPEnroll
post /me/totp/enroll-confirm (TOTPEnrollConfirmReq) returns (TOTPEnrollConfirmData)
@doc "驗證 TOTPstep-up 測試)"
/*
@respdoc-200 (EmptyOKStatus) // 成功code=102000
@respdoc-400 (
10101000: (APIErrorStatus) 參數格式錯誤
29104000: (APIErrorStatus) code 必填Member scope
) // 參數錯誤
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-403 (
29505000: (APIErrorStatus) TOTP 碼無效或已使用
) // 禁止存取
@respdoc-409 (
29309000: (APIErrorStatus) TOTP 未綁定
) // 資源狀態衝突
@respdoc-500 (
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler verifyTOTP
post /me/totp/verify (TOTPVerifyReq)
@doc "重產 TOTP 備援碼"
/*
@respdoc-200 (TOTPBackupCodesOKStatus) // 成功code=102000
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-404 (
29301000: (APIErrorStatus) member 不存在
) // 資源不存在
@respdoc-409 (
29309000: (APIErrorStatus) TOTP 未綁定
) // 資源狀態衝突
@respdoc-500 (
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler regenerateTOTPBackupCodes
post /me/totp/backup-codes returns (TOTPBackupCodesData)
@doc "解除 TOTP 綁定"
/*
@respdoc-200 (EmptyOKStatus) // 成功code=102000
@respdoc-401 (
29501000: (APIErrorStatus) 缺少 Bearer 或 X-Tenant-ID/X-UID
) // 未授權
@respdoc-404 (
29301000: (APIErrorStatus) member 不存在
) // 資源不存在
@respdoc-500 (
29201000: (APIErrorStatus) 資料庫錯誤
29601000: (APIErrorStatus) 系統內部錯誤
) // 內部錯誤
@respdoc-501 (
29605000: (APIErrorStatus) 功能未配置
) // 未實作
*/
2026-05-20 23:51:22 +00:00
@handler disableTOTP
delete /me/totp
}