为 9 个模块添加 Context 超时控制
完成模块: - auth: 3 个 Repository 方法 + Service + Handler + Middleware - wallet: 已有 context 支持,修复依赖调用 - payment: 已有 context 支持,修复 wallet 调用 - adminaudit: 1 个方法 - notification: 2 个方法 - realname: 2 个方法 - systemconfig: 4 个方法 - adminauth: 7 个方法 - adminuser: 6 个方法 所有数据库调用已改为 r.db.WithContext(ctx),完整传递 context 链路。 待完成模块: order, listing, chat 等 12 个模块(约 157 个方法)
This commit is contained in:
@@ -20,7 +20,7 @@ func NewHandler(service *Service) *Handler {
|
||||
}
|
||||
|
||||
func (h *Handler) Captcha(c *gin.Context) {
|
||||
item, err := h.service.Captcha()
|
||||
item, err := h.service.Captcha(c.Request.Context(), )
|
||||
if err != nil {
|
||||
writeAdminAuthError(c, err)
|
||||
return
|
||||
@@ -34,7 +34,7 @@ func (h *Handler) Login(c *gin.Context) {
|
||||
response.BadRequest(c, "用户名、密码和验证码不能为空")
|
||||
return
|
||||
}
|
||||
result, err := h.service.Login(strings.TrimSpace(req.Username), req.Password, strings.TrimSpace(req.CaptchaID), strings.TrimSpace(req.CaptchaCode))
|
||||
result, err := h.service.Login(c.Request.Context(), strings.TrimSpace(req.Username), req.Password, strings.TrimSpace(req.CaptchaID), strings.TrimSpace(req.CaptchaCode))
|
||||
if err != nil {
|
||||
writeAdminAuthError(c, err)
|
||||
return
|
||||
@@ -53,7 +53,7 @@ func (h *Handler) Me(c *gin.Context) {
|
||||
response.Unauthorized(c, "管理员上下文无效")
|
||||
return
|
||||
}
|
||||
admin, err := h.service.Me(adminID)
|
||||
admin, err := h.service.Me(c.Request.Context(), adminID)
|
||||
if err != nil {
|
||||
writeAdminAuthError(c, err)
|
||||
return
|
||||
@@ -76,7 +76,7 @@ func (h *Handler) UpdateSupportStatus(c *gin.Context) {
|
||||
response.BadRequest(c, "状态值无效,必须是 online、offline 或 busy")
|
||||
return
|
||||
}
|
||||
if err := h.service.UpdateSupportStatus(adminID, req.Status); err != nil {
|
||||
if err := h.service.UpdateSupportStatus(c.Request.Context(), adminID, req.Status); err != nil {
|
||||
writeAdminAuthError(c, err)
|
||||
return
|
||||
}
|
||||
@@ -102,7 +102,7 @@ func (h *Handler) Refresh(c *gin.Context) {
|
||||
response.BadRequest(c, "refresh_token 不能为空")
|
||||
return
|
||||
}
|
||||
tokens, err := h.service.Refresh(req.RefreshToken)
|
||||
tokens, err := h.service.Refresh(c.Request.Context(), req.RefreshToken)
|
||||
if err != nil {
|
||||
writeAdminAuthError(c, err)
|
||||
return
|
||||
|
||||
@@ -36,7 +36,7 @@ func NewRepository(db *gorm.DB, redis *redis.Client, jwt *auth.JWTManager) *Repo
|
||||
return &Repository{db: db, redis: redis, jwt: jwt}
|
||||
}
|
||||
|
||||
func (r *Repository) Captcha() (*CaptchaDTO, error) {
|
||||
func (r *Repository) Captcha(ctx context.Context) (*CaptchaDTO, error) {
|
||||
if r.redis == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
@@ -48,7 +48,6 @@ func (r *Repository) Captcha() (*CaptchaDTO, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctx := context.Background()
|
||||
if err := r.redis.Set(ctx, captchaKey(captchaID), strings.ToUpper(code), captchaTTL).Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -59,15 +58,15 @@ func (r *Repository) Captcha() (*CaptchaDTO, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) Login(username string, password string, captchaID string, captchaCode string) (LoginResult, error) {
|
||||
if err := r.verifyCaptcha(captchaID, captchaCode); err != nil {
|
||||
func (r *Repository) Login(ctx context.Context, username string, password string, captchaID string, captchaCode string) (LoginResult, error) {
|
||||
if err := r.verifyCaptcha(ctx, captchaID, captchaCode); err != nil {
|
||||
return LoginResult{}, err
|
||||
}
|
||||
if err := r.ensureDefaultAdmin(); err != nil {
|
||||
if err := r.ensureDefaultAdmin(ctx); err != nil {
|
||||
return LoginResult{}, err
|
||||
}
|
||||
var admin model.AdminUser
|
||||
if err := r.db.Where("username = ?", username).First(&admin).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Where("username = ?", username).First(&admin).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return LoginResult{}, ErrInvalidCredential
|
||||
}
|
||||
@@ -81,7 +80,7 @@ func (r *Repository) Login(username string, password string, captchaID string, c
|
||||
}
|
||||
now := time.Now()
|
||||
admin.LastLoginAt = &now
|
||||
if err := r.db.Save(&admin).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Save(&admin).Error; err != nil {
|
||||
return LoginResult{}, err
|
||||
}
|
||||
tokens, err := r.jwt.GenerateSubjectPair(admin.ID, admin.Username, "admin")
|
||||
@@ -89,15 +88,14 @@ func (r *Repository) Login(username string, password string, captchaID string, c
|
||||
return LoginResult{}, err
|
||||
}
|
||||
dto := toDTO(admin)
|
||||
r.loadRolesAndPerms(&dto)
|
||||
r.loadRolesAndPerms(ctx, &dto)
|
||||
return LoginResult{Admin: dto, Tokens: tokens}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) verifyCaptcha(captchaID string, captchaCode string) error {
|
||||
func (r *Repository) verifyCaptcha(ctx context.Context, captchaID string, captchaCode string) error {
|
||||
if r.redis == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
ctx := context.Background()
|
||||
key := captchaKey(captchaID)
|
||||
stored, err := r.redis.Get(ctx, key).Result()
|
||||
if errors.Is(err, redis.Nil) {
|
||||
@@ -113,34 +111,34 @@ func (r *Repository) verifyCaptcha(captchaID string, captchaCode string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) FindByID(id uint64) (*AdminDTO, error) {
|
||||
func (r *Repository) FindByID(ctx context.Context, id uint64) (*AdminDTO, error) {
|
||||
var admin model.AdminUser
|
||||
if err := r.db.First(&admin, id).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).First(&admin, id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if admin.Status != "active" {
|
||||
return nil, ErrAdminDisabled
|
||||
}
|
||||
dto := toDTO(admin)
|
||||
r.loadRolesAndPerms(&dto)
|
||||
r.loadRolesAndPerms(ctx, &dto)
|
||||
return &dto, nil
|
||||
}
|
||||
|
||||
func (r *Repository) UpdateSupportStatus(adminID uint64, status string) error {
|
||||
func (r *Repository) UpdateSupportStatus(ctx context.Context, adminID uint64, status string) error {
|
||||
if r.db == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
if status != "online" && status != "offline" && status != "busy" {
|
||||
return errors.New("invalid support status")
|
||||
}
|
||||
return r.db.Model(&model.AdminUser{}).
|
||||
return r.db.WithContext(ctx).Model(&model.AdminUser{}).
|
||||
Where("id = ?", adminID).
|
||||
Update("support_status", status).Error
|
||||
}
|
||||
|
||||
func (r *Repository) ensureDefaultAdmin() error {
|
||||
func (r *Repository) ensureDefaultAdmin(ctx context.Context) error {
|
||||
var count int64
|
||||
if err := r.db.Model(&model.AdminUser{}).Count(&count).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Model(&model.AdminUser{}).Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if count > 0 {
|
||||
@@ -156,14 +154,14 @@ func (r *Repository) ensureDefaultAdmin() error {
|
||||
Nickname: "超级管理员",
|
||||
Status: "active",
|
||||
}
|
||||
if err := r.db.Create(&admin).Error; err != nil {
|
||||
if err := r.db.WithContext(ctx).Create(&admin).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 自动关联 super_admin 角色
|
||||
var superAdminRole model.Role
|
||||
if err := r.db.Where("code = ?", "super_admin").First(&superAdminRole).Error; err == nil {
|
||||
r.db.Create(&model.AdminUserRole{
|
||||
if err := r.db.WithContext(ctx).Where("code = ?", "super_admin").First(&superAdminRole).Error; err == nil {
|
||||
r.db.WithContext(ctx).Create(&model.AdminUserRole{
|
||||
AdminID: admin.ID,
|
||||
RoleID: superAdminRole.ID,
|
||||
})
|
||||
@@ -183,13 +181,13 @@ func toDTO(admin model.AdminUser) AdminDTO {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Repository) loadRolesAndPerms(dto *AdminDTO) {
|
||||
func (r *Repository) loadRolesAndPerms(ctx context.Context, dto *AdminDTO) {
|
||||
if r.db == nil {
|
||||
return
|
||||
}
|
||||
// 加载角色
|
||||
var roles []RoleDTO
|
||||
r.db.Table("roles").
|
||||
r.db.WithContext(ctx).Table("roles").
|
||||
Joins("JOIN admin_user_roles aur ON aur.role_id = roles.id").
|
||||
Where("aur.admin_user_id = ?", dto.ID).
|
||||
Find(&roles)
|
||||
@@ -205,7 +203,7 @@ func (r *Repository) loadRolesAndPerms(dto *AdminDTO) {
|
||||
}
|
||||
|
||||
var permCodes []string
|
||||
r.db.Table("permissions").
|
||||
r.db.WithContext(ctx).Table("permissions").
|
||||
Select("DISTINCT permissions.code").
|
||||
Joins("JOIN role_permissions rp ON rp.permission_id = permissions.id").
|
||||
Joins("JOIN admin_user_roles aur ON aur.role_id = rp.role_id").
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package adminauth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"hfb_sys/backend/internal/modules/auth"
|
||||
@@ -23,7 +24,7 @@ func NewService(repo *Repository, jwt *auth.JWTManager) *Service {
|
||||
return &Service{repo: repo, jwt: jwt}
|
||||
}
|
||||
|
||||
func (s *Service) Refresh(refreshToken string) (*auth.TokenPair, error) {
|
||||
func (s *Service) Refresh(ctx context.Context, refreshToken string) (*auth.TokenPair, error) {
|
||||
if s.jwt == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
@@ -38,33 +39,33 @@ func (s *Service) Refresh(refreshToken string) (*auth.TokenPair, error) {
|
||||
return &pair, nil
|
||||
}
|
||||
|
||||
func (s *Service) Captcha() (*CaptchaDTO, error) {
|
||||
func (s *Service) Captcha(ctx context.Context, ) (*CaptchaDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.Captcha()
|
||||
return s.repo.Captcha(ctx, )
|
||||
}
|
||||
|
||||
func (s *Service) Login(username string, password string, captchaID string, captchaCode string) (LoginResult, error) {
|
||||
func (s *Service) Login(ctx context.Context, username string, password string, captchaID string, captchaCode string) (LoginResult, error) {
|
||||
if s.repo == nil {
|
||||
return LoginResult{}, ErrDependencyUnavailable
|
||||
}
|
||||
if username == "" || password == "" || captchaID == "" || captchaCode == "" {
|
||||
return LoginResult{}, ErrInvalidCredential
|
||||
}
|
||||
return s.repo.Login(username, password, captchaID, captchaCode)
|
||||
return s.repo.Login(ctx, username, password, captchaID, captchaCode)
|
||||
}
|
||||
|
||||
func (s *Service) Me(adminID uint64) (*AdminDTO, error) {
|
||||
func (s *Service) Me(ctx context.Context, adminID uint64) (*AdminDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.FindByID(adminID)
|
||||
return s.repo.FindByID(ctx, adminID)
|
||||
}
|
||||
|
||||
func (s *Service) UpdateSupportStatus(adminID uint64, status string) error {
|
||||
func (s *Service) UpdateSupportStatus(ctx context.Context, adminID uint64, status string) error {
|
||||
if s.repo == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.UpdateSupportStatus(adminID, status)
|
||||
return s.repo.UpdateSupportStatus(ctx, adminID, status)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user