优化结构

This commit is contained in:
Yvan
2026-08-24 21:50:33 +08:00
parent d3c20c578f
commit 969afee284
20 changed files with 497 additions and 244 deletions
+13 -3
View File
@@ -56,6 +56,16 @@ func NewAuthenticationUsecase(users *UserUsecase, security *SecurityUsecase, iss
return &AuthenticationUsecase{users: users, security: security, issuer: issuer, audit: audit}
}
// passwordExpired reports whether the security policy has aged out this user's
// password. Both the credential login and the per-request token check consult
// it, so the rule lives in one place.
func passwordExpired(config *SecurityConfig, user *User) bool {
if config == nil || user == nil || !config.PwdExpireEnable || config.PwdExpireDays <= 0 || user.PasswordUpdatedAt == nil {
return false
}
return time.Now().After(user.PasswordUpdatedAt.AddDate(0, 0, config.PwdExpireDays))
}
func (uc *AuthenticationUsecase) recordLogin(ctx context.Context, attempt *LoginAttempt, status bool, message string, userID uint) {
if uc.audit == nil || attempt == nil {
return
@@ -119,7 +129,7 @@ func (uc *AuthenticationUsecase) Login(ctx context.Context, attempt *LoginAttemp
}
uc.security.ClearLoginState(ctx, attempt.Username)
if config.PwdExpireEnable && config.PwdExpireDays > 0 && user.PasswordUpdatedAt != nil && time.Now().After((*user.PasswordUpdatedAt).AddDate(0, 0, config.PwdExpireDays)) {
if passwordExpired(config, user) {
user.MustChangePassword = true
}
issued, err := uc.issuer.IssueToken(user, user.AuthorityID, user.MustChangePassword, 0)
@@ -185,7 +195,7 @@ func (uc *AuthenticationUsecase) currentTokenUser(ctx context.Context, claims *A
if err != nil || config == nil {
return nil, ErrTokenDisabled
}
if config.PwdExpireEnable && config.PwdExpireDays > 0 && user.PasswordUpdatedAt != nil && time.Now().After(user.PasswordUpdatedAt.AddDate(0, 0, config.PwdExpireDays)) {
if passwordExpired(config, user) {
user.MustChangePassword = true
}
return user, nil
@@ -219,7 +229,7 @@ func (uc *AuthenticationUsecase) AuthenticateToken(ctx context.Context, token st
// this makes a revoked-but-expired token report the revocation reason (and
// not the generic expiry message), which the frontend uses to decide whether
// to clear a session.
disabled, err := uc.security.tokens.IsTokenDisabled(ctx, token)
disabled, err := uc.security.TokenDisabled(ctx, token)
if err != nil || disabled {
return nil, ErrTokenDisabled
}
+5
View File
@@ -5,6 +5,11 @@ import (
"time"
)
// SuperAdminAuthorityID is the seeded super-administrator role created by the
// bootstrap data in internal/data/system/seed.go. It is the fallback authority
// for new users and the recipient group for system-wide alerts.
const SuperAdminAuthorityID uint = 888
type AuthorityAccessRepo interface {
CreateAuthority(context.Context, *Authority) error
CopyAuthority(context.Context, uint, *Authority) error
+10
View File
@@ -270,6 +270,16 @@ func (uc *SecurityUsecase) RotateActiveToken(ctx context.Context, username, oldT
func (uc *SecurityUsecase) UseMultipoint() bool { return uc.settings.UseMultipoint() }
// TokenDisabled reports whether the token sits on the revocation blacklist. The
// blacklist belongs to the token usecase; exposing it here keeps authentication
// from reaching through this usecase into another one's dependencies.
func (uc *SecurityUsecase) TokenDisabled(ctx context.Context, token string) (bool, error) {
if uc == nil || uc.tokens == nil {
return false, nil
}
return uc.tokens.IsTokenDisabled(ctx, token)
}
func (uc *SecurityUsecase) CaptchaRuntimeSettings() CaptchaSettings {
return uc.settings.CaptchaSettings()
}