Files
platform/web/auth/account.go

177 lines
4.6 KiB
Go
Raw Normal View History

package auth
import (
"context"
"errors"
"log/slog"
"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.
2026-03-18 18:09:32 +08:00
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{
2026-04-15 16:56:24 +08:00
Phone: 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) {
// 验证验证码
2026-04-15 16:56:24 +08:00
err := s.Verifier.VerifySms(context.Background(), username, code, s.VerifierSmsPurposeLogin)
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
}
2026-03-18 18:09:32 +08:00
func adminScopes(admin *m.Admin) ([]string, error) {
var scopes []struct{ Name string }
err := q.Admin.
2026-03-18 18:09:32 +08:00
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
}
scopeNames := make([]string, 0, len(scopes))
for _, scope := range scopes {
if scope.Name == "" {
continue
}
scopeNames = append(scopeNames, scope.Name)
}
return scopeNames, nil
2026-03-18 18:09:32 +08:00
}