411 lines
13 KiB
Plaintext
411 lines
13 KiB
Plaintext
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 格式(可選)
|
||
}
|
||
|
||
VerificationStartReq {
|
||
Target string `json:"target"` // 驗證目標:email 地址或 E.164 手機號(依端點而定)
|
||
}
|
||
|
||
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 驗證碼
|
||
}
|
||
|
||
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 碼
|
||
}
|
||
|
||
TOTPEnrollConfirmData {
|
||
BackupCodes []string `json:"backup_codes"`
|
||
}
|
||
|
||
TOTPVerifyReq {
|
||
Code string `json:"code"` // TOTP 6 位數碼,或 8 位數備援碼
|
||
}
|
||
|
||
TOTPBackupCodesData {
|
||
BackupCodes []string `json:"backup_codes"`
|
||
}
|
||
|
||
// 文件用:成功回應 envelope(HTTP 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"`
|
||
}
|
||
)
|
||
|
||
@server(
|
||
group: member
|
||
prefix: /api/v1/members
|
||
middleware: AuthJWT
|
||
tags: "Member - 會員"
|
||
summary: "Profile / 業務 Email 與 Phone 驗證 / TOTP MFA(需 Bearer)"
|
||
)
|
||
service gateway {
|
||
@doc "取得當前會員 profile(Bearer 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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@handler confirmTOTPEnroll
|
||
post /me/totp/enroll-confirm (TOTPEnrollConfirmReq) returns (TOTPEnrollConfirmData)
|
||
|
||
@doc "驗證 TOTP(step-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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@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) 功能未配置
|
||
) // 未實作
|
||
*/
|
||
@handler disableTOTP
|
||
delete /me/totp
|
||
}
|