package controllers import ( "strconv" "lokistack/dto" "lokistack/models" "lokistack/pkg/jwt" "lokistack/services" "lokistack/utils" "github.com/gin-gonic/gin" ) // UserController 用户管理(全部端点仅 admin 可用,无 RBAC) type UserController struct { service *services.AuthService } func NewUserController() *UserController { return &UserController{service: services.NewAuthService()} } // List 分页返回用户列表(Sanitized 输出,密码哈希不出库) func (ctrl *UserController) List(c *gin.Context) { page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20")) if page < 1 { page = 1 } if pageSize < 1 || pageSize > 100 { pageSize = 20 } users, total := ctrl.service.ListUsers(page, pageSize) list := make([]map[string]interface{}, len(users)) for i := range users { list[i] = users[i].Sanitized() } utils.Success(c, utils.PageData{List: list, Total: total, Page: page, PageSize: pageSize}) } // Create 创建用户(原 /auth/register 逻辑收编至此) func (ctrl *UserController) Create(c *gin.Context) { var req dto.UserCreateRequest if !utils.BindAndValidate(c, &req) { return } role := req.Role if role == "" { role = "user" } user, err := ctrl.service.Register(req.Username, req.Password, req.Nickname, role) if err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, models.SanitizedJSON(user)) } // Delete 删除用户(守卫:不能删自己 / 最后一个 admin) func (ctrl *UserController) Delete(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { utils.BadRequest(c, "无效的用户 ID") return } claims, ok := jwt.GetUserFromContext(c) if !ok { utils.Unauthorized(c, "") return } if err := ctrl.service.DeleteUser(uint(id), claims.UserID); err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, gin.H{"message": "user deleted"}) } // BatchDelete 批量删除用户;逐个应用守卫(不能删自己/最后一个 admin),失败项单独返回不阻断整体 func (ctrl *UserController) BatchDelete(c *gin.Context) { var req dto.BatchDeleteUsersRequest if !utils.BindAndValidate(c, &req) { return } claims, ok := jwt.GetUserFromContext(c) if !ok { utils.Unauthorized(c, "") return } deleted, failures := ctrl.service.BatchDeleteUsers(req.IDs, claims.UserID) utils.Success(c, gin.H{"deleted": deleted, "failures": failures}) } // ResetPassword 管理员重置密码(递增 TokenVersion,目标用户旧会话全部失效) func (ctrl *UserController) ResetPassword(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil { utils.BadRequest(c, "无效的用户 ID") return } var req dto.ResetPasswordRequest if !utils.BindAndValidate(c, &req) { return } if err := ctrl.service.ResetPassword(uint(id), req.NewPassword); err != nil { utils.Error(c, 400, err.Error()) return } utils.Success(c, gin.H{"message": "password reset"}) } // BatchImportLDAP 从 LDAP 批量导入用户(冲突策略见 services.BatchImportLDAPUsers) func (ctrl *UserController) BatchImportLDAP(c *gin.Context) { var req dto.LdapImportRequest if !utils.BindAndValidate(c, &req) { return } users := make([]services.LDAPImportUser, 0, len(req.Users)) for _, u := range req.Users { users = append(users, services.LDAPImportUser{DN: u.DN, Username: u.Username, Nickname: u.Nickname, Email: u.Email}) } result := services.BatchImportLDAPUsers(users) utils.Success(c, result) }