mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 14:06:36 +08:00
455e2f8be5
Public config now comes from admin as a flat visibility=1 map instead of a cross-plugin query that compared an integer column to "visible". Login and register resolve CaptchaService per request so CAP is not skipped when user applies before cap.
188 lines
6.4 KiB
Go
188 lines
6.4 KiB
Go
// Copyright 2026 Arctel.net
|
||
// SPDX-License-Identifier: Apache-2.0
|
||
|
||
package handler
|
||
|
||
import (
|
||
"Wavelet/pkg/response"
|
||
"Wavelet/plugins/domain/admin/errs"
|
||
"Wavelet/plugins/domain/admin/model"
|
||
"Wavelet/plugins/domain/admin/service"
|
||
"errors"
|
||
"net/http"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
// GetPublicConfig 获取公共配置
|
||
// @Summary 获取公共配置
|
||
// @Description 返回系统配置表中 visibility 为 1 的扁平键值集合(如 cap_login_enabled)
|
||
// @Tags config
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Success 200 {object} response.Any
|
||
// @Router /api/v1/config/public [get]
|
||
func GetPublicConfig(c *gin.Context) {
|
||
resp, err := service.PublicSystemConfigs(c.Request.Context())
|
||
if err != nil {
|
||
response.AbortInternal(c, err.Error())
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, response.OK(resp))
|
||
}
|
||
|
||
// GetRobotsTXT 动态生成 robots.txt
|
||
// @Summary 获取 robots.txt
|
||
// @Description 根据系统配置决定是否允许搜索引擎检索,并返回相应的 robots.txt 文件内容
|
||
// @Tags config
|
||
// @Produce text/plain
|
||
// @Success 200 {string} string "robots.txt 内容"
|
||
// @Router /robots.txt [get]
|
||
func GetRobotsTXT(c *gin.Context) {
|
||
c.Data(http.StatusOK, "text/plain; charset=utf-8", []byte(service.RobotsTxtBody(c.Request.Context())))
|
||
}
|
||
|
||
// CreateSystemConfig 创建系统配置
|
||
// @Summary 创建系统配置
|
||
// @Description 创建一条新的系统配置项,配置键不可重复,同时将新配置同步到 Redis,需要管理员权限
|
||
// @Tags admin
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security SessionCookie
|
||
// @Param request body model.CreateSystemConfigRequest true "创建请求参数"
|
||
// @Success 200 {object} response.Any{data=string} "创建成功"
|
||
// @Failure 400 {object} response.Any "参数错误或配置键已存在"
|
||
// @Failure 401 {object} response.Any "未登录"
|
||
// @Failure 403 {object} response.Any "无管理员权限"
|
||
// @Failure 500 {object} response.Any "内部错误"
|
||
// @Router /api/v1/admin/system-configs [post]
|
||
func CreateSystemConfig(c *gin.Context) {
|
||
var req model.CreateSystemConfigRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.AbortBadRequest(c, err.Error())
|
||
return
|
||
}
|
||
|
||
if err := service.CreateAdminSystemConfig(c.Request.Context(), req); err != nil {
|
||
if errors.Is(err, errs.ErrProtectedConfigKey) || errors.Is(err, errs.ErrConfigKeyExists) {
|
||
response.AbortBadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.AbortInternal(c, err.Error())
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, response.OKNil())
|
||
}
|
||
|
||
// ListSystemConfigs 获取系统配置列表
|
||
// @Summary 获取系统配置列表
|
||
// @Description 返回所有系统配置列表,支持按配置类型(system/business)过滤,需要管理员权限
|
||
// @Tags admin
|
||
// @Produce json
|
||
// @Security SessionCookie
|
||
// @Param type query string false "配置类型(system/business)"
|
||
// @Success 200 {object} response.Any{data=[]model.SystemConfig} "系统配置列表"
|
||
// @Failure 401 {object} response.Any "未登录"
|
||
// @Failure 403 {object} response.Any "无管理员权限"
|
||
// @Failure 500 {object} response.Any "内部错误"
|
||
// @Router /api/v1/admin/system-configs [get]
|
||
func ListSystemConfigs(c *gin.Context) {
|
||
configs, err := service.ListAdminSystemConfigs(c.Request.Context(), c.Query("type"))
|
||
if err != nil {
|
||
response.AbortInternal(c, err.Error())
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, response.OK(configs))
|
||
}
|
||
|
||
// GetSystemConfig 获取单个系统配置
|
||
// @Summary 获取单个系统配置
|
||
// @Description 根据配置键获取对应的系统配置详情,需要管理员权限
|
||
// @Tags admin
|
||
// @Produce json
|
||
// @Security SessionCookie
|
||
// @Param key path string true "配置键"
|
||
// @Success 200 {object} response.Any{data=model.SystemConfig} "系统配置详情"
|
||
// @Failure 401 {object} response.Any "未登录"
|
||
// @Failure 403 {object} response.Any "无管理员权限"
|
||
// @Failure 404 {object} response.Any "配置不存在"
|
||
// @Failure 500 {object} response.Any "内部错误"
|
||
// @Router /api/v1/admin/system-configs/{key} [get]
|
||
func GetSystemConfig(c *gin.Context) {
|
||
config, err := service.GetAdminSystemConfig(c.Request.Context(), c.Param("key"))
|
||
if err != nil {
|
||
if errors.Is(err, errs.ErrSystemConfigNotFound) {
|
||
response.AbortNotFound(c, errs.SystemConfigNotFound)
|
||
return
|
||
}
|
||
response.AbortInternal(c, err.Error())
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, response.OK(config))
|
||
}
|
||
|
||
// UpdateSystemConfig 更新系统配置
|
||
// @Summary 更新系统配置
|
||
// @Description 根据配置键更新对应的配置内容,同时将更新同步到 Redis,需要管理员权限
|
||
// @Tags admin
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security SessionCookie
|
||
// @Param key path string true "配置键"
|
||
// @Param request body model.UpdateSystemConfigRequest true "更新请求参数"
|
||
// @Success 200 {object} response.Any{data=string} "更新成功"
|
||
// @Failure 400 {object} response.Any "参数错误"
|
||
// @Failure 401 {object} response.Any "未登录"
|
||
// @Failure 403 {object} response.Any "无管理员权限"
|
||
// @Failure 404 {object} response.Any "配置不存在"
|
||
// @Failure 500 {object} response.Any "内部错误"
|
||
// @Router /api/v1/admin/system-configs/{key} [put]
|
||
func UpdateSystemConfig(c *gin.Context) {
|
||
var req model.UpdateSystemConfigRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.AbortBadRequest(c, err.Error())
|
||
return
|
||
}
|
||
|
||
key := c.Param("key")
|
||
if err := service.UpdateAdminSystemConfig(c.Request.Context(), key, req); err != nil {
|
||
if errors.Is(err, errs.ErrSystemConfigNotFound) {
|
||
response.AbortNotFound(c, errs.SystemConfigNotFound)
|
||
return
|
||
}
|
||
if errors.Is(err, errs.ErrProtectedConfigKey) || errs.IsStorageConfigValidationError(err) {
|
||
response.AbortBadRequest(c, err.Error())
|
||
return
|
||
}
|
||
response.AbortInternal(c, err.Error())
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, response.OKNil())
|
||
}
|
||
|
||
// TestSMTP 测试 SMTP 邮件发送
|
||
// @Summary 测试 SMTP 邮件发送
|
||
// @Description 使用传入的配置进行 SMTP 邮件发送测试,支持使用 ****** 占位符使用保存的数据库密码
|
||
// @Tags admin
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Security SessionCookie
|
||
// @Param request body model.TestSMTPRequest true "测试请求参数"
|
||
// @Success 200 {object} response.Any{data=model.TestSMTPResponse} "测试执行完毕"
|
||
// @Failure 400 {object} response.Any "参数错误"
|
||
// @Router /api/v1/admin/system-configs/smtp/test [post]
|
||
func TestSMTP(c *gin.Context) {
|
||
var req model.TestSMTPRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
response.AbortBadRequest(c, err.Error())
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, response.OK(service.TestSMTP(c.Request.Context(), req)))
|
||
}
|