// Package authsvc 是后台登录与当前用户信息的业务逻辑。 package authsvc import ( "context" "strconv" "time" "portal-mini-go/internal/middleware" "portal-mini-go/internal/model/admin" "portal-mini-go/internal/pkg/auth" "portal-mini-go/internal/pkg/errors" "portal-mini-go/internal/pkg/token" ) // userRepo 是登录与信息所需的用户仓储最小接口(由 repository/admin 实现)。 type userRepo interface { GetByUsername(ctx context.Context, username string) (*admin.User, error) GetByID(ctx context.Context, id uint64) (*admin.User, error) } // Service 后台认证业务:登录签发 JWT、当前用户信息聚合。 type Service struct { userRepo userRepo provider middleware.PermissionProvider jwtSecret string tokenTTL time.Duration } func New(userRepo userRepo, provider middleware.PermissionProvider, jwtSecret string, tokenTTL time.Duration) *Service { return &Service{userRepo: userRepo, provider: provider, jwtSecret: jwtSecret, tokenTTL: tokenTTL} } // LoginReq 登录请求。 type LoginReq struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } // Login 校验账号密码,成功返回 JWT。账号不存在 / 密码错误 / 禁用均返回未授权, // 避免泄露账号是否存在。 func (s *Service) Login(ctx context.Context, req LoginReq) (string, error) { u, err := s.userRepo.GetByUsername(ctx, req.Username) if err != nil { return "", errors.ErrUnauthorized } if u.Status != admin.UserStatusEnabled { return "", errors.ErrUnauthorized } if !auth.VerifyPassword(req.Password, u.PasswordHash) { return "", errors.ErrUnauthorized } return token.Generate(s.jwtSecret, strconv.FormatUint(u.ID, 10), s.tokenTTL) } // Info 是当前管理员聚合信息,供前端渲染与鉴权。 type Info struct { ID string `json:"id"` Username string `json:"username"` Nickname string `json:"nickname"` Roles []string `json:"roles"` Permissions []string `json:"permissions"` Menus []admin.MenuNode `json:"menus"` } // Info 返回当前管理员的角色、权限与可见菜单树。 func (s *Service) Info(ctx context.Context, adminID uint64) (*Info, error) { u, err := s.userRepo.GetByID(ctx, adminID) if err != nil { return nil, err } roles, err := s.provider.RolesOf(ctx, adminID) if err != nil { return nil, err } perms, err := s.provider.PermissionsOf(ctx, adminID) if err != nil { return nil, err } menus, err := s.provider.MenuTree(ctx, adminID) if err != nil { return nil, err } return &Info{ ID: strconv.FormatUint(u.ID, 10), Username: u.Username, Nickname: u.Nickname, Roles: roles, Permissions: perms, Menus: menus, }, nil }