package pub import ( "context" "errors" "perms-system-server/internal/consts" "perms-system-server/internal/loaders" authHelper "perms-system-server/internal/logic/auth" "perms-system-server/internal/model/user" "perms-system-server/internal/svc" "github.com/zeromicro/go-zero/core/limit" "golang.org/x/crypto/bcrypt" ) type LoginResult struct { UserDetails *loaders.UserDetails AccessToken string RefreshToken string } type LoginError struct { Code int Message string } func (e *LoginError) Error() string { return e.Message } func ValidateProductLogin(ctx context.Context, svcCtx *svc.ServiceContext, username, password, productCode string) (*LoginResult, error) { if svcCtx.UsernameLoginLimit != nil { code, _ := svcCtx.UsernameLoginLimit.Take(username) if code == limit.OverQuota { return nil, &LoginError{Code: 429, Message: "该账号登录尝试过于频繁,请5分钟后再试"} } } u, err := svcCtx.SysUserModel.FindOneByUsername(ctx, username) if err != nil { if errors.Is(err, user.ErrNotFound) { return nil, &LoginError{Code: 401, Message: "用户名或密码错误"} } return nil, err } if u.Status != consts.StatusEnabled { return nil, &LoginError{Code: 403, Message: "账号已被冻结"} } if err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)); err != nil { return nil, &LoginError{Code: 401, Message: "用户名或密码错误"} } if u.IsSuperAdmin == consts.IsSuperAdminYes { return nil, &LoginError{Code: 403, Message: "超级管理员不允许通过产品端登录,请使用管理后台"} } product, err := svcCtx.SysProductModel.FindOneByCode(ctx, productCode) if err != nil { return nil, &LoginError{Code: 400, Message: "产品不存在"} } if product.Status != consts.StatusEnabled { return nil, &LoginError{Code: 403, Message: "该产品已被禁用"} } member, memberErr := svcCtx.SysProductMemberModel.FindOneByProductCodeUserId(ctx, productCode, u.Id) if memberErr != nil { return nil, &LoginError{Code: 403, Message: "您不是该产品的成员"} } if member.Status != consts.StatusEnabled { return nil, &LoginError{Code: 403, Message: "您在该产品下的成员资格已被禁用"} } ud := svcCtx.UserDetailsLoader.Load(ctx, u.Id, productCode) accessToken, err := authHelper.GenerateAccessToken( svcCtx.Config.Auth.AccessSecret, svcCtx.Config.Auth.AccessExpire, ud.UserId, ud.Username, ud.ProductCode, ud.MemberType, ud.TokenVersion, ) if err != nil { return nil, err } refreshToken, err := authHelper.GenerateRefreshToken( svcCtx.Config.Auth.RefreshSecret, svcCtx.Config.Auth.RefreshExpire, ud.UserId, ud.ProductCode, ud.TokenVersion, ) if err != nil { return nil, err } return &LoginResult{ UserDetails: ud, AccessToken: accessToken, RefreshToken: refreshToken, }, nil }