package rbac import ( "context" "portal-mini-go/internal/model/admin" "portal-mini-go/internal/pkg/auth" "portal-mini-go/internal/pkg/errors" adminrepo "portal-mini-go/internal/repository/admin" ) // AdminService 管理员账号业务:CRUD、角色分配、密码重置。 type AdminService struct { repo UserRepository invalidator CacheInvalidator } func NewAdminService(repo UserRepository, invalidator CacheInvalidator) *AdminService { return &AdminService{repo: repo, invalidator: invalidator} } // CreateReq 新建管理员请求。 type CreateAdminReq struct { Username string `json:"username" binding:"required"` Nickname string `json:"nickname"` Password string `json:"password" binding:"required"` Status int8 `json:"status"` } // Create 新建管理员,用户名唯一,密码以 bcrypt 存储。 func (s *AdminService) Create(ctx context.Context, req CreateAdminReq) (*admin.User, error) { if req.Status == 0 { req.Status = admin.UserStatusEnabled } if req.Status != admin.UserStatusEnabled && req.Status != admin.UserStatusDisabled { return nil, errors.New(40000, "非法的管理员状态") } if _, err := s.repo.GetByUsername(ctx, req.Username); err == nil { return nil, errors.New(40900, "用户名已存在") } else if !errors.Is(err, errors.ErrNotFound) { return nil, err } hash, err := auth.HashPassword(req.Password) if err != nil { return nil, errors.Wrap(50000, "hash password", err) } u := &admin.User{ Username: req.Username, Nickname: req.Nickname, PasswordHash: hash, Status: req.Status, } if err := s.repo.Create(ctx, u); err != nil { return nil, err } return u, nil } // AdminListReq 管理员列表过滤条件。 type AdminListReq struct { Keyword string Status int8 Page int Size int } // List 分页查询管理员。 func (s *AdminService) List(ctx context.Context, req AdminListReq) ([]admin.User, int64, error) { page, size := req.Page, req.Size if page <= 0 { page = 1 } if size <= 0 { size = 20 } return s.repo.List(ctx, adminrepo.UserListFilter{ Keyword: req.Keyword, Status: req.Status, Page: page, Size: size, }) } // GetByID 按 ID 查询管理员。 func (s *AdminService) GetByID(ctx context.Context, id uint64) (*admin.User, error) { return s.repo.GetByID(ctx, id) } // UpdateAdminReq 编辑管理员请求;指针区分“未提供”与“置空”。 type UpdateAdminReq struct { Nickname *string `json:"nickname"` Status *int8 `json:"status"` } // Update 局部更新管理员昵称与状态。 func (s *AdminService) Update(ctx context.Context, id uint64, req UpdateAdminReq) (*admin.User, error) { cols := map[string]interface{}{} if req.Nickname != nil { cols["nickname"] = *req.Nickname } if req.Status != nil { if *req.Status != admin.UserStatusEnabled && *req.Status != admin.UserStatusDisabled { return nil, errors.New(40000, "非法的管理员状态") } cols["status"] = *req.Status } if len(cols) == 0 { return s.repo.GetByID(ctx, id) } if err := s.repo.Update(ctx, id, cols); err != nil { return nil, err } s.invalidator.Invalidate(ctx, id) return s.repo.GetByID(ctx, id) } // Delete 删除管理员(同时清理其角色关联,并失效缓存)。 func (s *AdminService) Delete(ctx context.Context, id uint64) error { if err := s.repo.Delete(ctx, id); err != nil { return err } s.invalidator.Invalidate(ctx, id) return nil } // SetRoles 为管理员分配角色(全量替换)。 func (s *AdminService) SetRoles(ctx context.Context, id uint64, roleIDs []uint64) error { if err := s.repo.SetRoles(ctx, id, roleIDs); err != nil { return err } s.invalidator.Invalidate(ctx, id) return nil } // ResetPassword 重置管理员密码。 func (s *AdminService) ResetPassword(ctx context.Context, id uint64, newPassword string) error { hash, err := auth.HashPassword(newPassword) if err != nil { return errors.Wrap(50000, "hash password", err) } if err := s.repo.Update(ctx, id, map[string]interface{}{"password_hash": hash}); err != nil { return err } s.invalidator.Invalidate(ctx, id) return nil }