mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-03 07:06:36 +08:00
refactor(api): unify error handling and split upload/oauth god modules
Replace c.JSON(200, response.Err) and middleware gin.H bypasses with response.Abort* helpers so errors flow through Gin Error chain and ErrorHandlerMiddleware for OTel trace correlation. Split oauth/sources.go into domain-focused files and decompose upload into handler/filesrv/stats/task/cache/storage/util subpackages with a root facade preserving existing import paths.
This commit is contained in:
@@ -50,7 +50,7 @@ type ToggleAuthSourceRequest struct {
|
||||
func ListAuthSources(c *gin.Context) {
|
||||
sources, err := model.GetAuthSources(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, response.OK(sources))
|
||||
@@ -72,7 +72,7 @@ func ListAuthSources(c *gin.Context) {
|
||||
func CreateAuthSource(c *gin.Context) {
|
||||
var req AuthSourceRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ func CreateAuthSource(c *gin.Context) {
|
||||
IconURL: req.IconURL,
|
||||
}
|
||||
if err := model.CreateAuthSource(c.Request.Context(), &source); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
source.Sanitize()
|
||||
@@ -113,13 +113,13 @@ func CreateAuthSource(c *gin.Context) {
|
||||
func UpdateAuthSource(c *gin.Context) {
|
||||
id, err := parseSourceID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var req AuthSourceRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ func UpdateAuthSource(c *gin.Context) {
|
||||
}
|
||||
keepSecret := source.ClientSecret == ""
|
||||
if err := model.UpdateAuthSource(c.Request.Context(), &source, keepSecret); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ func UpdateAuthSource(c *gin.Context) {
|
||||
|
||||
updated, err := model.GetAuthSourceByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
updated.Sanitize()
|
||||
@@ -177,18 +177,18 @@ func UpdateAuthSource(c *gin.Context) {
|
||||
func ToggleAuthSource(c *gin.Context) {
|
||||
id, err := parseSourceID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var req ToggleAuthSourceRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := model.ToggleAuthSource(c.Request.Context(), id, req.IsActive); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
@@ -209,11 +209,11 @@ func ToggleAuthSource(c *gin.Context) {
|
||||
func DeleteAuthSource(c *gin.Context) {
|
||||
id, err := parseSourceID(c)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := model.DeleteAuthSource(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
|
||||
Vendored
+5
-5
@@ -56,7 +56,7 @@ func GetCacheStatus(c *gin.Context) {
|
||||
func UpdateCacheConfig(c *gin.Context) {
|
||||
var req updateCacheConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -64,19 +64,19 @@ func UpdateCacheConfig(c *gin.Context) {
|
||||
|
||||
// Update Max Size
|
||||
if err := saveOrUpdateConfig(ctx, model.ConfigKeyDiskCacheMaxSizeMB, strconv.FormatInt(req.MaxSizeMB, 10)); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Update Default TTL
|
||||
if err := saveOrUpdateConfig(ctx, model.ConfigKeyDiskCacheTTLMinutes, strconv.FormatInt(req.TTLMinutes, 10)); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Update LRU Enabled
|
||||
if err := saveOrUpdateConfig(ctx, model.ConfigKeyDiskCacheLRUEnabled, strconv.FormatBool(req.LRUEnabled)); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ func UpdateCacheConfig(c *gin.Context) {
|
||||
// @Router /api/v1/admin/cache/clear [post]
|
||||
func ClearCache(c *gin.Context) {
|
||||
if err := diskcache.GetGlobalCache().Clear(); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
|
||||
@@ -213,7 +213,7 @@ func getPostgresOverview(gormDB *gorm.DB) (DBOverviewResponse, error) {
|
||||
func GetDBOverview(c *gin.Context) {
|
||||
gormDB := db.DB(c.Request.Context())
|
||||
if gormDB == nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err("数据库未初始化"))
|
||||
response.AbortInternal(c, "数据库未初始化")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ func GetDBOverview(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ func GetDBOverview(c *gin.Context) {
|
||||
func ListDBTables(c *gin.Context) {
|
||||
gormDB := db.DB(c.Request.Context())
|
||||
if gormDB == nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err("数据库未初始化"))
|
||||
response.AbortInternal(c, "数据库未初始化")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ func ListDBTables(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -273,13 +273,13 @@ func ListDBTables(c *gin.Context) {
|
||||
func GetDBTableData(c *gin.Context) {
|
||||
var req GetTableDataRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
gormDB := db.DB(c.Request.Context())
|
||||
if gormDB == nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err("数据库未初始化"))
|
||||
response.AbortInternal(c, "数据库未初始化")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ func GetDBTableData(c *gin.Context) {
|
||||
|
||||
var total int64
|
||||
if err := gormDB.Raw("SELECT count(*) FROM " + quotedTable).Scan(&total).Error; err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ func GetDBTableData(c *gin.Context) {
|
||||
|
||||
rows, err := gormDB.Raw("SELECT * FROM "+quotedTable+" LIMIT ? OFFSET ?", limit, offset).Rows()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
@@ -312,13 +312,13 @@ func GetDBTableData(c *gin.Context) {
|
||||
|
||||
cols, err := rows.Columns()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
results, err := scanTableRows(rows, cols)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -449,19 +449,19 @@ func executeSQLMutation(gormDB *gorm.DB, sqlStr string, startTime time.Time) (Ex
|
||||
func ExecuteSQL(c *gin.Context) {
|
||||
var req ExecuteSQLRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
gormDB := db.DB(c.Request.Context())
|
||||
if gormDB == nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err("数据库未初始化"))
|
||||
response.AbortInternal(c, "数据库未初始化")
|
||||
return
|
||||
}
|
||||
|
||||
trimmedSQL := strings.TrimSpace(req.SQL)
|
||||
if trimmedSQL == "" {
|
||||
c.JSON(http.StatusBadRequest, response.Err("SQL 语句不能为空"))
|
||||
response.AbortBadRequest(c, "SQL 语句不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -488,7 +488,7 @@ func ExecuteSQL(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/common/response"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
"github.com/Rain-kl/Wavelet/internal/util"
|
||||
"github.com/Rain-kl/Wavelet/pkg/logger"
|
||||
@@ -29,13 +28,13 @@ func LoginAdminRequired() gin.HandlerFunc {
|
||||
if tokenAuth, _ := util.GetFromContext[bool](c, oauth.TokenAuthKey); tokenAuth {
|
||||
tokenAdmin, _ := util.GetFromContext[bool](c, oauth.TokenAdminKey)
|
||||
if !tokenAdmin {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error_msg": TokenAdminRequired, "data": nil})
|
||||
response.AbortNotFound(c, TokenAdminRequired)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !user.IsAdmin {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error_msg": AdminRequired, "data": nil})
|
||||
response.AbortNotFound(c, AdminRequired)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ func ListChannels(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
var channels []model.PushChannel
|
||||
if err := db.DB(ctx).Order("created_at DESC").Find(&channels).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, response.OK(channels))
|
||||
@@ -71,7 +71,7 @@ type CreateChannelRequest struct {
|
||||
func CreateChannel(c *gin.Context) {
|
||||
var req CreateChannelRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -79,11 +79,11 @@ func CreateChannel(c *gin.Context) {
|
||||
|
||||
var count int64
|
||||
if err := db.DB(ctx).Model(&model.PushChannel{}).Where("name = ?", req.Name).Count(&count).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
if count > 0 {
|
||||
c.JSON(http.StatusBadRequest, response.Err("channel name already exists"))
|
||||
response.AbortBadRequest(c, "channel name already exists")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -98,12 +98,12 @@ func CreateChannel(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := channel.Validate(); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(ctx).Create(&channel).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -138,13 +138,13 @@ func UpdateChannel(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err("invalid channel id"))
|
||||
response.AbortBadRequest(c, "invalid channel id")
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateChannelRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -153,10 +153,10 @@ func UpdateChannel(c *gin.Context) {
|
||||
var channel model.PushChannel
|
||||
if err := db.DB(ctx).Where("id = ?", id).First(&channel).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, response.Err("channel not found"))
|
||||
response.AbortNotFound(c, "channel not found")
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -168,12 +168,12 @@ func UpdateChannel(c *gin.Context) {
|
||||
channel.Enabled = req.Enabled
|
||||
|
||||
if err := channel.Validate(); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(ctx).Save(&channel).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ func DeleteChannel(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err("invalid channel id"))
|
||||
response.AbortBadRequest(c, "invalid channel id")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -204,15 +204,15 @@ func DeleteChannel(c *gin.Context) {
|
||||
var channel model.PushChannel
|
||||
if err := db.DB(ctx).Where("id = ?", id).First(&channel).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, response.Err("channel not found"))
|
||||
response.AbortNotFound(c, "channel not found")
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(ctx).Delete(&channel).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ type TestChannelRequest struct {
|
||||
func TestChannel(c *gin.Context) {
|
||||
var req TestChannelRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ func TestChannel(c *gin.Context) {
|
||||
if req.Name != "" {
|
||||
var channel model.PushChannel
|
||||
if err := db.DB(ctx).Where("name = ?", req.Name).First(&channel).Error; err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err("channel not found"))
|
||||
response.AbortBadRequest(c, "channel not found")
|
||||
return
|
||||
}
|
||||
url = channel.URL
|
||||
@@ -284,7 +284,7 @@ func TestChannel(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := tempChannel.Validate(); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
url = tempChannel.URL
|
||||
@@ -342,7 +342,7 @@ func TestChannel(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := enqueuePushTask(ctx, payload); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ func ListEvents(c *gin.Context) {
|
||||
|
||||
var events []model.PushEvent
|
||||
if err := db.DB(ctx).Order("created_at DESC").Find(&events).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, response.OK(events))
|
||||
@@ -166,7 +166,7 @@ func getEventInfo(req CreateEventRequest) (string, string, []byte, error) {
|
||||
func CreateEvent(c *gin.Context) {
|
||||
var req CreateEventRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -174,18 +174,18 @@ func CreateEvent(c *gin.Context) {
|
||||
|
||||
eventKey, eventName, defaultTemplateBytes, err := getEventInfo(req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 检查是否已经创建过该事件的配置
|
||||
var count int64
|
||||
if err := db.DB(ctx).Model(&model.PushEvent{}).Where("event_key = ?", eventKey).Count(&count).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
if count > 0 {
|
||||
c.JSON(http.StatusBadRequest, response.Err("this notification event is already configured"))
|
||||
response.AbortBadRequest(c, "this notification event is already configured")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ func CreateEvent(c *gin.Context) {
|
||||
} else {
|
||||
var tempMap map[string]any
|
||||
if err := json.Unmarshal([]byte(templateStr), &tempMap); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err("custom template is not a valid JSON format"))
|
||||
response.AbortBadRequest(c, "custom template is not a valid JSON format")
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -222,12 +222,12 @@ func CreateEvent(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := event.Validate(); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(ctx).Create(&event).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ func DeleteEvent(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err("invalid event id"))
|
||||
response.AbortBadRequest(c, "invalid event id")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -258,15 +258,15 @@ func DeleteEvent(c *gin.Context) {
|
||||
var event model.PushEvent
|
||||
if err := db.DB(ctx).First(&event, id).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, response.Err("notification event not found"))
|
||||
response.AbortNotFound(c, "notification event not found")
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(ctx).Delete(&event).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -291,22 +291,22 @@ func UpdateEvent(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err("invalid event id"))
|
||||
response.AbortBadRequest(c, "invalid event id")
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateEventRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var event model.PushEvent
|
||||
if err := db.DB(c.Request.Context()).First(&event, id).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, response.Err("notification event not found"))
|
||||
response.AbortNotFound(c, "notification event not found")
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -317,12 +317,12 @@ func UpdateEvent(c *gin.Context) {
|
||||
event.Enabled = req.Enabled
|
||||
|
||||
if err := event.Validate(); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(c.Request.Context()).Save(&event).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -345,27 +345,27 @@ func ToggleEvent(c *gin.Context) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err("invalid event id"))
|
||||
response.AbortBadRequest(c, "invalid event id")
|
||||
return
|
||||
}
|
||||
|
||||
var event model.PushEvent
|
||||
if err := db.DB(c.Request.Context()).First(&event, id).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, response.Err("notification event not found"))
|
||||
response.AbortNotFound(c, "notification event not found")
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
event.Enabled = !event.Enabled
|
||||
if event.Enabled && len(event.Channels) == 0 {
|
||||
c.JSON(http.StatusBadRequest, response.Err("cannot enable event without any push channels configured"))
|
||||
response.AbortBadRequest(c, "cannot enable event without any push channels configured")
|
||||
return
|
||||
}
|
||||
if err := db.DB(c.Request.Context()).Model(&event).Update("enabled", event.Enabled).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -420,14 +420,14 @@ func ListHistories(c *gin.Context) {
|
||||
|
||||
var total int64
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var results []model.PushHistory
|
||||
offset := (page - 1) * pageSize
|
||||
if err := query.Offset(offset).Limit(pageSize).Find(&results).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -450,19 +450,19 @@ func ListHistories(c *gin.Context) {
|
||||
func TestPush(c *gin.Context) {
|
||||
var req TestPushRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
pusher, err := push.GetPusher(req.Config.Channel)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 校验配置
|
||||
if err := pusher.ValidateConfig(req.Config); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(fmt.Sprintf("validation failed: %v", err)))
|
||||
response.AbortBadRequest(c, fmt.Sprintf("validation failed: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -494,7 +494,7 @@ func TestPush(c *gin.Context) {
|
||||
|
||||
err = pusher.Send(c.Request.Context(), req.Config, req.Target, testBody, "", nil)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ func exportSQLite(c *gin.Context) {
|
||||
|
||||
f, err := os.Open(path) //nolint:gosec // path is loaded from server startup configuration, not user input
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err("无法打开数据库文件: "+err.Error()))
|
||||
response.AbortInternal(c, "无法打开数据库文件: "+err.Error())
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
@@ -301,7 +301,7 @@ func exportSQLite(c *gin.Context) {
|
||||
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err("无法读取数据库文件信息: "+err.Error()))
|
||||
response.AbortInternal(c, "无法读取数据库文件信息: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ func exportPostgres(c *gin.Context) {
|
||||
// 检查 pg_dump 是否可用
|
||||
pgDumpPath, err := exec.LookPath("pg_dump")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err("pg_dump 不可用,请确保服务器已安装 PostgreSQL 客户端工具"))
|
||||
response.AbortInternal(c, "pg_dump 不可用,请确保服务器已安装 PostgreSQL 客户端工具")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -60,17 +60,17 @@ type UpdateSystemConfigRequest struct {
|
||||
func CreateSystemConfig(c *gin.Context) {
|
||||
var req CreateSystemConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 检查配置键是否已存在
|
||||
var existing model.SystemConfig
|
||||
if err := db.DB(c.Request.Context()).Where("key = ?", req.Key).First(&existing).Error; err == nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(ConfigKeyExists))
|
||||
response.AbortBadRequest(c, ConfigKeyExists)
|
||||
return
|
||||
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ func CreateSystemConfig(c *gin.Context) {
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ func ListSystemConfigs(c *gin.Context) {
|
||||
|
||||
var configs []model.SystemConfig
|
||||
if err := query.Find(&configs).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -152,9 +152,9 @@ func GetSystemConfig(c *gin.Context) {
|
||||
var config model.SystemConfig
|
||||
if err := db.DB(c.Request.Context()).Where("key = ?", c.Param("key")).First(&config).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, response.Err(SystemConfigNotFound))
|
||||
response.AbortNotFound(c, SystemConfigNotFound)
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -183,7 +183,7 @@ func GetSystemConfig(c *gin.Context) {
|
||||
func UpdateSystemConfig(c *gin.Context) {
|
||||
var req UpdateSystemConfigRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -193,9 +193,9 @@ func UpdateSystemConfig(c *gin.Context) {
|
||||
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, response.Err(SystemConfigNotFound))
|
||||
response.AbortNotFound(c, SystemConfigNotFound)
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -209,7 +209,7 @@ func UpdateSystemConfig(c *gin.Context) {
|
||||
|
||||
validatedVal, err := validateAndMergeStorageConfig(c.Request.Context(), req.Value, config.Value)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
req.Value = validatedVal
|
||||
@@ -242,7 +242,7 @@ func UpdateSystemConfig(c *gin.Context) {
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ type TestSMTPResponse struct {
|
||||
func TestSMTP(c *gin.Context) {
|
||||
var req TestSMTPRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -65,13 +65,13 @@ type DispatchTaskRequest struct {
|
||||
func DispatchTask(c *gin.Context) {
|
||||
var req DispatchTaskRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
meta := task.GetTaskMeta(req.TaskType)
|
||||
if meta == nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(InvalidTaskType))
|
||||
response.AbortBadRequest(c, InvalidTaskType)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -82,13 +82,13 @@ func DispatchTask(c *gin.Context) {
|
||||
|
||||
validated, err := task.ValidateAndNormalizePayload(meta.AsynqTask, payloadBytes)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
taskID, err := task.DispatchTask(c.Request.Context(), req.TaskType, validated, "manual")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(fmt.Sprintf("%s: %v", TaskDispatchFailed, err)))
|
||||
response.AbortInternal(c, fmt.Sprintf("%s: %v", TaskDispatchFailed, err))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func DispatchTask(c *gin.Context) {
|
||||
func ListTaskExecutions(c *gin.Context) {
|
||||
var req model.ListTaskExecutionsRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ func ListTaskExecutions(c *gin.Context) {
|
||||
|
||||
executions, total, err := model.ListTaskExecutions(c.Request.Context(), req)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -152,13 +152,13 @@ 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, response.Err(admin.InvalidTaskExecutionID))
|
||||
response.AbortBadRequest(c, admin.InvalidTaskExecutionID)
|
||||
return
|
||||
}
|
||||
|
||||
execution, err := model.GetTaskExecutionByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, response.Err(TaskNotFound))
|
||||
response.AbortNotFound(c, TaskNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -182,7 +182,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, response.Err(admin.InvalidTaskExecutionID))
|
||||
response.AbortBadRequest(c, admin.InvalidTaskExecutionID)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -191,11 +191,11 @@ func RetryTask(c *gin.Context) {
|
||||
errMsg := err.Error()
|
||||
switch {
|
||||
case strings.Contains(errMsg, "不存在"):
|
||||
c.JSON(http.StatusNotFound, response.Err(errMsg))
|
||||
response.AbortNotFound(c, errMsg)
|
||||
case strings.Contains(errMsg, "只有失败的任务") || strings.Contains(errMsg, "不支持重试") || strings.Contains(errMsg, "已达到最大重试"):
|
||||
c.JSON(http.StatusBadRequest, response.Err(errMsg))
|
||||
response.AbortBadRequest(c, errMsg)
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, response.Err(fmt.Sprintf("%s: %v", TaskRetryFailed, err)))
|
||||
response.AbortInternal(c, fmt.Sprintf("%s: %v", TaskRetryFailed, err))
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -216,7 +216,7 @@ func RetryTask(c *gin.Context) {
|
||||
func ListSchedules(c *gin.Context) {
|
||||
schedules, err := model.ListSchedules(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, response.OK(schedules))
|
||||
@@ -248,20 +248,20 @@ type CreateScheduleRequest struct {
|
||||
func CreateSchedule(c *gin.Context) {
|
||||
var req CreateScheduleRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 校验 Cron 表达式
|
||||
if _, err := cron.ParseStandard(req.Cron); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(InvalidCronExpression))
|
||||
response.AbortBadRequest(c, InvalidCronExpression)
|
||||
return
|
||||
}
|
||||
|
||||
// 校验关联的异步任务类型
|
||||
meta := task.GetTaskMeta(req.TaskType)
|
||||
if meta == nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(InvalidTaskType))
|
||||
response.AbortBadRequest(c, InvalidTaskType)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ func CreateSchedule(c *gin.Context) {
|
||||
}
|
||||
validated, err := task.ValidateAndNormalizePayload(meta.AsynqTask, payloadBytes)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ func CreateSchedule(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := model.CreateSchedule(c.Request.Context(), schedule); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(fmt.Sprintf("%s: %v", ScheduleSaveFailed, err)))
|
||||
response.AbortInternal(c, fmt.Sprintf("%s: %v", ScheduleSaveFailed, err))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -325,33 +325,33 @@ type UpdateScheduleRequest struct {
|
||||
func UpdateSchedule(c *gin.Context) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err("无效的定时任务ID"))
|
||||
response.AbortBadRequest(c, "无效的定时任务ID")
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateScheduleRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 检查定时任务是否存在
|
||||
schedule, err := model.GetScheduleByID(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, response.Err(ScheduleNotFound))
|
||||
response.AbortNotFound(c, ScheduleNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// 校验 Cron 表达式
|
||||
if _, err := cron.ParseStandard(req.Cron); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(InvalidCronExpression))
|
||||
response.AbortBadRequest(c, InvalidCronExpression)
|
||||
return
|
||||
}
|
||||
|
||||
// 校验关联的异步任务类型
|
||||
meta := task.GetTaskMeta(req.TaskType)
|
||||
if meta == nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(InvalidTaskType))
|
||||
response.AbortBadRequest(c, InvalidTaskType)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ func UpdateSchedule(c *gin.Context) {
|
||||
}
|
||||
validated, err := task.ValidateAndNormalizePayload(meta.AsynqTask, payloadBytes)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -373,7 +373,7 @@ func UpdateSchedule(c *gin.Context) {
|
||||
schedule.IsActive = *req.IsActive
|
||||
|
||||
if err := model.UpdateSchedule(c.Request.Context(), schedule); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(fmt.Sprintf("%s: %v", ScheduleSaveFailed, err)))
|
||||
response.AbortInternal(c, fmt.Sprintf("%s: %v", ScheduleSaveFailed, err))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -401,12 +401,12 @@ func UpdateSchedule(c *gin.Context) {
|
||||
func DeleteSchedule(c *gin.Context) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err("无效的定时任务ID"))
|
||||
response.AbortBadRequest(c, "无效的定时任务ID")
|
||||
return
|
||||
}
|
||||
|
||||
if err := model.DeleteSchedule(c.Request.Context(), id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(fmt.Sprintf("%s: %v", ScheduleDeleteFailed, err)))
|
||||
response.AbortInternal(c, fmt.Sprintf("%s: %v", ScheduleDeleteFailed, err))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -49,17 +49,17 @@ type UpdateTemplateRequest struct {
|
||||
func CreateTemplate(c *gin.Context) {
|
||||
var req CreateTemplateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// 检查模板 Key 是否已存在
|
||||
var existing model.Template
|
||||
if err := db.DB(c.Request.Context()).Where("key = ?", req.Key).First(&existing).Error; err == nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(TemplateKeyExists))
|
||||
response.AbortBadRequest(c, TemplateKeyExists)
|
||||
return
|
||||
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -74,12 +74,12 @@ func CreateTemplate(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := tmpl.Validate(); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(c.Request.Context()).Create(&tmpl).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ func CreateTemplate(c *gin.Context) {
|
||||
func ListTemplates(c *gin.Context) {
|
||||
var templates []model.Template
|
||||
if err := db.DB(c.Request.Context()).Order("is_system DESC, created_at DESC").Find(&templates).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,9 +124,9 @@ func GetTemplate(c *gin.Context) {
|
||||
var tmpl model.Template
|
||||
if err := db.DB(c.Request.Context()).Where("key = ?", c.Param("key")).First(&tmpl).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, response.Err(TemplateNotFound))
|
||||
response.AbortNotFound(c, TemplateNotFound)
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -153,7 +153,7 @@ func GetTemplate(c *gin.Context) {
|
||||
func UpdateTemplate(c *gin.Context) {
|
||||
var req UpdateTemplateRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -163,9 +163,9 @@ func UpdateTemplate(c *gin.Context) {
|
||||
var tmpl model.Template
|
||||
if err := db.DB(c.Request.Context()).Where("key = ?", key).First(&tmpl).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, response.Err(TemplateNotFound))
|
||||
response.AbortNotFound(c, TemplateNotFound)
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -177,12 +177,12 @@ func UpdateTemplate(c *gin.Context) {
|
||||
tmpl.Description = req.Description
|
||||
|
||||
if err := tmpl.Validate(); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(c.Request.Context()).Save(&tmpl).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -210,21 +210,21 @@ func DeleteTemplate(c *gin.Context) {
|
||||
var tmpl model.Template
|
||||
if err := db.DB(c.Request.Context()).Where("key = ?", key).First(&tmpl).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusNotFound, response.Err(TemplateNotFound))
|
||||
response.AbortNotFound(c, TemplateNotFound)
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 限制系统模板删除
|
||||
if tmpl.IsSystem {
|
||||
c.JSON(http.StatusBadRequest, response.Err(SystemTemplateCannotDelete))
|
||||
response.AbortBadRequest(c, SystemTemplateCannotDelete)
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(c.Request.Context()).Delete(&tmpl).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ func GetUpdateStatus(c *gin.Context) {
|
||||
status, _, err := defaultManager.status(c.Request.Context())
|
||||
if err != nil {
|
||||
logger.ErrorF(c.Request.Context(), "[Updater] check release failed: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, response.OK(status))
|
||||
@@ -49,7 +49,7 @@ func ApplyUpdate(c *gin.Context) {
|
||||
executable, stagedBinary, err := defaultManager.prepareUpgrade(c.Request.Context())
|
||||
if err != nil {
|
||||
logger.ErrorF(c.Request.Context(), "[Updater] prepare upgrade failed: %v", err)
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ type listUsersResponse struct {
|
||||
func parseUserID(c *gin.Context) (uint64, bool) {
|
||||
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
c.JSON(http.StatusBadRequest, response.Err(userNotFound))
|
||||
response.AbortBadRequest(c, userNotFound)
|
||||
return 0, false
|
||||
}
|
||||
return id, true
|
||||
@@ -102,7 +102,7 @@ func toUser(u model.User) user {
|
||||
func ListUsers(c *gin.Context) {
|
||||
var req listUsersRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ func ListUsers(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ func ListUsers(c *gin.Context) {
|
||||
Offset(offset).
|
||||
Limit(req.PageSize).
|
||||
Find(&modelUsers).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -176,10 +176,10 @@ func GetUser(c *gin.Context) {
|
||||
Where("id = ?", id).
|
||||
First(&targetUser).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
c.JSON(http.StatusNotFound, response.Err(userNotFound))
|
||||
response.AbortNotFound(c, userNotFound)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ type updateUserStatusRequest struct {
|
||||
func UpdateUserStatus(c *gin.Context) {
|
||||
var req updateUserStatusRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -229,15 +229,15 @@ func UpdateUserStatus(c *gin.Context) {
|
||||
Where("id = ?", id).
|
||||
First(&targetUser).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
c.JSON(http.StatusNotFound, response.Err(userNotFound))
|
||||
response.AbortNotFound(c, userNotFound)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if !req.IsActive && targetUser.IsAdmin {
|
||||
c.JSON(http.StatusForbidden, response.Err(cannotDisable))
|
||||
response.AbortForbidden(c, cannotDisable)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ func UpdateUserStatus(c *gin.Context) {
|
||||
Model(&model.User{}).
|
||||
Where("id = ?", id).
|
||||
Update("is_active", req.IsActive).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(updateUserFailed))
|
||||
response.AbortInternal(c, updateUserFailed)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ func DeleteUser(c *gin.Context) {
|
||||
|
||||
currUser, _ := util.GetFromContext[*model.User](c, oauth.UserObjKey)
|
||||
if currUser != nil && currUser.ID == id {
|
||||
c.JSON(http.StatusForbidden, response.Err(cannotDeleteSelf))
|
||||
response.AbortForbidden(c, cannotDeleteSelf)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -288,15 +288,15 @@ func DeleteUser(c *gin.Context) {
|
||||
Where("id = ?", id).
|
||||
First(&targetUser).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
c.JSON(http.StatusNotFound, response.Err(userNotFound))
|
||||
response.AbortNotFound(c, userNotFound)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if targetUser.IsAdmin {
|
||||
c.JSON(http.StatusForbidden, response.Err(cannotDelete))
|
||||
response.AbortForbidden(c, cannotDelete)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ func DeleteUser(c *gin.Context) {
|
||||
}
|
||||
return tx.Where("id = ?", id).Delete(&model.User{}).Error
|
||||
}); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(deleteUserFailed))
|
||||
response.AbortInternal(c, deleteUserFailed)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ type createUserRequest struct {
|
||||
func CreateUser(c *gin.Context) {
|
||||
var req createUserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, response.Err(err.Error()))
|
||||
response.AbortBadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -353,36 +353,36 @@ func CreateUser(c *gin.Context) {
|
||||
req.Email = strings.TrimSpace(req.Email)
|
||||
|
||||
if req.Username == "" {
|
||||
c.JSON(http.StatusBadRequest, response.Err(usernameRequired))
|
||||
response.AbortBadRequest(c, usernameRequired)
|
||||
return
|
||||
}
|
||||
if req.Email == "" {
|
||||
c.JSON(http.StatusBadRequest, response.Err(emailRequired))
|
||||
response.AbortBadRequest(c, emailRequired)
|
||||
return
|
||||
}
|
||||
if len(req.Password) < minPasswordLength {
|
||||
c.JSON(http.StatusBadRequest, response.Err(passwordTooShort))
|
||||
response.AbortBadRequest(c, passwordTooShort)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := c.Request.Context()
|
||||
var count int64
|
||||
if err := db.DB(ctx).Model(&model.User{}).Where("username = ?", req.Username).Count(&count).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
if count > 0 {
|
||||
c.JSON(http.StatusBadRequest, response.Err(usernameExists))
|
||||
response.AbortBadRequest(c, usernameExists)
|
||||
return
|
||||
}
|
||||
|
||||
var emailCount int64
|
||||
if err := db.DB(ctx).Model(&model.User{}).Where("email = ?", req.Email).Count(&emailCount).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
if emailCount > 0 {
|
||||
c.JSON(http.StatusBadRequest, response.Err(emailExists))
|
||||
response.AbortBadRequest(c, emailExists)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -400,12 +400,12 @@ func CreateUser(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := newUser.SetEncryptedPassword(req.Password); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(ctx).Create(&newUser).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
response.AbortInternal(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user