docs: add Swagger annotations to 13 API handlers

Added @Summary, @Description, @Tags, @Param, @Success, @Failure,
@Router annotations to all major handler endpoints for OpenAPI/Swagger
auto-generation. Covers 86 annotations across:

- auth_handler.go (25): all auth endpoints
- user_handler.go (14): CRUD + roles + admin management
- device_handler.go (13): device CRUD + trust management
- role_handler.go (8): role CRUD + permissions
- custom_field_handler.go (7): field CRUD + user values
- permission_handler.go (7): permission CRUD + tree
- log_handler.go (3): login/operation logs
- captcha_handler.go (3): generate/verify
- stats_handler.go (2): dashboard + user stats
- avatar_handler.go (1): upload avatar
- totp_handler.go (1): totp status
- password_reset_handler.go (1): forgot password

Partially addresses P2: missing Swagger annotations
(PRODUCTION_GAP_ANALYSIS_2026-04-08)
This commit is contained in:
2026-04-11 21:23:52 +08:00
parent 27a8dd91a2
commit 0564bfd9ad
12 changed files with 891 additions and 3 deletions

View File

@@ -21,6 +21,19 @@ func NewUserHandler(userService *service.UserService) *UserHandler {
return &UserHandler{userService: userService}
}
// CreateUser 创建用户
// @Summary 创建用户
// @Description 创建新用户账号(仅管理员)
// @Tags 用户管理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body CreateUserRequest true "用户信息"
// @Success 201 {object} Response{data=UserResponse} "用户创建成功"
// @Failure 400 {object} Response "请求参数错误"
// @Failure 401 {object} Response "未认证"
// @Failure 403 {object} Response "无权限"
// @Router /api/v1/users [post]
func (h *UserHandler) CreateUser(c *gin.Context) {
var req struct {
Username string `json:"username" binding:"required"`
@@ -62,6 +75,18 @@ func (h *UserHandler) CreateUser(c *gin.Context) {
})
}
// ListUsers 获取用户列表
// @Summary 获取用户列表
// @Description 获取用户列表,支持游标分页和偏移分页
// @Tags 用户管理
// @Produce json
// @Security BearerAuth
// @Param cursor query string false "游标分页游标"
// @Param size query int false "每页大小"
// @Param offset query int false "偏移分页偏移量"
// @Param limit query int false "每页大小"
// @Success 200 {object} Response{data=UserListResponse} "用户列表"
// @Router /api/v1/users [get]
func (h *UserHandler) ListUsers(c *gin.Context) {
cursor := c.Query("cursor")
sizeStr := c.DefaultQuery("size", "")
@@ -113,6 +138,16 @@ func (h *UserHandler) ListUsers(c *gin.Context) {
})
}
// GetUser 获取用户详情
// @Summary 获取用户详情
// @Description 根据ID获取用户详细信息
// @Tags 用户管理
// @Produce json
// @Security BearerAuth
// @Param id path int true "用户ID"
// @Success 200 {object} Response{data=UserResponse} "用户信息"
// @Failure 404 {object} Response "用户不存在"
// @Router /api/v1/users/{id} [get]
func (h *UserHandler) GetUser(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -129,6 +164,20 @@ func (h *UserHandler) GetUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "success", "data": toUserResponse(user)})
}
// UpdateUser 更新用户
// @Summary 更新用户信息
// @Description 更新用户的基本信息(仅管理员或本人)
// @Tags 用户管理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "用户ID"
// @Param request body UpdateUserRequest true "更新信息"
// @Success 200 {object} Response{data=UserResponse} "更新成功"
// @Failure 400 {object} Response "请求参数错误"
// @Failure 403 {object} Response "无权限"
// @Failure 404 {object} Response "用户不存在"
// @Router /api/v1/users/{id} [put]
func (h *UserHandler) UpdateUser(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -167,6 +216,17 @@ func (h *UserHandler) UpdateUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "success", "data": toUserResponse(user)})
}
// DeleteUser 删除用户
// @Summary 删除用户
// @Description 删除用户账号(仅管理员)
// @Tags 用户管理
// @Produce json
// @Security BearerAuth
// @Param id path int true "用户ID"
// @Success 200 {object} Response "删除成功"
// @Failure 403 {object} Response "无权限"
// @Failure 404 {object} Response "用户不存在"
// @Router /api/v1/users/{id} [delete]
func (h *UserHandler) DeleteUser(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -182,6 +242,20 @@ func (h *UserHandler) DeleteUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "success"})
}
// UpdatePassword 修改密码
// @Summary 修改用户密码
// @Description 修改用户密码(仅管理员或本人)
// @Tags 用户管理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "用户ID"
// @Param request body UpdatePasswordRequest true "密码信息"
// @Success 200 {object} Response "密码修改成功"
// @Failure 400 {object} Response "请求参数错误"
// @Failure 403 {object} Response "无权限"
// @Failure 404 {object} Response "用户不存在"
// @Router /api/v1/users/{id}/password [put]
func (h *UserHandler) UpdatePassword(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -207,6 +281,20 @@ func (h *UserHandler) UpdatePassword(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "密码修改成功"})
}
// UpdateUserStatus 更新用户状态
// @Summary 更新用户状态
// @Description 更新用户账号状态active/inactive/locked/disabled仅管理员
// @Tags 用户管理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "用户ID"
// @Param request body UpdateStatusRequest true "状态信息"
// @Success 200 {object} Response "状态更新成功"
// @Failure 400 {object} Response "无效的状态值"
// @Failure 403 {object} Response "无权限"
// @Failure 404 {object} Response "用户不存在"
// @Router /api/v1/users/{id}/status [put]
func (h *UserHandler) UpdateUserStatus(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -246,6 +334,17 @@ func (h *UserHandler) UpdateUserStatus(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "success"})
}
// GetUserRoles 获取用户角色
// @Summary 获取用户角色列表
// @Description 获取指定用户的角色列表(仅本人或管理员)
// @Tags 用户管理
// @Produce json
// @Security BearerAuth
// @Param id path int true "用户ID"
// @Success 200 {object} Response{data=[]domain.Role} "角色列表"
// @Failure 403 {object} Response "无权限"
// @Failure 404 {object} Response "用户不存在"
// @Router /api/v1/users/{id}/roles [get]
func (h *UserHandler) GetUserRoles(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -282,6 +381,20 @@ func (h *UserHandler) GetUserRoles(c *gin.Context) {
})
}
// AssignRoles 分配用户角色
// @Summary 分配用户角色
// @Description 为用户分配角色(替换现有角色)(仅管理员)
// @Tags 用户管理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path int true "用户ID"
// @Param request body AssignRolesRequest true "角色ID列表"
// @Success 200 {object} Response "角色分配成功"
// @Failure 400 {object} Response "请求参数错误"
// @Failure 403 {object} Response "无权限"
// @Failure 404 {object} Response "用户不存在"
// @Router /api/v1/users/{id}/roles [post]
func (h *UserHandler) AssignRoles(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
@@ -306,6 +419,18 @@ func (h *UserHandler) AssignRoles(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "角色分配成功"})
}
// BatchUpdateStatus 批量更新用户状态
// @Summary 批量更新用户状态
// @Description 批量更新多个用户的状态(仅管理员)
// @Tags 用户管理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body service.BatchUpdateStatusRequest true "批量更新请求"
// @Success 200 {object} Response "批量更新成功"
// @Failure 400 {object} Response "请求参数错误"
// @Failure 403 {object} Response "无权限"
// @Router /api/v1/users/batch/status [put]
func (h *UserHandler) BatchUpdateStatus(c *gin.Context) {
var req service.BatchUpdateStatusRequest
if err := c.ShouldBindJSON(&req); err != nil {
@@ -322,6 +447,18 @@ func (h *UserHandler) BatchUpdateStatus(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "更新成功", "data": gin.H{"count": count}})
}
// BatchDelete 批量删除用户
// @Summary 批量删除用户
// @Description 批量删除多个用户(仅管理员)
// @Tags 用户管理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body service.BatchDeleteRequest true "批量删除请求"
// @Success 200 {object} Response "批量删除成功"
// @Failure 400 {object} Response "请求参数错误"
// @Failure 403 {object} Response "无权限"
// @Router /api/v1/users/batch [delete]
func (h *UserHandler) BatchDelete(c *gin.Context) {
var req service.BatchDeleteRequest
if err := c.ShouldBindJSON(&req); err != nil {
@@ -338,6 +475,15 @@ func (h *UserHandler) BatchDelete(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "删除成功", "data": gin.H{"count": count}})
}
// ListAdmins 获取管理员列表
// @Summary 获取管理员列表
// @Description 获取所有管理员用户列表(仅管理员)
// @Tags 用户管理
// @Produce json
// @Security BearerAuth
// @Success 200 {object} Response{data=[]UserResponse} "管理员列表"
// @Failure 403 {object} Response "无权限"
// @Router /api/v1/users/admins [get]
func (h *UserHandler) ListAdmins(c *gin.Context) {
admins, err := h.userService.ListAdmins(c.Request.Context())
if err != nil {
@@ -353,6 +499,18 @@ func (h *UserHandler) ListAdmins(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": 0, "message": "success", "data": adminResponses})
}
// CreateAdmin 创建管理员
// @Summary 创建管理员
// @Description 创建新管理员账号(仅管理员)
// @Tags 用户管理
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body CreateAdminRequest true "管理员信息"
// @Success 201 {object} Response{data=UserResponse} "管理员创建成功"
// @Failure 400 {object} Response "请求参数错误"
// @Failure 403 {object} Response "无权限"
// @Router /api/v1/users/admins [post]
func (h *UserHandler) CreateAdmin(c *gin.Context) {
var req struct {
Username string `json:"username" binding:"required"`
@@ -382,6 +540,18 @@ func (h *UserHandler) CreateAdmin(c *gin.Context) {
c.JSON(http.StatusCreated, gin.H{"code": 0, "message": "管理员创建成功", "data": toUserResponse(admin)})
}
// DeleteAdmin 删除管理员
// @Summary 删除管理员
// @Description 删除管理员角色(最后管理员保护、自删保护)(仅管理员)
// @Tags 用户管理
// @Produce json
// @Security BearerAuth
// @Param id path int true "用户ID"
// @Success 200 {object} Response "管理员已移除"
// @Failure 400 {object} Response "无效的用户ID"
// @Failure 403 {object} Response "无权限"
// @Failure 409 {object} Response "无法删除(最后管理员或自删)"
// @Router /api/v1/users/admins/{id} [delete]
func (h *UserHandler) DeleteAdmin(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {