This commit is contained in:
ryan
2026-06-08 20:08:14 +08:00
parent 02f458856d
commit cd3d0c9f82
61 changed files with 2180 additions and 1891 deletions
+3 -2
View File
@@ -21,6 +21,7 @@ import (
"fmt"
"net/http"
"github.com/Rain-kl/Wavelet/internal/apps/admin"
"github.com/Rain-kl/Wavelet/internal/model"
"github.com/Rain-kl/Wavelet/internal/util"
"github.com/gin-gonic/gin"
@@ -217,7 +218,7 @@ func DeleteAuthSource(c *gin.Context) {
func parseSourceID(c *gin.Context) (uint64, error) {
raw := c.Param("id")
if raw == "" {
return 0, errors.New("认证源 ID 无效")
return 0, errors.New(admin.InvalidAuthSourceID)
}
source, err := model.GetAuthSourceByName(raw)
if err == nil {
@@ -225,7 +226,7 @@ func parseSourceID(c *gin.Context) (uint64, error) {
}
var id uint64
if _, scanErr := fmt.Sscanf(raw, "%d", &id); scanErr != nil || id == 0 {
return 0, errors.New("认证源 ID 无效")
return 0, errors.New(admin.InvalidAuthSourceID)
}
return id, nil
}
+4 -1
View File
@@ -18,5 +18,8 @@ limitations under the License.
package admin
const (
AdminRequired = "未经授权访问"
AdminRequired = "未经授权访问"
InvalidAuthSourceID = "认证源 ID 无效"
InvalidCursorParam = "无效的 cursor 参数"
InvalidTaskExecutionID = "无效的任务执行记录 ID"
)
+2 -1
View File
@@ -21,6 +21,7 @@ import (
"encoding/json"
"net/http"
"github.com/Rain-kl/Wavelet/internal/apps/admin"
"github.com/Rain-kl/Wavelet/internal/logger"
"github.com/Rain-kl/Wavelet/internal/util"
"github.com/gin-gonic/gin"
@@ -53,7 +54,7 @@ func GetLogs(c *gin.Context) {
var cursor, limit int
if _, err := parsePositiveInt(cursorStr, &cursor); err != nil {
c.JSON(http.StatusBadRequest, util.Err("无效的 cursor 参数"))
c.JSON(http.StatusBadRequest, util.Err(admin.InvalidCursorParam))
return
}
if _, err := parsePositiveInt(limitStr, &limit); err != nil || limit <= 0 {
@@ -227,52 +227,6 @@ func UpdateSystemConfig(c *gin.Context) {
c.JSON(http.StatusOK, util.OKNil())
}
// DeleteSystemConfig 删除系统配置
// @Summary 删除系统配置
// @Description 根据配置键删除对应配置,同时从 Redis 中移除对应缓存,需要管理员权限
// @Tags admin
// @Produce json
// @Security SessionCookie
// @Param key path string true "配置键"
// @Success 200 {object} util.ResponseAny{data=string} "删除成功"
// @Failure 401 {object} util.ResponseAny "未登录"
// @Failure 403 {object} util.ResponseAny "无管理员权限"
// @Failure 404 {object} util.ResponseAny "配置不存在"
// @Failure 500 {object} util.ResponseAny "内部错误"
// @Router /api/v1/admin/system-configs/{key} [delete]
func DeleteSystemConfig(c *gin.Context) {
key := c.Param("key")
// 检查配置是否存在
var config model.SystemConfig
if err := db.DB(c.Request.Context()).Where("key = ?", key).First(&config).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, util.Err(SystemConfigNotFound))
} else {
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
}
return
}
if err := db.DB(c.Request.Context()).Transaction(func(tx *gorm.DB) error {
// 删除配置
if err := tx.Delete(&config).Error; err != nil {
return err
}
if err := db.Redis.HDel(c.Request.Context(), db.PrefixedKey(model.SystemConfigRedisHashKey), key).Err(); err != nil {
return err
}
return nil
}); err != nil {
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
return
}
c.JSON(http.StatusOK, util.OKNil())
}
// TestSMTPRequest 测试 SMTP 配置请求
type TestSMTPRequest struct {
SMTPHost string `json:"smtp_host" binding:"required,max=255"`
@@ -56,7 +56,6 @@ func setupTestRouter(authUser *model.User) *gin.Engine {
{
systemConfigRouter.GET("", GetSystemConfig)
systemConfigRouter.PUT("", UpdateSystemConfig)
systemConfigRouter.DELETE("", DeleteSystemConfig)
}
return r
@@ -263,48 +262,6 @@ func TestUpdateSystemConfig(t *testing.T) {
})
}
func TestDeleteSystemConfig(t *testing.T) {
dbConn, _, cleanup := testhelper.SetupTestEnvironment(t)
defer cleanup()
adminUser := &model.User{ID: 1001, Username: "admin", IsAdmin: true}
router := setupTestRouter(adminUser)
t.Run("delete successfully", func(t *testing.T) {
req, _ := http.NewRequest("DELETE", "/api/v1/admin/system-configs/"+model.ConfigKeySiteName, nil)
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Fatalf("expected 200 OK, got %d. Body: %s", w.Code, w.Body.String())
}
// Verify database
var count int64
dbConn.Model(&model.SystemConfig{}).Where("key = ?", model.ConfigKeySiteName).Count(&count)
if count != 0 {
t.Error("config still exists in DB")
}
// Verify Redis Cache removal
var redisConfig model.SystemConfig
err := db.HGetJSON(context.Background(), model.SystemConfigRedisHashKey, model.ConfigKeySiteName, &redisConfig)
if err == nil {
t.Error("config should have been deleted from Redis cache")
}
})
t.Run("delete non-existent config", func(t *testing.T) {
req, _ := http.NewRequest("DELETE", "/api/v1/admin/system-configs/invalid_key", nil)
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
if w.Code != http.StatusNotFound {
t.Errorf("expected 404 Not Found, got %d", w.Code)
}
})
}
func TestTestSMTP(t *testing.T) {
_, _, cleanup := testhelper.SetupTestEnvironment(t)
defer cleanup()
+3 -2
View File
@@ -24,6 +24,7 @@ import (
"strings"
"time"
"github.com/Rain-kl/Wavelet/internal/apps/admin"
"github.com/Rain-kl/Wavelet/internal/model"
"github.com/Rain-kl/Wavelet/internal/task"
taskhandlers "github.com/Rain-kl/Wavelet/internal/task/handlers"
@@ -156,7 +157,7 @@ func ListTaskExecutions(c *gin.Context) {
func GetTaskExecution(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, util.Err("无效的任务执行记录 ID"))
c.JSON(http.StatusBadRequest, util.Err(admin.InvalidTaskExecutionID))
return
}
@@ -186,7 +187,7 @@ func GetTaskExecution(c *gin.Context) {
func RetryTask(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, util.Err("无效的任务执行记录 ID"))
c.JSON(http.StatusBadRequest, util.Err(admin.InvalidTaskExecutionID))
return
}