mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 22:06:38 +08:00
docs(swagger): restore gold @Router comments on platform APIs
This commit is contained in:
@@ -14,7 +14,17 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ListAuthSources lists all configured authentication sources.
|
||||
// ListAuthSources 获取认证源列表
|
||||
// @Summary 获取认证源列表
|
||||
// @Description 返回所有已配置的 OAuth/OIDC 认证源列表,包括已启用和未启用的,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any "认证源列表"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 403 {object} response.Any "无管理员权限"
|
||||
// @Failure 500 {object} response.Any "内部错误"
|
||||
// @Router /api/v1/admin/auth-sources [get]
|
||||
func ListAuthSources(c *gin.Context) {
|
||||
views, err := service.ListAuthSources(c.Request.Context())
|
||||
if err != nil {
|
||||
@@ -25,7 +35,19 @@ func ListAuthSources(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(views))
|
||||
}
|
||||
|
||||
// CreateAuthSource creates a new authentication source.
|
||||
// CreateAuthSource 创建认证源
|
||||
// @Summary 创建认证源
|
||||
// @Description 创建一个新的 OAuth/OIDC 认证源配置,认证源名称必须唯一且符合命名规范,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param request body contracts.AuthSourceDTO true "创建认证源参数"
|
||||
// @Success 200 {object} response.Any "创建成功,返回认证源信息"
|
||||
// @Failure 400 {object} response.Any "参数错误或验证失败"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 403 {object} response.Any "无管理员权限"
|
||||
// @Router /api/v1/admin/auth-sources [post]
|
||||
func CreateAuthSource(c *gin.Context) {
|
||||
var source contracts.AuthSourceDTO
|
||||
if err := c.ShouldBindJSON(&source); err != nil {
|
||||
@@ -42,7 +64,21 @@ func CreateAuthSource(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(created))
|
||||
}
|
||||
|
||||
// UpdateAuthSource updates an authentication source.
|
||||
// UpdateAuthSource 更新认证源
|
||||
// @Summary 更新认证源
|
||||
// @Description 更新指定 ID 的认证源配置。若 client_secret 字段为空,则保留原有密钥不变,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param id path uint64 true "认证源 ID 或名称"
|
||||
// @Param request body contracts.AuthSourceDTO true "更新认证源参数"
|
||||
// @Success 200 {object} response.Any "更新成功,返回更新后的认证源信息"
|
||||
// @Failure 400 {object} response.Any "参数错误或验证失败"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 403 {object} response.Any "无管理员权限"
|
||||
// @Failure 500 {object} response.Any "内部错误"
|
||||
// @Router /api/v1/admin/auth-sources/{id} [put]
|
||||
func UpdateAuthSource(c *gin.Context) {
|
||||
id, ok := parseAuthSourceID(c)
|
||||
if !ok {
|
||||
@@ -64,7 +100,19 @@ func UpdateAuthSource(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(updated))
|
||||
}
|
||||
|
||||
// ToggleAuthSource toggles the active state of an auth source.
|
||||
// ToggleAuthSource 切换认证源启用状态
|
||||
// @Summary 切换认证源启用状态
|
||||
// @Description 启用或禁用指定认证源。尝试启用时将验证 Client ID 和 Client Secret 是否已配置,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param id path uint64 true "认证源 ID 或名称"
|
||||
// @Success 200 {object} response.Any{data=string} "切换成功"
|
||||
// @Failure 400 {object} response.Any "验证失败或认证源不存在"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 403 {object} response.Any "无管理员权限"
|
||||
// @Router /api/v1/admin/auth-sources/{id}/toggle [put]
|
||||
func ToggleAuthSource(c *gin.Context) {
|
||||
id, ok := parseAuthSourceID(c)
|
||||
if !ok {
|
||||
@@ -80,7 +128,18 @@ func ToggleAuthSource(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(gin.H{"is_active": toggled.IsActive}))
|
||||
}
|
||||
|
||||
// DeleteAuthSource deletes an authentication source.
|
||||
// DeleteAuthSource 删除认证源
|
||||
// @Summary 删除认证源
|
||||
// @Description 删除指定认证源及其关联的所有外部帐号绑定记录,警告:删除后相关用户将无法通过该源登录,需要管理员权限
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param id path uint64 true "认证源 ID 或名称"
|
||||
// @Success 200 {object} response.Any{data=string} "删除成功"
|
||||
// @Failure 400 {object} response.Any "ID 无效或删除失败"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 403 {object} response.Any "无管理员权限"
|
||||
// @Router /api/v1/admin/auth-sources/{id} [delete]
|
||||
func DeleteAuthSource(c *gin.Context) {
|
||||
id, ok := parseAuthSourceID(c)
|
||||
if !ok {
|
||||
|
||||
@@ -25,11 +25,26 @@ import (
|
||||
)
|
||||
|
||||
// GetLoginSources 获取可用登录源列表
|
||||
// @Summary 获取可用登录源
|
||||
// @Description 返回当前系统已启用的所有 OAuth 登录源,前端展示登录按钮列表时调用
|
||||
// @Tags oauth
|
||||
// @Produce json
|
||||
// @Success 200 {object} response.Any{data=[]auth.AuthSourceView} "登录源列表"
|
||||
// @Router /api/v1/oauth/sources [get]
|
||||
func GetLoginSources(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(activeLoginSources(c.Request.Context())))
|
||||
}
|
||||
|
||||
// GetLoginURL 获取登录授权地址
|
||||
// @Summary 获取登录授权地址
|
||||
// @Description 根据指定认证源生成 OAuth 授权 URL,前端跳转到该 URL 完成 OAuth 登录授权。source 参数为空时使用第一个启用的认证源。
|
||||
// @Tags oauth
|
||||
// @Produce json
|
||||
// @Param source query string false "认证源名称,为空使用第一个启用的认证源"
|
||||
// @Success 200 {object} response.Any{data=auth.OAuthAuthorizeResponse} "授权 URL"
|
||||
// @Failure 400 {object} response.Any "认证源不存在或未配置"
|
||||
// @Failure 500 {object} response.Any "构造 URL 失败"
|
||||
// @Router /api/v1/oauth/login [get]
|
||||
func GetLoginURL(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
if !isOIDCLoginEnabled(ctx) {
|
||||
@@ -126,6 +141,16 @@ func reserveOAuthStateSlot(ctx context.Context, sessionHash string) error {
|
||||
}
|
||||
|
||||
// Authorize 发起指定认证源授权
|
||||
// @Summary 发起指定认证源授权
|
||||
// @Description 根据指定认证源名称发起 OAuth 授权,支持 purpose 参数用于区分登录和账号绑定场景。认证源必须已启用。
|
||||
// @Tags oauth
|
||||
// @Produce json
|
||||
// @Param source path string true "认证源名称"
|
||||
// @Param purpose query string false "授权目的:login(登录)或 bind(绑定账号),默认 login"
|
||||
// @Success 200 {object} response.Any{data=auth.OAuthAuthorizeResponse} "授权 URL"
|
||||
// @Failure 400 {object} response.Any "认证源不存在或未启用"
|
||||
// @Failure 500 {object} response.Any "构造 URL 失败"
|
||||
// @Router /api/v1/oauth/{source}/authorize [get]
|
||||
func Authorize(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
if !isOIDCLoginEnabled(ctx) {
|
||||
@@ -197,6 +222,17 @@ func Authorize(c *gin.Context) {
|
||||
}
|
||||
|
||||
// Callback OAuth 回调处理
|
||||
// @Summary OAuth 回调处理
|
||||
// @Description 接收前端传回的 state 和 code,完成 OAuth/OIDC 认证并建立会话。支持登录(login)和账号绑定(bind)两种场景。
|
||||
// @Tags oauth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body auth.CallbackRequest true "回调请求参数"
|
||||
// @Success 200 {object} response.Any{data=auth.OAuthCallbackResult} "登录或绑定成功"
|
||||
// @Failure 400 {object} response.Any "state 无效、参数错误或认证源错误"
|
||||
// @Failure 401 {object} response.Any "绑定场景未登录"
|
||||
// @Failure 500 {object} response.Any "OAuth 认证失败或内部错误"
|
||||
// @Router /api/v1/oauth/callback [post]
|
||||
func Callback(c *gin.Context) {
|
||||
var req CallbackRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -437,6 +473,15 @@ func handleCallbackRegister(ctx context.Context, c *gin.Context, source *AuthSou
|
||||
}
|
||||
|
||||
// UserInfo 获取当前登录用户信息
|
||||
// @Summary 获取当前登录用户信息
|
||||
// @Description 返回当前登录用户的基本信息,需要登录。
|
||||
// @Tags oauth
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any{data=auth.BasicUserInfo} "用户信息"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Router /api/v1/oauth/user-info [get]
|
||||
// @Router /api/v1/user-info [get]
|
||||
func UserInfo(c *gin.Context) {
|
||||
user, _ := ginutil.GetFromContext[*contracts.UserDTO](c, contracts.AuthUserObjKey)
|
||||
session := sessions.Default(c)
|
||||
@@ -449,6 +494,14 @@ func UserInfo(c *gin.Context) {
|
||||
}
|
||||
|
||||
// Logout 退出登录
|
||||
// @Summary 退出登录
|
||||
// @Description 清除当前用户的登录会话,完成退出。清除 Cookie 中的 Session 数据。
|
||||
// @Tags oauth
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any{data=string} "退出成功"
|
||||
// @Failure 500 {object} response.Any "Session 清除失败"
|
||||
// @Router /api/v1/oauth/logout [get]
|
||||
func Logout(c *gin.Context) {
|
||||
session := sessions.Default(c)
|
||||
userID := session.Get(UserIDKey)
|
||||
@@ -469,6 +522,15 @@ func Logout(c *gin.Context) {
|
||||
}
|
||||
|
||||
// ListExternalAccounts 获取当前用户的外部帐号绑定列表
|
||||
// @Summary 获取外部帐号列表
|
||||
// @Description 返回当前登录用户已绑定的所有外部 OAuth 帐号信息,需要登录
|
||||
// @Tags oauth
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any "外部帐号列表"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 500 {object} response.Any "内部错误"
|
||||
// @Router /api/v1/oauth/external-accounts [get]
|
||||
func ListExternalAccounts(c *gin.Context) {
|
||||
userID := GetUserIDFromContext(c)
|
||||
accounts, err := ListExternalAccountsByUserID(c.Request.Context(), userID)
|
||||
@@ -480,6 +542,16 @@ func ListExternalAccounts(c *gin.Context) {
|
||||
}
|
||||
|
||||
// DeleteExternalAccount 解除外部帐号绑定
|
||||
// @Summary 解除外部帐号绑定
|
||||
// @Description 解除当前登录用户与指定外部帐号的绑定关系,需要登录
|
||||
// @Tags oauth
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param id path uint64 true "外部帐号绑定记录 ID"
|
||||
// @Success 200 {object} response.Any{data=string} "解除绑定成功"
|
||||
// @Failure 400 {object} response.Any "ID 无效或解除失败"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Router /api/v1/oauth/external-accounts/{id}/delete [post]
|
||||
func DeleteExternalAccount(c *gin.Context) {
|
||||
userID := GetUserIDFromContext(c)
|
||||
if userID == 0 {
|
||||
|
||||
@@ -15,12 +15,26 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ListPushChannelDefinitions returns channel definitions.
|
||||
// ListPushChannelDefinitions 获取各种消息通道的表单配置定义列表
|
||||
// @Summary 获取所有消息通道配置字段定义
|
||||
// @Description 返回系统支持的所有消息通道类型的动态表单定义,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any "通道配置定义列表"
|
||||
// @Router /api/v1/admin/push/channels/definitions [get]
|
||||
func ListPushChannelDefinitions(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(model.ListPushDefinitions()))
|
||||
}
|
||||
|
||||
// ListPushChannels lists configured push channels.
|
||||
// ListPushChannels 获取消息通道列表
|
||||
// @Summary 获取所有消息通道
|
||||
// @Description 返回系统配置的所有消息通道列表,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any{data=[]model.PushChannel} "消息通道列表"
|
||||
// @Router /api/v1/admin/push/channels [get]
|
||||
func ListPushChannels(c *gin.Context) {
|
||||
channels, err := service.ListPushChannels(c.Request.Context())
|
||||
if err != nil {
|
||||
@@ -49,19 +63,46 @@ func handlePushChannelNotFoundError(c *gin.Context, err error, fallback func(c *
|
||||
fallback(c, err.Error())
|
||||
}
|
||||
|
||||
// CreatePushChannel creates a push channel.
|
||||
// CreatePushChannel 创建消息通道
|
||||
// @Summary 创建消息通道
|
||||
// @Description 新建一个消息通道配置,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param request body model.CreatePushChannelRequest true "创建参数"
|
||||
// @Success 200 {object} response.Any{data=model.PushChannel} "创建成功"
|
||||
// @Router /api/v1/admin/push/channels [post]
|
||||
func CreatePushChannel(c *gin.Context) {
|
||||
handleJSONRequest(c, service.CreatePushChannel)
|
||||
}
|
||||
|
||||
// UpdatePushChannel updates a push channel.
|
||||
// UpdatePushChannel 更新消息通道
|
||||
// @Summary 更新消息通道
|
||||
// @Description 修改消息通道配置,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param id path uint64 true "通道ID"
|
||||
// @Param request body model.UpdatePushChannelRequest true "更新参数"
|
||||
// @Success 200 {object} response.Any{data=model.PushChannel} "更新成功"
|
||||
// @Router /api/v1/admin/push/channels/{id} [put]
|
||||
func UpdatePushChannel(c *gin.Context) {
|
||||
handleEntityUpdate(c, parsePushChannelID, service.UpdatePushChannel, func(c *gin.Context, err error) {
|
||||
handlePushChannelNotFoundError(c, err, response.AbortInternal)
|
||||
})
|
||||
}
|
||||
|
||||
// DeletePushChannel deletes a push channel.
|
||||
// DeletePushChannel 删除消息通道
|
||||
// @Summary 删除消息通道
|
||||
// @Description 根据ID删除消息通道,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param id path uint64 true "通道ID"
|
||||
// @Success 200 {object} response.Any "删除成功"
|
||||
// @Router /api/v1/admin/push/channels/{id} [delete]
|
||||
func DeletePushChannel(c *gin.Context) {
|
||||
id, ok := parsePushChannelID(c)
|
||||
if !ok {
|
||||
@@ -75,7 +116,16 @@ func DeletePushChannel(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
}
|
||||
|
||||
// TestPushChannel tests connectivity of a push channel.
|
||||
// TestPushChannel 测试通道连通性
|
||||
// @Summary 测试通道连通性
|
||||
// @Description 触发一次临时的或现有的通道连通性推送测试,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param request body model.TestPushChannelRequest true "测试参数"
|
||||
// @Success 200 {object} response.Any "测试触发成功"
|
||||
// @Router /api/v1/admin/push/channels/test [post]
|
||||
func TestPushChannel(c *gin.Context) {
|
||||
var req model.TestPushChannelRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -15,7 +15,14 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ListPushEvents lists configured push events.
|
||||
// ListPushEvents 获取通知事件列表
|
||||
// @Summary 获取所有通知事件
|
||||
// @Description 返回系统配置的通知事件列表,包括预置和自定义事件,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any{data=[]model.PushEvent} "通知事件列表"
|
||||
// @Router /api/v1/admin/push/events [get]
|
||||
func ListPushEvents(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
events, err := service.ListPushEvents(ctx)
|
||||
@@ -26,7 +33,14 @@ func ListPushEvents(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(events))
|
||||
}
|
||||
|
||||
// ListBuiltInPushEvents lists system built-in push event definitions.
|
||||
// ListBuiltInPushEvents 获取内置通知事件列表
|
||||
// @Summary 获取所有内置通知事件
|
||||
// @Description 返回系统定义的所有内置通知事件元数据,供前端下拉框选择,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any "内置通知事件列表"
|
||||
// @Router /api/v1/admin/push/events/builtin [get]
|
||||
func ListBuiltInPushEvents(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(service.GetBuiltInEvents()))
|
||||
}
|
||||
@@ -50,12 +64,29 @@ func handlePushEventNotFoundError(c *gin.Context, err error, fallback func(c *gi
|
||||
fallback(c, err.Error())
|
||||
}
|
||||
|
||||
// CreatePushEvent creates a new push event configuration.
|
||||
// CreatePushEvent 创建通知事件
|
||||
// @Summary 创建通知事件
|
||||
// @Description 绑定系统内置事件或异步任务、推送渠道、接收目标并创建通知事件配置,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param request body model.CreatePushEventRequest true "创建参数"
|
||||
// @Success 200 {object} response.Any{data=model.PushEvent} "创建成功"
|
||||
// @Router /api/v1/admin/push/events [post]
|
||||
func CreatePushEvent(c *gin.Context) {
|
||||
handleJSONRequest(c, service.CreatePushEvent)
|
||||
}
|
||||
|
||||
// DeletePushEvent deletes a push event configuration by ID.
|
||||
// DeletePushEvent 删除通知事件配置
|
||||
// @Summary 删除通知事件配置
|
||||
// @Description 删除数据库中的特定通知事件配置,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param id path int true "事件 ID"
|
||||
// @Success 200 {object} response.Any{data=string} "删除成功"
|
||||
// @Router /api/v1/admin/push/events/{id} [delete]
|
||||
func DeletePushEvent(c *gin.Context) {
|
||||
id, ok := parsePushEventID(c)
|
||||
if !ok {
|
||||
@@ -69,7 +100,17 @@ func DeletePushEvent(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
}
|
||||
|
||||
// UpdatePushEvent updates an existing push event.
|
||||
// UpdatePushEvent 更新通知事件
|
||||
// @Summary 更新通知事件
|
||||
// @Description 更新已有通知事件的推送渠道、接收目标和内容模板,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param id path int true "事件 ID"
|
||||
// @Param request body model.UpdatePushEventRequest true "更新参数"
|
||||
// @Success 200 {object} response.Any{data=string} "修改成功"
|
||||
// @Router /api/v1/admin/push/events/{id} [put]
|
||||
func UpdatePushEvent(c *gin.Context) {
|
||||
id, ok := parsePushEventID(c)
|
||||
if !ok {
|
||||
@@ -89,7 +130,15 @@ func UpdatePushEvent(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
}
|
||||
|
||||
// TogglePushEvent toggles the enabled state of a push event.
|
||||
// TogglePushEvent 快捷切换通知事件启用状态
|
||||
// @Summary 快捷切换通知事件启用状态
|
||||
// @Description 启用或禁用指定的通知事件
|
||||
// @Tags admin-push
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param id path int true "事件 ID"
|
||||
// @Success 200 {object} response.Any{data=string} "切换成功"
|
||||
// @Router /api/v1/admin/push/events/{id}/toggle [post]
|
||||
func TogglePushEvent(c *gin.Context) {
|
||||
id, ok := parsePushEventID(c)
|
||||
if !ok {
|
||||
@@ -104,7 +153,18 @@ func TogglePushEvent(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(enabled))
|
||||
}
|
||||
|
||||
// ListPushHistories returns paginated push notification delivery histories.
|
||||
// ListPushHistories 分页获取通知推送历史
|
||||
// @Summary 分页获取通知推送历史
|
||||
// @Description 返回分页的通知历史日志数据,需要管理员权限
|
||||
// @Tags admin-push
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param page query int false "当前页码"
|
||||
// @Param page_size query int false "分页大小"
|
||||
// @Param event_key query string false "过滤事件名称"
|
||||
// @Param status query string false "过滤发送状态"
|
||||
// @Success 200 {object} response.Any "推送历史列表"
|
||||
// @Router /api/v1/admin/push/histories [get]
|
||||
func ListPushHistories(c *gin.Context) {
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
@@ -132,7 +192,16 @@ func ListPushHistories(c *gin.Context) {
|
||||
}))
|
||||
}
|
||||
|
||||
// TestPush executes a synchronous push test using the specified config.
|
||||
// TestPush 测试推送通道发送
|
||||
// @Summary 测试推送通道发送
|
||||
// @Description 接收临时通知渠道配置并在本地同步调用 Pusher.Send 发送测试消息
|
||||
// @Tags admin-push
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Param request body model.TestPushRequest true "测试请求体"
|
||||
// @Success 200 {object} response.Any{data=string} "测试成功"
|
||||
// @Router /api/v1/admin/push/test [post]
|
||||
func TestPush(c *gin.Context) {
|
||||
var req model.TestPushRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
|
||||
@@ -56,9 +56,7 @@ func (p *Plugin) Apply(ctx *core.Context) error {
|
||||
ctx.Router().GET("/api/healthz", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
||||
})
|
||||
ctx.Router().GET("/api/health", func(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
})
|
||||
ctx.Router().GET("/api/health", Health)
|
||||
ctx.Router().RegisterWhitelist("/api/health")
|
||||
|
||||
// 2. Public config
|
||||
@@ -92,3 +90,14 @@ func (p *Plugin) Apply(ctx *core.Context) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Health 健康检查
|
||||
// @Summary 健康检查
|
||||
// @Description 检查服务是否正常运行,可用于负载均衡存活探测
|
||||
// @Tags health
|
||||
// @Produce json
|
||||
// @Success 200 {object} response.Any{data=string} "服务正常"
|
||||
// @Router /api/health [get]
|
||||
func Health(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ type listFilesResponse struct {
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any{data=listFilesResponse} "查询成功"
|
||||
// @Failure 400 {object} response.Any "参数错误"
|
||||
// @Router /api/v1/admin/uploads [get]
|
||||
// @Router /api/v1/admin/uploads/files [get]
|
||||
func ListFiles(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
@@ -96,6 +97,7 @@ func ListFiles(c *gin.Context) {
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any "删除成功"
|
||||
// @Failure 404 {object} response.Any "文件不存在"
|
||||
// @Router /api/v1/admin/uploads/{id} [delete]
|
||||
// @Router /api/v1/admin/uploads/files/{id} [delete]
|
||||
func DeleteFile(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
@@ -77,7 +77,17 @@ func invalidateTokenCache(ctx context.Context, tokenHash string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Login handles username and password authentication.
|
||||
// Login 用户密码登录
|
||||
// @Summary 用户密码登录
|
||||
// @Description 使用用户名和密码登录,登录成功后建立 Session。若管理员已关闭密码登录功能则返回错误。
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body user.loginRequest true "登录请求参数"
|
||||
// @Success 200 {object} response.Any "登录成功,返回用户信息"
|
||||
// @Failure 400 {object} response.Any "用户名或密码错误"
|
||||
// @Failure 500 {object} response.Any "服务内部错误"
|
||||
// @Router /api/v1/user/login [post]
|
||||
func Login(c *gin.Context) {
|
||||
var req loginRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -109,7 +119,17 @@ func Login(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(user))
|
||||
}
|
||||
|
||||
// Register registers a new user.
|
||||
// Register 用户注册
|
||||
// @Summary 用户注册
|
||||
// @Description 使用用户名和密码注册新账号,注册成功后自动登录并建立 Session。
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body user.registerRequest true "注册请求参数"
|
||||
// @Success 200 {object} response.Any "注册并登录成功,返回用户信息"
|
||||
// @Failure 400 {object} response.Any "参数错误、用户名已存在或注册已关闭"
|
||||
// @Failure 500 {object} response.Any "服务内部错误"
|
||||
// @Router /api/v1/user/register [post]
|
||||
func Register(c *gin.Context) {
|
||||
var req registerRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -142,7 +162,15 @@ func Register(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(newUser))
|
||||
}
|
||||
|
||||
// Logout logs out the current session.
|
||||
// Logout 用户退出登录
|
||||
// @Summary 用户退出登录
|
||||
// @Description 清除用户登录 Session,完成退出
|
||||
// @Tags user
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any{data=string} "退出成功"
|
||||
// @Failure 500 {object} response.Any "Session 清除失败"
|
||||
// @Router /api/v1/user/logout [get]
|
||||
func Logout(c *gin.Context) {
|
||||
sess := sessions.Default(c)
|
||||
sess.Options(sessions.Options{
|
||||
@@ -156,12 +184,30 @@ func Logout(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
}
|
||||
|
||||
// SendEmailCode sends an email verification code.
|
||||
// SendEmailCode 发送邮箱验证码
|
||||
// @Summary 发送邮箱验证码
|
||||
// @Description 向指定邮箱发送验证码(用于注册场景)
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} response.Any "发送成功"
|
||||
// @Failure 400 {object} response.Any "参数错误"
|
||||
// @Router /api/v1/user/send-email-code [post]
|
||||
func SendEmailCode(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(gin.H{"sent": true}))
|
||||
}
|
||||
|
||||
// ChangePassword changes the current user password.
|
||||
// ChangePassword 修改用户密码
|
||||
// @Summary 修改用户密码
|
||||
// @Description 修改当前登录用户的密码。
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body user.changePasswordRequest true "修改密码请求参数"
|
||||
// @Success 200 {object} response.Any{data=string} "修改密码成功"
|
||||
// @Failure 400 {object} response.Any "原密码错误或新密码不符合要求"
|
||||
// @Failure 401 {object} response.Any "请先登录"
|
||||
// @Router /api/v1/user/change-password [post]
|
||||
func ChangePassword(c *gin.Context) {
|
||||
var req changePasswordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -200,7 +246,15 @@ func ChangePassword(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
}
|
||||
|
||||
// Self returns the current authenticated user.
|
||||
// Self 获取当前登录用户信息
|
||||
// @Summary 获取当前登录用户信息
|
||||
// @Description 返回当前登录用户的基本信息,需要登录。
|
||||
// @Tags user
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any "用户信息"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Router /api/v1/user/self [get]
|
||||
func Self(c *gin.Context) {
|
||||
svc := getAuthService()
|
||||
if svc == nil {
|
||||
@@ -216,7 +270,17 @@ func Self(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(user))
|
||||
}
|
||||
|
||||
// UpdateProfile updates profile info.
|
||||
// UpdateProfile 修改当前登录用户的个人资料
|
||||
// @Summary 修改当前登录用户的个人资料
|
||||
// @Description 修改当前登录用户的昵称、头像、简介、电话、性别、个人网站和所在地。
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body user.updateProfileRequest true "更新请求参数"
|
||||
// @Success 200 {object} response.Any "修改成功,返回更新后的用户信息"
|
||||
// @Failure 400 {object} response.Any "参数错误"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Router /api/v1/user/profile [put]
|
||||
func UpdateProfile(c *gin.Context) {
|
||||
var req updateProfileRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -247,7 +311,15 @@ func UpdateProfile(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OK(user))
|
||||
}
|
||||
|
||||
// ListAccessTokens lists access tokens for the current user.
|
||||
// ListAccessTokens 获取当前用户的 AccessToken 列表
|
||||
// @Summary 获取当前用户的 AccessToken 列表
|
||||
// @Description 返回当前登录用户的所有 active access tokens(脱敏后)
|
||||
// @Tags user
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any{data=[]user.AccessToken} "令牌列表"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Router /api/v1/user/access-tokens [get]
|
||||
func ListAccessTokens(c *gin.Context) {
|
||||
userID := getUserIDFromSession(c)
|
||||
tokens, err := listAccessTokensByUser(c.Request.Context(), userID)
|
||||
@@ -262,7 +334,17 @@ const (
|
||||
tokenMaskMinLength = 8
|
||||
)
|
||||
|
||||
// CreateAccessToken generates a new access token.
|
||||
// CreateAccessToken 创建一个新的 AccessToken
|
||||
// @Summary 创建一个新的 AccessToken
|
||||
// @Description 为当前用户新建一个 API 访问令牌,仅在此接口返回一次明文令牌值,请妥善保存。
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body user.createAccessTokenRequest true "令牌名称"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any "新建令牌成功"
|
||||
// @Failure 400 {object} response.Any "参数错误或超限"
|
||||
// @Router /api/v1/user/access-tokens [post]
|
||||
func CreateAccessToken(c *gin.Context) {
|
||||
var req createAccessTokenRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -301,7 +383,16 @@ func CreateAccessToken(c *gin.Context) {
|
||||
}))
|
||||
}
|
||||
|
||||
// DeleteAccessToken deletes a specific access token.
|
||||
// DeleteAccessToken 删除一个 AccessToken
|
||||
// @Summary 删除一个 AccessToken
|
||||
// @Description 撤销并删除一个属于当前用户的 API 访问令牌
|
||||
// @Tags user
|
||||
// @Produce json
|
||||
// @Param id path string true "令牌ID"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any{data=string} "删除成功"
|
||||
// @Failure 400 {object} response.Any "参数错误"
|
||||
// @Router /api/v1/user/access-tokens/{id} [delete]
|
||||
func DeleteAccessToken(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
@@ -324,7 +415,16 @@ func DeleteAccessToken(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
}
|
||||
|
||||
// RotateAccessToken rotates an access token value.
|
||||
// RotateAccessToken 轮换一个 AccessToken
|
||||
// @Summary 轮换一个 AccessToken
|
||||
// @Description 轮换(重新生成)一个属于当前用户的 API 访问令牌的密钥,旧令牌将立即失效
|
||||
// @Tags user
|
||||
// @Produce json
|
||||
// @Param id path string true "令牌ID"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} response.Any "令牌轮换成功"
|
||||
// @Failure 400 {object} response.Any "参数错误"
|
||||
// @Router /api/v1/user/access-tokens/{id}/rotate [post]
|
||||
func RotateAccessToken(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
|
||||
Reference in New Issue
Block a user