package auth import ( "context" "errors" "log/slog" "platform/pkg/u" "platform/web/core" m "platform/web/models" q "platform/web/queries" s "platform/web/services" "golang.org/x/crypto/bcrypt" ) func authClient(clientId string, clientSecrets ...string) (*m.Client, error) { // 获取客户端信息 client, err := q.Client. Preload(q.Client.Permissions). Where( q.Client.ClientID.Eq(clientId), q.Client.Status.Eq(1)). Take() if err != nil { return nil, err } // 检查客户端密钥 if client.Spec == m.ClientSpecWeb || client.Spec == m.ClientSpecAPI { if len(clientSecrets) == 0 { return nil, errors.New("客户端密钥错误") } clientSecret := clientSecrets[0] if bcrypt.CompareHashAndPassword([]byte(client.ClientSecret), []byte(clientSecret)) != nil { return nil, errors.New("客户端密钥错误") } } // 组织授权信息(一次性请求) return client, nil } func authUser(loginType PwdLoginType, username, password string) (user *m.User, err error) { switch loginType { case PwdLoginByPhone: user, err = authUserBySms(q.Q, username, password) if err != nil { return nil, err } if user == nil { user = &m.User{ Phone: username, Username: u.P(username), Status: m.UserStatusEnabled, } } case PwdLoginByEmail: user, err = authUserByEmail(q.Q, username, password) if err != nil { return nil, err } case PwdLoginByPassword: user, err = authUserByPassword(q.Q, username, password) if err != nil { return nil, err } default: return nil, ErrAuthorizeInvalidRequest } // 账户状态 if user.Status == m.UserStatusDisabled { return nil, core.NewBizErr("账号已禁用") } return user, nil } func authUserBySms(tx *q.Query, username, code string) (*m.User, error) { // 验证验证码 err := s.Verifier.VerifySms(context.Background(), username, code) if err != nil { return nil, core.NewBizErr("短信认证失败", err) } // 查找用户 return tx.User.Where(tx.User.Phone.Eq(username)).Take() } func authUserByEmail(tx *q.Query, username, code string) (*m.User, error) { return nil, core.NewServErr("邮箱登录不可用") } func authUserByPassword(tx *q.Query, username, password string) (*m.User, error) { user, err := tx.User. Where(tx.User.Phone.Eq(username)). Or(tx.User.Email.Eq(username)). Or(tx.User.Username.Eq(username)). Take() if err != nil { slog.Debug("查找用户失败", "error", err) return nil, core.NewBizErr("用户不存在或密码错误") } // 验证密码 if user.Password == nil || *user.Password == "" { slog.Debug("用户未设置密码", "username", username) return nil, core.NewBizErr("用户不存在或密码错误") } if bcrypt.CompareHashAndPassword([]byte(*user.Password), []byte(password)) != nil { slog.Debug("密码验证失败", "username", username) return nil, core.NewBizErr("用户不存在或密码错误") } return user, nil } func authAdmin(loginType PwdLoginType, username, password string) (admin *m.Admin, err error) { switch loginType { case PwdLoginByPhone, PwdLoginByEmail: return nil, core.NewServErr("不支持的登录方式:" + string(loginType)) case PwdLoginByPassword: admin, err = authAdminByPassword(q.Q, username, password) if err != nil { return nil, err } default: return nil, ErrAuthorizeInvalidRequest } // 账户状态 if admin.Status == m.AdminStatusDisabled { return nil, core.NewBizErr("账号已禁用") } return admin, nil } func authAdminByPassword(tx *q.Query, username, password string) (*m.Admin, error) { admin, err := tx.Admin.Where(tx.Admin.Username.Eq(username)).Take() if err != nil { return nil, core.NewBizErr("账号不存在或密码错误") } // 验证密码 if admin.Password == "" { return nil, core.NewBizErr("账号不存在或密码错误") } if bcrypt.CompareHashAndPassword([]byte(admin.Password), []byte(password)) != nil { return nil, core.NewBizErr("账号不存在或密码错误") } return admin, nil } func adminScopes(admin *m.Admin) ([]string, error) { count, err := q.Admin. LeftJoin(q.LinkAdminRole, q.LinkAdminRole.AdminID.EqCol(q.Admin.ID)). LeftJoin(q.LinkAdminRolePermission, q.LinkAdminRolePermission.RoleID.EqCol(q.LinkAdminRole.RoleID)). LeftJoin(q.Permission, q.Permission.ID.EqCol(q.LinkAdminRolePermission.PermissionID)). Where(q.Admin.ID.Eq(admin.ID)). Select(q.Permission.Name). Count() if err != nil { return nil, err } if count == 0 { return nil, nil } scopes := make([]string, 0, count) err = q.Admin. LeftJoin(q.LinkAdminRole, q.LinkAdminRole.AdminID.EqCol(q.Admin.ID)). LeftJoin(q.LinkAdminRolePermission, q.LinkAdminRolePermission.RoleID.EqCol(q.LinkAdminRole.RoleID)). LeftJoin(q.Permission, q.Permission.ID.EqCol(q.LinkAdminRolePermission.PermissionID)). Where(q.Admin.ID.Eq(admin.ID)). Select(q.Permission.Name). Scan(&scopes) if err != nil { return nil, err } return scopes, nil }