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:
ryan
2026-06-18 10:51:25 +08:00
parent f826807cf1
commit 9af84c8ed6
62 changed files with 2040 additions and 1696 deletions
+12 -12
View File
@@ -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())
+5 -5
View File
@@ -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())
+14 -14
View File
@@ -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
}
+3 -4
View File
@@ -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
}
+20 -20
View File
@@ -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
}
+29 -29
View File
@@ -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
}
+3 -3
View File
@@ -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
}
+13 -13
View File
@@ -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
}
+27 -27
View File
@@ -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
}
+17 -17
View File
@@ -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
}
+2 -2
View File
@@ -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
}
+26 -26
View File
@@ -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
}