Expose image studio flow and related admin controls

Bundle the current backend and web changes into one publishable snapshot
from the server worktree so the remote mirror reflects the deployed source.

Constraint: Push the existing mixed worktree from /docker/new-api/src without reshaping files
Rejected: Split into feature-specific commits | current worktree is already a single undifferentiated snapshot
Confidence: medium
Scope-risk: moderate
Directive: Split future feature work before deployment to preserve clearer history
Tested: git status inspection; git diff --stat review
Not-tested: build, lint, unit tests, integration tests
This commit is contained in:
OpenClaw Task Bot
2026-05-05 12:16:54 +08:00
parent 58c0258362
commit 92ee465a41
23 changed files with 2694 additions and 202 deletions

View File

@@ -16,6 +16,10 @@ const (
SecureVerificationSessionKey = "secure_verified_at"
// PasskeyReadySessionKey means WebAuthn finished and /api/verify can finalize step-up verification.
PasskeyReadySessionKey = "secure_passkey_ready_at"
// secureVerificationMethodSessionKey stores the method that completed step-up verification.
secureVerificationMethodSessionKey = "secure_verification_method"
secureVerificationMethod2FA = "2fa"
secureVerificationMethodPasskey = "passkey"
// SecureVerificationTimeout 验证有效期(秒)
SecureVerificationTimeout = 300 // 5分钟
// PasskeyReadyTimeout passkey ready 标记有效期(秒)
@@ -77,6 +81,7 @@ func UniversalVerify(c *gin.Context) {
// 根据验证方式进行验证
var verified bool
var verifyMethod string
var sessionMethod string
var err error
switch req.Method {
@@ -91,6 +96,7 @@ func UniversalVerify(c *gin.Context) {
}
verified = validateTwoFactorAuth(twoFA, req.Code)
verifyMethod = "2FA"
sessionMethod = secureVerificationMethod2FA
case "passkey":
if !hasPasskey {
@@ -108,6 +114,7 @@ func UniversalVerify(c *gin.Context) {
return
}
verifyMethod = "Passkey"
sessionMethod = secureVerificationMethodPasskey
default:
common.ApiError(c, fmt.Errorf("不支持的验证方式: %s", req.Method))
@@ -120,7 +127,7 @@ func UniversalVerify(c *gin.Context) {
}
// 验证成功,在 session 中记录时间戳
now, err := setSecureVerificationSession(c)
now, err := setSecureVerificationSession(c, sessionMethod)
if err != nil {
common.ApiError(c, fmt.Errorf("保存验证状态失败: %v", err))
return
@@ -139,11 +146,16 @@ func UniversalVerify(c *gin.Context) {
})
}
func setSecureVerificationSession(c *gin.Context) (int64, error) {
func setSecureVerificationSession(c *gin.Context, method string) (int64, error) {
session := sessions.Default(c)
session.Delete(PasskeyReadySessionKey)
now := time.Now().Unix()
session.Set(SecureVerificationSessionKey, now)
if method != "" {
session.Set(secureVerificationMethodSessionKey, method)
} else {
session.Delete(secureVerificationMethodSessionKey)
}
if err := session.Save(); err != nil {
return 0, err
}