From 98aeb063f54385b49544da3bbc45a40967c0cda7 Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Sat, 19 Sep 2026 07:55:27 +0200 Subject: [PATCH] refactor(serializer): finish context-aware error migration The deprecated context-less helpers (ErrDeprecated, ParamErrDeprecated, DBErrDeprecated) were still on two live paths: validator/binding error responses and the CSRF origin check. Responses built through them dropped the request correlation ID. - ErrorResponse now takes the gin context; all binding helpers pass it. - CSRF rejection uses ErrWithDetails so the correlation ID is preserved. - Deleted the deprecated helpers and the stale commented-out call sites left in service files. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- middleware/session.go | 2 +- pkg/serializer/error.go | 40 +-------------------------------- routers/controllers/callback.go | 6 ++--- routers/controllers/main.go | 17 +++++++------- service/admin/file.go | 7 ------ service/admin/group.go | 4 ---- service/admin/policy.go | 5 ----- service/admin/site.go | 2 -- service/callback/oauth.go | 14 ------------ service/callback/upload.go | 8 ------- service/setting/webdav.go | 2 -- 11 files changed, 14 insertions(+), 93 deletions(-) diff --git a/middleware/session.go b/middleware/session.go index aa1fae7d..92ad4dbc 100644 --- a/middleware/session.go +++ b/middleware/session.go @@ -61,7 +61,7 @@ func CSRFCheck() gin.HandlerFunc { return } - c.JSON(200, serializer.ErrDeprecated(serializer.CodeNoPermissionErr, "Invalid origin", nil)) + c.JSON(200, serializer.ErrWithDetails(c, serializer.CodeNoPermissionErr, "Invalid origin", nil)) c.Abort() } } diff --git a/pkg/serializer/error.go b/pkg/serializer/error.go index bb030a43..bccbfac5 100644 --- a/pkg/serializer/error.go +++ b/pkg/serializer/error.go @@ -285,7 +285,7 @@ const ( CodeNotSet = -1 ) -// DBErrDeprecated 数据库操作失败 +// DBErr 数据库操作失败 func DBErr(c context.Context, msg string, err error) Response { if msg == "" { msg = "Database operation failed." @@ -293,14 +293,6 @@ func DBErr(c context.Context, msg string, err error) Response { return ErrWithDetails(c, CodeDBError, msg, err) } -// DBErrDeprecated 数据库操作失败 -func DBErrDeprecated(msg string, err error) Response { - if msg == "" { - msg = "Database operation failed." - } - return ErrDeprecated(CodeDBError, msg, err) -} - // ParamErr 各种参数错误 func ParamErr(c context.Context, msg string, err error) Response { if msg == "" { @@ -309,36 +301,6 @@ func ParamErr(c context.Context, msg string, err error) Response { return ErrWithDetails(c, CodeParamErr, msg, err) } -// ParamErrDeprecated 各种参数错误 -// Deprecated -func ParamErrDeprecated(msg string, err error) Response { - if msg == "" { - msg = "Invalid parameters." - } - return ErrDeprecated(CodeParamErr, msg, err) -} - -// ErrDeprecated 通用错误处理 -func ErrDeprecated(errCode int, msg string, err error) Response { - // 底层错误是AppError,则尝试从AppError中获取详细信息 - var appError AppError - if errors.As(err, &appError) { - errCode = appError.Code - err = appError.RawError - msg = appError.Msg - } - - res := Response{ - Code: errCode, - Msg: msg, - } - // 生产环境隐藏底层报错 - if err != nil && gin.Mode() != gin.ReleaseMode { - res.Error = err.Error() - } - return res -} - // ErrWithDetails 通用错误处理 func ErrWithDetails(c context.Context, errCode int, msg string, err error) Response { res := Response{ diff --git a/routers/controllers/callback.go b/routers/controllers/callback.go index ef00b796..ef17a86d 100644 --- a/routers/controllers/callback.go +++ b/routers/controllers/callback.go @@ -71,7 +71,7 @@ func OSSCallbackValidate(c *gin.Context) { c.Next() } else { - c.JSON(401, ErrorResponse(err)) + c.JSON(401, ErrorResponse(c, err)) c.Abort() } } @@ -104,7 +104,7 @@ func OneDriveOAuth(c *gin.Context) { // redirect.RawQuery = queries.Encode() // c.Redirect(303, redirect.String()) //} else { - // c.JSON(200, ErrorResponse(err)) + // c.JSON(200, ErrorResponse(c, err)) //} } @@ -122,6 +122,6 @@ func GoogleDriveOAuth(c *gin.Context) { // redirect.RawQuery = queries.Encode() // c.Redirect(303, redirect.String()) //} else { - // c.JSON(200, ErrorResponse(err)) + // c.JSON(200, ErrorResponse(c, err)) //} } diff --git a/routers/controllers/main.go b/routers/controllers/main.go index 48ac68f2..73ebcda2 100644 --- a/routers/controllers/main.go +++ b/routers/controllers/main.go @@ -40,11 +40,12 @@ func ParamErrorMsg(filed string, tag string) string { } // ErrorResponse 返回错误消息 -func ErrorResponse(err error) serializer.Response { +func ErrorResponse(c *gin.Context, err error) serializer.Response { // 处理 Validator 产生的错误 if ve, ok := err.(validator.ValidationErrors); ok { for _, e := range ve { - return serializer.ParamErrDeprecated( + return serializer.ParamErr( + c, ParamErrorMsg(e.Field(), e.Tag()), err, ) @@ -52,10 +53,10 @@ func ErrorResponse(err error) serializer.Response { } if _, ok := err.(*json.UnmarshalTypeError); ok { - return serializer.ParamErrDeprecated("JSON marshall error", err) + return serializer.ParamErr(c, "JSON marshall error", err) } - return serializer.ParamErrDeprecated("Parameter error", err) + return serializer.ParamErr(c, "Parameter error", err) } // FromJSON Parse and validate JSON from request body @@ -66,7 +67,7 @@ func FromJSON[T any](ctxKey any) gin.HandlerFunc { c.Request = c.Request.WithContext(context.WithValue(c.Request.Context(), ctxKey, &service)) c.Next() } else { - c.JSON(200, ErrorResponse(err)) + c.JSON(200, ErrorResponse(c, err)) c.Abort() } } @@ -80,7 +81,7 @@ func FromQuery[T any](ctxKey any) gin.HandlerFunc { c.Request = c.Request.WithContext(context.WithValue(c.Request.Context(), ctxKey, &service)) c.Next() } else { - c.JSON(200, ErrorResponse(err)) + c.JSON(200, ErrorResponse(c, err)) c.Abort() } } @@ -93,7 +94,7 @@ func FromForm[T any](ctxKey any) gin.HandlerFunc { c.Request = c.Request.WithContext(context.WithValue(c.Request.Context(), ctxKey, &service)) c.Next() } else { - c.JSON(200, ErrorResponse(err)) + c.JSON(200, ErrorResponse(c, err)) c.Abort() } } @@ -107,7 +108,7 @@ func FromUri[T any](ctxKey any) gin.HandlerFunc { c.Request = c.Request.WithContext(context.WithValue(c.Request.Context(), ctxKey, &service)) c.Next() } else { - c.JSON(200, ErrorResponse(err)) + c.JSON(200, ErrorResponse(c, err)) c.Abort() } } diff --git a/service/admin/file.go b/service/admin/file.go index 192c0d87..4fd7ecea 100644 --- a/service/admin/file.go +++ b/service/admin/file.go @@ -46,13 +46,11 @@ func (service *ListFolderService) List(c *gin.Context) serializer.Response { // // 列取存储策略中的目录 // policy, err := model.GetPolicyByID(service.ID) // if err != nil { - // return serializer.ErrDeprecated(serializer.CodePolicyNotExist, "", err) // } // // // 创建文件系统 // fs, err := filesystem.NewAnonymousFileSystem() // if err != nil { - // return serializer.ErrDeprecated(serializer.CodeCreateFSError, "", err) // } // defer fs.Recycle() // @@ -60,7 +58,6 @@ func (service *ListFolderService) List(c *gin.Context) serializer.Response { // fs.Policy = &policy // res, err := fs.ListPhysical(c.Request.Context(), service.Path) // if err != nil { - // return serializer.ErrDeprecated(serializer.CodeListFilesError, "", err) // } // // return serializer.Response{ @@ -73,20 +70,17 @@ func (service *ListFolderService) List(c *gin.Context) serializer.Response { //// 查找用户 //user, err := model.GetUserByID(service.ID) //if err != nil { - // return serializer.ErrDeprecated(serializer.CodeUserNotFound, "", err) //} // //// 创建文件系统 //fs, err := filesystem.NewFileSystem(&user) //if err != nil { - // return serializer.ErrDeprecated(serializer.CodeCreateFSError, "", err) //} //defer fs.Recycle() // //// 列取目录 //res, err := fs.List(c.Request.Context(), service.Path, nil) //if err != nil { - // return serializer.ErrDeprecated(serializer.CodeListFilesError, "", err) //} //return serializer.Response{ @@ -100,7 +94,6 @@ func (service *ListFolderService) List(c *gin.Context) serializer.Response { func (service *FileBatchService) Delete(c *gin.Context) serializer.Response { //files, err := model.GetFilesByIDs(service.ID, 0) //if err != nil { - // return serializer.DBErrDeprecated("Failed to list files for deleting", err) //} // //// 根据用户分组 diff --git a/service/admin/group.go b/service/admin/group.go index 36b98e74..3b2eddc1 100644 --- a/service/admin/group.go +++ b/service/admin/group.go @@ -27,7 +27,6 @@ type GroupService struct { func (service *GroupService) Get() serializer.Response { //group, err := model.GetGroupByID(service.ID) //if err != nil { - // return serializer.ErrDeprecated(serializer.CodeGroupNotFound, "", err) //} // //return serializer.Response{Data: group} @@ -40,12 +39,10 @@ func (service *GroupService) Delete() serializer.Response { //// 查找用户组 //group, err := model.GetGroupByID(service.ID) //if err != nil { - // return serializer.ErrDeprecated(serializer.CodeGroupNotFound, "", err) //} // //// 是否为系统用户组 //if group.ID <= 3 { - // return serializer.ErrDeprecated(serializer.CodeInvalidActionOnSystemGroup, "", err) //} // //// 检查是否有用户使用 @@ -54,7 +51,6 @@ func (service *GroupService) Delete() serializer.Response { // Select("count(id)").Row() //row.Scan(&total) //if total > 0 { - // return serializer.ErrDeprecated(serializer.CodeGroupUsedByUser, strconv.Itoa(total), nil) //} // //model.DB.Delete(&group) diff --git a/service/admin/policy.go b/service/admin/policy.go index 0d323622..1ef6d989 100644 --- a/service/admin/policy.go +++ b/service/admin/policy.go @@ -136,7 +136,6 @@ func (service *SlavePingService) Test(c *gin.Context) error { func (service *SlaveTestService) Test() serializer.Response { //slave, err := url.Parse(service.Server) //if err != nil { - // return serializer.ParamErrDeprecated("Failed to parse slave node server URL: "+err.Error(), nil) //} // //controller, _ := url.Parse("/api/v3/slave/ping") @@ -147,7 +146,6 @@ func (service *SlaveTestService) Test() serializer.Response { //} //bodyByte, _ := json.Marshal(body) // - //r := request.NewClientDeprecated() //res, err := r.Request( // "POST", // slave.ResolveReference(controller).String(), @@ -159,11 +157,9 @@ func (service *SlaveTestService) Test() serializer.Response { // ), //).DecodeResponse() //if err != nil { - // return serializer.ParamErrDeprecated("Failed to connect to slave node: "+err.Error(), nil) //} // //if res.Code != 0 { - // return serializer.ParamErrDeprecated("Successfully connected to slave node, but slave returns: "+res.Msg, nil) //} return serializer.Response{} @@ -176,7 +172,6 @@ func (service *PathTestService) Test() serializer.Response { //path = filepath.Join(path, "test.txt") //file, err := util.CreatNestedFile(util.RelativePath(path)) //if err != nil { - // return serializer.ParamErrDeprecated(fmt.Sprintf("Failed to create \"%s\": %s", path, err.Error()), nil) //} // //file.Close() diff --git a/service/admin/site.go b/service/admin/site.go index c03347b2..2031f9a2 100644 --- a/service/admin/site.go +++ b/service/admin/site.go @@ -52,14 +52,12 @@ func (service *BatchSettingChangeService) Change() serializer.Response { // if err := tx.Model(&model.Setting{}).Where("name = ?", setting.Key).Update("value", setting.Value).Error; err != nil { // cache.Deletes(cacheClean, "setting_") // tx.Rollback() - // return serializer.ErrDeprecated(serializer.CodeUpdateSetting, "Setting "+setting.Key+" failed to update", err) // } // // cacheClean = append(cacheClean, setting.Key) //} // //if err := tx.Commit().Error; err != nil { - // return serializer.DBErrDeprecated("Failed to update setting", err) //} // //cache.Deletes(cacheClean, "setting_") diff --git a/service/callback/oauth.go b/service/callback/oauth.go index 3f9b6f3a..3a553a8f 100644 --- a/service/callback/oauth.go +++ b/service/callback/oauth.go @@ -17,42 +17,35 @@ type OauthService struct { //// GDriveAuth Google Drive 更新认证信息 //func (service *OauthService) GDriveAuth(c *gin.Context) serializer.Response { // if service.Error != "" { -// return serializer.ParamErrDeprecated(service.Error, nil) // } // // // validate required scope // if missing, found := lo.Find[string](googledrive.RequiredScope, func(item string) bool { // return !strings.Contains(service.Scope, item) // }); found { -// return serializer.ParamErrDeprecated(fmt.Sprintf("Missing required scope: %s", missing), nil) // } // // policyID, ok := util.GetSession(c, "googledrive_oauth_policy").(uint) // if !ok { -// return serializer.ErrDeprecated(serializer.CodeNotFound, "", nil) // } // // util.DeleteSession(c, "googledrive_oauth_policy") // // policy, err := model.GetPolicyByID(policyID) // if err != nil { -// return serializer.ErrDeprecated(serializer.CodePolicyNotExist, "", nil) // } // // client, err := googledrive.NewClient(&policy) // if err != nil { -// return serializer.ErrDeprecated(serializer.CodeInternalSetting, "Failed to initialize Google Drive client", err) // } // // credential, err := client.ObtainToken(c, service.Code, "") // if err != nil { -// return serializer.ErrDeprecated(serializer.CodeInternalSetting, "Failed to fetch AccessToken", err) // } // // // 更新存储策略的 RefreshToken // client.Policy.AccessKey = credential.RefreshToken // if err := client.Policy.SaveAndClearCache(); err != nil { -// return serializer.DBErrDeprecated("Failed to update RefreshToken", err) // } // // cache.Deletes([]string{client.Policy.AccessKey}, googledrive.TokenCachePrefix) @@ -62,41 +55,34 @@ type OauthService struct { // OdAuth OneDrive 更新认证信息 func (service *OauthService) OdAuth(c *gin.Context) serializer.Response { //if service.Error != "" { - // return serializer.ParamErrDeprecated(service.ErrorMsg, nil) //} // //policyID, ok := util.GetSession(c, "onedrive_oauth_policy").(uint) //if !ok { - // return serializer.ErrDeprecated(serializer.CodeNotFound, "", nil) //} // //util.DeleteSession(c, "onedrive_oauth_policy") // //policy, err := model.GetPolicyByID(policyID) //if err != nil { - // return serializer.ErrDeprecated(serializer.CodePolicyNotExist, "", nil) //} // //client, err := onedrive.NewClient(&policy) //if err != nil { - // return serializer.ErrDeprecated(serializer.CodeInternalSetting, "Failed to initialize OneDrive client", err) //} // //credential, err := client.ObtainToken(c, onedrive.WithCode(service.Code)) //if err != nil { - // return serializer.ErrDeprecated(serializer.CodeInternalSetting, "Failed to fetch AccessToken", err) //} // //// 更新存储策略的 RefreshToken //client.Policy.AccessKey = credential.RefreshToken //if err := client.Policy.SaveAndClearCache(); err != nil { - // return serializer.DBErrDeprecated("Failed to update RefreshToken", err) //} // //cache.Deletes([]string{client.Policy.AccessKey}, "onedrive_") //if client.Policy.OptionsSerialized.OdDriver != "" && strings.Contains(client.Policy.OptionsSerialized.OdDriver, "http") { // if err := querySharePointSiteID(c, client.Policy); err != nil { - // return serializer.ErrDeprecated(serializer.CodeInternalSetting, "Failed to query SharePoint basic ID", err) // } //} diff --git a/service/callback/upload.go b/service/callback/upload.go index 057c75eb..01c108e5 100644 --- a/service/callback/upload.go +++ b/service/callback/upload.go @@ -64,7 +64,6 @@ func ProcessCallback(c *gin.Context) error { // // 创建文件系统 // fs, err := filesystem.NewFileSystemFromCallback(c) // if err != nil { -// return serializer.ErrDeprecated(serializer.CodeCreateFSError, "", err) // } // defer fs.Recycle() // @@ -74,7 +73,6 @@ func ProcessCallback(c *gin.Context) error { // // 获取文件信息 // info, err := fs.Handler.(onedrive.Driver).Client.Meta(context.Background(), "", uploadSession.SavePath) // if err != nil { -// return serializer.ErrDeprecated(serializer.CodeQueryMetaFailed, "", err) // } // // // 验证与回调会话中是否一致 @@ -89,7 +87,6 @@ func ProcessCallback(c *gin.Context) error { // // if isSizeCheckFailed || !strings.EqualFold(info.GetSourcePath(), actualPath) { // fs.Handler.(onedrive.Driver).Client.Delete(context.Background(), []string{info.GetSourcePath()}) -// return serializer.ErrDeprecated(serializer.CodeMetaMismatch, "", err) // } // service.Meta = info // return ProcessCallback(c) @@ -102,7 +99,6 @@ func ProcessCallback(c *gin.Context) error { // // 创建文件系统 // fs, err := filesystem.NewFileSystemFromCallback(c) // if err != nil { -// return serializer.ErrDeprecated(serializer.CodeCreateFSError, "", err) // } // defer fs.Recycle() // @@ -112,12 +108,10 @@ func ProcessCallback(c *gin.Context) error { // // 获取文件信息 // info, err := fs.Handler.(*s3.Driver).Meta(context.Background(), uploadSession.SavePath) // if err != nil { -// return serializer.ErrDeprecated(serializer.CodeMetaMismatch, "", err) // } // // // 验证实际文件信息与回调会话中是否一致 // if uploadSession.Size != info.Size { -// return serializer.ErrDeprecated(serializer.CodeMetaMismatch, "", err) // } // // return ProcessCallback(service, c) @@ -128,7 +122,6 @@ func ProcessCallback(c *gin.Context) error { // // 创建文件系统 // fs, err := filesystem.NewFileSystemFromCallback(c) // if err != nil { -// return serializer.ErrDeprecated(serializer.CodeCreateFSError, "", err) // } // defer fs.Recycle() // @@ -138,7 +131,6 @@ func ProcessCallback(c *gin.Context) error { // // 验证文件大小 // if uploadSession.Size != service.Size { // fs.Handler.Delete(context.Background(), []string{uploadSession.SavePath}) -// return serializer.ErrDeprecated(serializer.CodeMetaMismatch, "", err) // } // // return ProcessCallback(service, c) diff --git a/service/setting/webdav.go b/service/setting/webdav.go index 3ed88001..9d194996 100644 --- a/service/setting/webdav.go +++ b/service/setting/webdav.go @@ -42,11 +42,9 @@ type WebDAVMountCreateService struct { // folderID, _ := c.Get("object_id") // folder, err := model.GetFoldersByIDs([]uint{folderID.(uint)}, user.ID) // if err != nil || len(folder) == 0 { -// return serializer.ErrDeprecated(serializer.CodeParentNotExist, "", err) // } // // if err := folder[0].Mount(0); err != nil { -// return serializer.DBErrDeprecated("Failed to update folder record", err) // } // // return serializer.Response{}