feat: 接入商务用户资料和全局统计偏好

This commit is contained in:
Yvan
2026-11-03 17:44:25 +08:00
parent 89cc7761b5
commit ce4b54a2e2
39 changed files with 2562 additions and 17 deletions
+2 -2
View File
@@ -122,7 +122,7 @@ func (uc *AuthenticationUsecase) Login(ctx context.Context, attempt *LoginAttemp
uc.recordLogin(ctx, attempt, false, "用户名不存在或者密码错误", 0)
return nil, ErrInvalidCredentials
}
if user.Enable != 1 {
if user.Enable != 1 || user.BusinessStatus != 0 {
_, _ = uc.security.IncrementLoginIP(ctx, attempt.IP, ipTTL)
uc.recordLogin(ctx, attempt, false, "用户被禁止登录", user.ID)
return nil, &UserDisabledError{UserID: user.ID}
@@ -183,7 +183,7 @@ func (uc *AuthenticationUsecase) currentTokenUser(ctx context.Context, claims *A
if err != nil || user == nil || user.ID != claims.ID || user.Username != claims.Username {
return nil, ErrTokenDisabled
}
if user.Enable != 1 {
if user.Enable != 1 || user.BusinessStatus != 0 {
return nil, &UserDisabledError{UserID: user.ID}
}
if !userHasAuthority(user, claims.AuthorityID) {
@@ -0,0 +1,27 @@
package system
import (
"context"
"errors"
"golang.org/x/crypto/bcrypt"
"testing"
"time"
)
func TestBusinessReviewStateBlocksPasswordAndExistingSession(t *testing.T) {
hash, err := bcrypt.GenerateFromPassword([]byte("secret"), bcrypt.MinCost)
if err != nil {
t.Fatal(err)
}
for _, status := range []int{1, 2, 3} {
user := &User{ID: 7, Username: "business", Password: string(hash), Enable: 1, BusinessStatus: status}
security := NewSecurityUsecase(&authenticationSecurityRepo{}, &authenticationCache{}, &authenticationSettings{}, nil)
uc := NewAuthenticationUsecase(NewUserUsecase(&authenticationUserRepo{user: user}), security, &authenticationIssuer{}, nil)
if _, err := uc.Login(context.Background(), &LoginAttempt{Username: "business", Password: "secret", IP: "127.0.0.1"}); !errors.Is(err, ErrUserDisabled) {
t.Fatalf("审核状态 %d 的登录应被拒绝: %v", status, err)
}
if _, err := uc.currentTokenUser(context.Background(), &AuthClaims{ID: 7, Username: "business", UUID: "uuid", IssuedAt: time.Now()}); !errors.Is(err, ErrUserDisabled) {
t.Fatalf("审核状态 %d 的现有会话应被拒绝: %v", status, err)
}
}
}
+8
View File
@@ -29,6 +29,14 @@ type User struct {
OriginSetting map[string]any
MustChangePassword bool
PasswordUpdatedAt *time.Time
// 商务资料与系统身份共用主键;平台商务 ID 另由绑定关系持有。
Level int
ParentID uint
IDPath string
RealName string
QQNumber string
BusinessStatus int
RejectReason string
}
type UserListFilter struct {
Username, NickName, Phone, Email, OrderKey string