优化安全码与外部邮箱二选一校验
Some checks are pending
Security Checks / security (push) Waiting to run

This commit is contained in:
smail 2026-10-03 01:41:24 +08:00
parent 0a23f6cb0e
commit f501f971bb
2 changed files with 28 additions and 2 deletions

View File

@ -2,6 +2,27 @@ package access
import "testing"
func TestHasRecoveryOptionAcceptsEitherConfiguredMethod(t *testing.T) {
tests := []struct {
name string
code bool
email bool
want bool
}{
{name: "neither", want: false},
{name: "security code only", code: true, want: true},
{name: "external email only", email: true, want: true},
{name: "both", code: true, email: true, want: true},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if got := HasRecoveryOption(test.code, test.email); got != test.want {
t.Fatalf("HasRecoveryOption(%t, %t) = %t, want %t", test.code, test.email, got, test.want)
}
})
}
}
func TestRecoveryOptionAuthorization(t *testing.T) {
for _, capability := range []Capability{CapabilityPasswordReset, CapabilityUserSecurityManage, CapabilityNotificationManage} {
for _, ready := range []struct {

View File

@ -40,6 +40,11 @@ type Request struct {
DeploymentChannel bool
}
// HasRecoveryOption 判断账号是否至少配置了一种可用恢复方式。
func HasRecoveryOption(recoveryCodeConfigured, externalEmailConfigured bool) bool {
return recoveryCodeConfigured || externalEmailConfigured
}
func Authorize(request Request) error {
if !request.ActorRole.Valid() {
return deny(CodeInvalidRole)
@ -58,7 +63,7 @@ func Authorize(request Request) error {
return deny(CodeRecentAuthRequired)
}
// 保留原策略与错误码名称;普通角色的恢复保障允许安全码或已验证外部邮箱任选其一。
if policy.RequiresRecoveryCode && request.ActorRole != RoleSuperAdmin && !request.RecoveryCodeConfigured && !request.ExternalEmailConfigured && !request.DeploymentChannel {
if policy.RequiresRecoveryCode && request.ActorRole != RoleSuperAdmin && !HasRecoveryOption(request.RecoveryCodeConfigured, request.ExternalEmailConfigured) && !request.DeploymentChannel {
return deny(CodeRecoveryCodeRequired)
}
return authorizeResource(request)
@ -101,7 +106,7 @@ func authorizeResource(request Request) error {
if !canManageAccountTarget(request.ActorRole, request.TargetRole) || !request.NewRole.Valid() || request.NewRole == RoleSuperAdmin {
return deny(CodeTargetRoleDenied)
}
if !request.TargetRecoveryConfigured && !request.TargetExternalEmailConfigured {
if !HasRecoveryOption(request.TargetRecoveryConfigured, request.TargetExternalEmailConfigured) {
return deny(CodeRecoveryCodeRequired)
}
case CapabilityPluginRestart: