mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-04 07:06:36 +08:00
refactor(util): move response helper to common/response and session logic to oauth
- Relocated generic HTTP response helpers (Response, OK, Err, etc.) from internal/util/ to a dedicated internal/common/response/ package. - Renamed ResponseAny to Any to resolve revive stuttering warnings. - Moved session building options and cookie headers logic from internal/util/ to internal/apps/oauth/. - Removed all direct imports of Gin/Sessions/HTTP frameworks from internal/util/ to keep general utilities 100% pure. - Regenerated Swagger API documentation via make swagger. - All tests and make code-check compile and pass with 0 issues.
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/apps/oauth"
|
||||
"github.com/Rain-kl/Wavelet/internal/common/response"
|
||||
"github.com/Rain-kl/Wavelet/internal/db"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
"github.com/Rain-kl/Wavelet/internal/util"
|
||||
@@ -46,16 +47,16 @@ type listFilesResponse struct {
|
||||
// @Param extension query string false "扩展名过滤"
|
||||
// @Param user_id query uint64 false "上传用户 ID"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} util.ResponseAny{data=listFilesResponse} "查询成功"
|
||||
// @Failure 401 {object} util.ResponseAny "未登录"
|
||||
// @Failure 403 {object} util.ResponseAny "无管理员权限"
|
||||
// @Success 200 {object} response.Any{data=listFilesResponse} "查询成功"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 403 {object} response.Any "无管理员权限"
|
||||
// @Router /api/v1/admin/uploads [get]
|
||||
func ListFiles(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
var req listFilesRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrInvalidParams))
|
||||
c.JSON(http.StatusOK, response.Err(ErrInvalidParams))
|
||||
return
|
||||
}
|
||||
if req.Page <= 0 {
|
||||
@@ -83,18 +84,18 @@ func ListFiles(c *gin.Context) {
|
||||
|
||||
var total int64
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrQueryFileCountFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrQueryFileCountFailed))
|
||||
return
|
||||
}
|
||||
|
||||
var items []model.Upload
|
||||
offset := (req.Page - 1) * req.PageSize
|
||||
if err := query.Order("created_at DESC").Offset(offset).Limit(req.PageSize).Find(&items).Error; err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrQueryFileListFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrQueryFileListFailed))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, util.OK(listFilesResponse{
|
||||
c.JSON(http.StatusOK, response.OK(listFilesResponse{
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
@@ -109,20 +110,20 @@ func ListFiles(c *gin.Context) {
|
||||
// @Produce json
|
||||
// @Param id path string true "文件 ID"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} util.ResponseAny "删除成功"
|
||||
// @Failure 403 {object} util.ResponseAny "无权操作"
|
||||
// @Failure 404 {object} util.ResponseAny "文件不存在"
|
||||
// @Success 200 {object} response.Any "删除成功"
|
||||
// @Failure 403 {object} response.Any "无权操作"
|
||||
// @Failure 404 {object} response.Any "文件不存在"
|
||||
// @Router /api/v1/admin/uploads/{id} [delete]
|
||||
func DeleteFile(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
if StorageReadOnly(ctx) {
|
||||
c.JSON(http.StatusConflict, util.Err(ErrStorageReadOnly))
|
||||
c.JSON(http.StatusConflict, response.Err(ErrStorageReadOnly))
|
||||
return
|
||||
}
|
||||
|
||||
uploadID, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrInvalidFileID))
|
||||
c.JSON(http.StatusOK, response.Err(ErrInvalidFileID))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -132,14 +133,14 @@ func DeleteFile(c *gin.Context) {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, util.Err(ErrQueryUploadRecordFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrQueryUploadRecordFailed))
|
||||
return
|
||||
}
|
||||
if err := db.DB(ctx).Model(&upload).Update("status", model.UploadStatusDeleted).Error; err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrDeleteFileFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrDeleteFileFailed))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, util.OKNil())
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
}
|
||||
|
||||
// GetDistinctUploadTypes 获取数据库中所有已存在的文件业务类型
|
||||
@@ -148,10 +149,10 @@ func DeleteFile(c *gin.Context) {
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} util.ResponseAny{data=[]string} "业务类型列表"
|
||||
// @Failure 401 {object} util.ResponseAny "未登录"
|
||||
// @Failure 403 {object} util.ResponseAny "无管理员权限"
|
||||
// @Failure 500 {object} util.ResponseAny "内部错误"
|
||||
// @Success 200 {object} response.Any{data=[]string} "业务类型列表"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 403 {object} response.Any "无管理员权限"
|
||||
// @Failure 500 {object} response.Any "内部错误"
|
||||
// @Router /api/v1/admin/uploads/types [get]
|
||||
func GetDistinctUploadTypes(c *gin.Context) {
|
||||
var dbTypes []string
|
||||
@@ -159,11 +160,11 @@ func GetDistinctUploadTypes(c *gin.Context) {
|
||||
Where("type IS NOT NULL AND type != ''").
|
||||
Distinct().
|
||||
Pluck("type", &dbTypes).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, util.Err(err.Error()))
|
||||
c.JSON(http.StatusInternalServerError, response.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
sort.Strings(dbTypes)
|
||||
c.JSON(http.StatusOK, util.OK(dbTypes))
|
||||
c.JSON(http.StatusOK, response.OK(dbTypes))
|
||||
}
|
||||
|
||||
type listMyFilesRequest struct {
|
||||
@@ -192,8 +193,8 @@ type listMyFilesResponse struct {
|
||||
// @Param type query string false "业务分类过滤"
|
||||
// @Param extension query string false "扩展名过滤"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} util.ResponseAny{data=listMyFilesResponse} "查询成功"
|
||||
// @Failure 401 {object} util.ResponseAny "未登录"
|
||||
// @Success 200 {object} response.Any{data=listMyFilesResponse} "查询成功"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Router /api/v1/upload/my [get]
|
||||
func ListMyFiles(c *gin.Context) {
|
||||
currUser, _ := util.GetFromContext[*model.User](c, oauth.UserObjKey)
|
||||
@@ -201,7 +202,7 @@ func ListMyFiles(c *gin.Context) {
|
||||
|
||||
var req listMyFilesRequest
|
||||
if err := c.ShouldBindQuery(&req); err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrInvalidParams))
|
||||
c.JSON(http.StatusOK, response.Err(ErrInvalidParams))
|
||||
return
|
||||
}
|
||||
if req.Page <= 0 {
|
||||
@@ -226,18 +227,18 @@ func ListMyFiles(c *gin.Context) {
|
||||
|
||||
var total int64
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrQueryFileCountFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrQueryFileCountFailed))
|
||||
return
|
||||
}
|
||||
|
||||
var items []model.Upload
|
||||
offset := (req.Page - 1) * req.PageSize
|
||||
if err := query.Order("created_at DESC").Offset(offset).Limit(req.PageSize).Find(&items).Error; err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrQueryFileListFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrQueryFileListFailed))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, util.OK(listMyFilesResponse{
|
||||
c.JSON(http.StatusOK, response.OK(listMyFilesResponse{
|
||||
Total: total,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
@@ -252,21 +253,21 @@ func ListMyFiles(c *gin.Context) {
|
||||
// @Produce json
|
||||
// @Param id path string true "文件 ID"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} util.ResponseAny "删除成功"
|
||||
// @Failure 403 {object} util.ResponseAny "无权操作"
|
||||
// @Failure 404 {object} util.ResponseAny "文件不存在"
|
||||
// @Success 200 {object} response.Any "删除成功"
|
||||
// @Failure 403 {object} response.Any "无权操作"
|
||||
// @Failure 404 {object} response.Any "文件不存在"
|
||||
// @Router /api/v1/upload/{id} [delete]
|
||||
func DeleteMyFile(c *gin.Context) {
|
||||
currUser, _ := util.GetFromContext[*model.User](c, oauth.UserObjKey)
|
||||
ctx := c.Request.Context()
|
||||
if StorageReadOnly(ctx) {
|
||||
c.JSON(http.StatusConflict, util.Err(ErrStorageReadOnly))
|
||||
c.JSON(http.StatusConflict, response.Err(ErrStorageReadOnly))
|
||||
return
|
||||
}
|
||||
|
||||
uploadID, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrInvalidFileID))
|
||||
c.JSON(http.StatusOK, response.Err(ErrInvalidFileID))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -276,7 +277,7 @@ func DeleteMyFile(c *gin.Context) {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, util.Err(ErrQueryUploadRecordFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrQueryUploadRecordFailed))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -286,10 +287,10 @@ func DeleteMyFile(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := db.DB(ctx).Model(&upload).Update("status", model.UploadStatusDeleted).Error; err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrDeleteFileFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrDeleteFileFailed))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, util.OKNil())
|
||||
c.JSON(http.StatusOK, response.OKNil())
|
||||
}
|
||||
|
||||
type updateMyFileRequest struct {
|
||||
@@ -306,27 +307,27 @@ type updateMyFileRequest struct {
|
||||
// @Param id path string true "文件 ID"
|
||||
// @Param request body updateMyFileRequest true "更新字段"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} util.ResponseAny{data=model.Upload} "更新成功"
|
||||
// @Failure 403 {object} util.ResponseAny "无权操作"
|
||||
// @Failure 404 {object} util.ResponseAny "文件不存在"
|
||||
// @Success 200 {object} response.Any{data=model.Upload} "更新成功"
|
||||
// @Failure 403 {object} response.Any "无权操作"
|
||||
// @Failure 404 {object} response.Any "文件不存在"
|
||||
// @Router /api/v1/upload/{id} [put]
|
||||
func UpdateMyFile(c *gin.Context) {
|
||||
currUser, _ := util.GetFromContext[*model.User](c, oauth.UserObjKey)
|
||||
ctx := c.Request.Context()
|
||||
if StorageReadOnly(ctx) {
|
||||
c.JSON(http.StatusConflict, util.Err(ErrStorageReadOnly))
|
||||
c.JSON(http.StatusConflict, response.Err(ErrStorageReadOnly))
|
||||
return
|
||||
}
|
||||
|
||||
uploadID, err := strconv.ParseUint(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrInvalidFileID))
|
||||
c.JSON(http.StatusOK, response.Err(ErrInvalidFileID))
|
||||
return
|
||||
}
|
||||
|
||||
var req updateMyFileRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrInvalidParams))
|
||||
c.JSON(http.StatusOK, response.Err(ErrInvalidParams))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -336,7 +337,7 @@ func UpdateMyFile(c *gin.Context) {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, util.Err(ErrQueryUploadRecordFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrQueryUploadRecordFailed))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -355,10 +356,10 @@ func UpdateMyFile(c *gin.Context) {
|
||||
|
||||
if len(updates) > 0 {
|
||||
if err := db.DB(ctx).Model(&upload).Updates(updates).Error; err != nil {
|
||||
c.JSON(http.StatusOK, util.Err("更新文件记录失败"))
|
||||
c.JSON(http.StatusOK, response.Err("更新文件记录失败"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, util.OK(upload))
|
||||
c.JSON(http.StatusOK, response.OK(upload))
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
package upload
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
import ("bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -34,10 +33,10 @@ import (
|
||||
// @Param id path string true "文件 ID"
|
||||
// @Param quality query string false "图片质量 (low, medium, high, origin),默认为 origin"
|
||||
// @Success 200 {file} file "成功获取文件内容"
|
||||
// @Failure 400 {object} util.ResponseAny "文件 ID 格式错误"
|
||||
// @Failure 401 {object} util.ResponseAny "未登录"
|
||||
// @Failure 404 {object} util.ResponseAny "文件未找到"
|
||||
// @Failure 500 {object} util.ResponseAny "服务内部错误"
|
||||
// @Failure 400 {object} response.Any "文件 ID 格式错误"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 404 {object} response.Any "文件未找到"
|
||||
// @Failure 500 {object} response.Any "服务内部错误"
|
||||
// @Router /f/{id} [get]
|
||||
func ServeFileByID(c *gin.Context) {
|
||||
upload, err := getUploadRecordByID(c)
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
package upload
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
import ("archive/zip"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
@@ -32,6 +31,7 @@ import (
|
||||
"github.com/Rain-kl/Wavelet/pkg/logger"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
"github.com/Rain-kl/Wavelet/internal/common/response"
|
||||
)
|
||||
|
||||
type batchDownloadRequest struct {
|
||||
@@ -48,10 +48,10 @@ type batchDownloadRequest struct {
|
||||
// @Param type formData string false "业务分类 (例如: avatar, attachment, doc,默认为 generic)"
|
||||
// @Param metadata formData string false "额外的 JSON 格式元数据"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} util.ResponseAny{data=model.Upload} "上传成功"
|
||||
// @Failure 400 {object} util.ResponseAny "请求参数错误或文件受限"
|
||||
// @Failure 401 {object} util.ResponseAny "未登录"
|
||||
// @Failure 500 {object} util.ResponseAny "内部错误"
|
||||
// @Success 200 {object} response.Any{data=model.Upload} "上传成功"
|
||||
// @Failure 400 {object} response.Any "请求参数错误或文件受限"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 500 {object} response.Any "内部错误"
|
||||
// @Router /api/v1/upload [post]
|
||||
//
|
||||
//nolint:revive
|
||||
@@ -67,20 +67,20 @@ func UploadFile(c *gin.Context) {
|
||||
|
||||
header, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrNoFileSelected))
|
||||
c.JSON(http.StatusOK, response.Err(ErrNoFileSelected))
|
||||
return
|
||||
}
|
||||
|
||||
file, err := header.Open()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrOpenFileFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrOpenFileFailed))
|
||||
return
|
||||
}
|
||||
defer func() { _ = file.Close() }()
|
||||
|
||||
// 校验大小
|
||||
if header.Size > maxUploadSize {
|
||||
c.JSON(http.StatusOK, util.Err(ErrGenericFileTooLarge))
|
||||
c.JSON(http.StatusOK, response.Err(ErrGenericFileTooLarge))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ func UploadFile(c *gin.Context) {
|
||||
|
||||
// 3. 校验文件后缀是否在允许的系统配置列表中
|
||||
if errMsg := validateUploadExtension(ctx, ext); errMsg != "" {
|
||||
c.JSON(http.StatusOK, util.Err(errMsg))
|
||||
c.JSON(http.StatusOK, response.Err(errMsg))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func UploadFile(c *gin.Context) {
|
||||
var buf bytes.Buffer
|
||||
size, err := io.Copy(&buf, io.TeeReader(file, hashWriter))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrProcessFileFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrProcessFileFailed))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ func UploadFile(c *gin.Context) {
|
||||
|
||||
// 校验真实 MIME Type 是否与常见图片扩展名匹配,防止 Polyglot / HTML 注入攻击
|
||||
if isImageExtension(ext) && !strings.HasPrefix(mimeType, "image/") {
|
||||
c.JSON(http.StatusOK, util.Err(ErrFileContentExtensionMismatch))
|
||||
c.JSON(http.StatusOK, response.Err(ErrFileContentExtensionMismatch))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ func UploadFile(c *gin.Context) {
|
||||
var err error
|
||||
accessMode, err = strconv.Atoi(accessModeStr)
|
||||
if err != nil || (accessMode != 0 && accessMode != 1) {
|
||||
c.JSON(http.StatusOK, util.Err("无效的 access_mode 参数"))
|
||||
c.JSON(http.StatusOK, response.Err("无效的 access_mode 参数"))
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -140,14 +140,14 @@ func UploadFile(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if lookupErr != nil && !errors.Is(lookupErr, gorm.ErrRecordNotFound) {
|
||||
c.JSON(http.StatusOK, util.Err(ErrFileValidationFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrFileValidationFailed))
|
||||
return
|
||||
}
|
||||
|
||||
// 7. 解析可选元数据字段
|
||||
meta, errMsg := parseUploadMetadata(c, mimeType)
|
||||
if errMsg != "" {
|
||||
c.JSON(http.StatusOK, util.Err(errMsg))
|
||||
c.JSON(http.StatusOK, response.Err(errMsg))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ func UploadFile(c *gin.Context) {
|
||||
// 8. 写入当前活动存储驱动。
|
||||
storageDriver, subPath, errMsg := storeUploadFile(ctx, subPath, size, mimeType, &buf, &meta)
|
||||
if errMsg != "" {
|
||||
c.JSON(http.StatusOK, util.Err(errMsg))
|
||||
c.JSON(http.StatusOK, response.Err(errMsg))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -179,11 +179,11 @@ func UploadFile(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := saveUploadRecord(ctx, &newUpload, storageDriver, subPath); err != "" {
|
||||
c.JSON(http.StatusOK, util.Err(err))
|
||||
c.JSON(http.StatusOK, response.Err(err))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, util.OK(newUpload))
|
||||
c.JSON(http.StatusOK, response.OK(newUpload))
|
||||
}
|
||||
|
||||
// DownloadFile 通用单文件下载接口
|
||||
@@ -195,9 +195,9 @@ func UploadFile(c *gin.Context) {
|
||||
// @Param quality query string false "图片质量 (low, medium, high, origin),默认为 origin"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {file} file "成功下载文件"
|
||||
// @Failure 400 {object} util.ResponseAny "参数错误"
|
||||
// @Failure 404 {object} util.ResponseAny "文件不存在"
|
||||
// @Failure 500 {object} util.ResponseAny "服务内部错误"
|
||||
// @Failure 400 {object} response.Any "参数错误"
|
||||
// @Failure 404 {object} response.Any "文件不存在"
|
||||
// @Failure 500 {object} response.Any "服务内部错误"
|
||||
// @Router /api/v1/admin/uploads/download/{id} [get]
|
||||
func DownloadFile(c *gin.Context) {
|
||||
upload, err := getUploadRecordByID(c)
|
||||
@@ -207,10 +207,10 @@ func DownloadFile(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if _, ok := err.(*strconv.NumError); ok {
|
||||
c.JSON(http.StatusOK, util.Err(ErrInvalidFileID))
|
||||
c.JSON(http.StatusOK, response.Err(ErrInvalidFileID))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, util.Err(ErrQueryUploadRecordFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrQueryUploadRecordFailed))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -247,15 +247,15 @@ func DownloadFile(c *gin.Context) {
|
||||
// @Param request body upload.batchDownloadRequest true "包含文件 ID 数组 of string 的请求体"
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {file} file "成功下载打包后的 ZIP"
|
||||
// @Failure 400 {object} util.ResponseAny "参数错误"
|
||||
// @Failure 500 {object} util.ResponseAny "打包失败"
|
||||
// @Failure 400 {object} response.Any "参数错误"
|
||||
// @Failure 500 {object} response.Any "打包失败"
|
||||
// @Router /api/v1/admin/uploads/download/batch [post]
|
||||
func BatchDownloadFiles(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
|
||||
var req batchDownloadRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrInvalidBatchDownloadRequest))
|
||||
c.JSON(http.StatusOK, response.Err(ErrInvalidBatchDownloadRequest))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ func BatchDownloadFiles(c *gin.Context) {
|
||||
for _, idStr := range req.IDs {
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(fmt.Sprintf(ErrInvalidIDValueFormat, idStr)))
|
||||
c.JSON(http.StatusOK, response.Err(fmt.Sprintf(ErrInvalidIDValueFormat, idStr)))
|
||||
return
|
||||
}
|
||||
ids = append(ids, id)
|
||||
@@ -273,12 +273,12 @@ func BatchDownloadFiles(c *gin.Context) {
|
||||
// 查库获取所有匹配且正常的文件记录
|
||||
var uploads []model.Upload
|
||||
if err := db.DB(ctx).Where("id IN ? AND status IN (?, ?)", ids, model.UploadStatusPending, model.UploadStatusUsed).Find(&uploads).Error; err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrRetrieveUploadRecordsFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrRetrieveUploadRecordsFailed))
|
||||
return
|
||||
}
|
||||
|
||||
if len(uploads) == 0 {
|
||||
c.JSON(http.StatusOK, util.Err(ErrNoValidFilesForArchive))
|
||||
c.JSON(http.StatusOK, response.Err(ErrNoValidFilesForArchive))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ func tryInstantUpload(ctx context.Context, c *gin.Context, currUser *model.User,
|
||||
return false, err
|
||||
}
|
||||
if StorageReadOnly(ctx) {
|
||||
c.JSON(http.StatusConflict, util.Err(ErrStorageReadOnly))
|
||||
c.JSON(http.StatusConflict, response.Err(ErrStorageReadOnly))
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -385,12 +385,12 @@ func tryInstantUpload(ctx context.Context, c *gin.Context, currUser *model.User,
|
||||
}
|
||||
|
||||
if err := db.DB(ctx).Create(&newUpload).Error; err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(ErrSaveUploadRecordFailed))
|
||||
c.JSON(http.StatusOK, response.Err(ErrSaveUploadRecordFailed))
|
||||
return true, err
|
||||
}
|
||||
|
||||
logger.InfoF(ctx, "文件触发秒传成功! ID: %d, Path: %s", id, existing.FilePath)
|
||||
c.JSON(http.StatusOK, util.OK(newUpload))
|
||||
c.JSON(http.StatusOK, response.OK(newUpload))
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
|
||||
package upload
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
import ("net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/db"
|
||||
"github.com/Rain-kl/Wavelet/internal/model"
|
||||
"github.com/Rain-kl/Wavelet/internal/util"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/common/response")
|
||||
|
||||
const (
|
||||
catImage = "图片"
|
||||
@@ -49,10 +48,10 @@ type fileStatsResponse struct {
|
||||
// @Tags admin
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} util.ResponseAny{data=fileStatsResponse} "获取成功"
|
||||
// @Failure 401 {object} util.ResponseAny "未登录"
|
||||
// @Failure 403 {object} util.ResponseAny "无管理员权限"
|
||||
// @Failure 500 {object} util.ResponseAny "内部错误"
|
||||
// @Success 200 {object} response.Any{data=fileStatsResponse} "获取成功"
|
||||
// @Failure 401 {object} response.Any "未登录"
|
||||
// @Failure 403 {object} response.Any "无管理员权限"
|
||||
// @Failure 500 {object} response.Any "内部错误"
|
||||
// @Router /api/v1/admin/uploads/stats [get]
|
||||
func GetFileStats(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
@@ -67,7 +66,7 @@ func GetFileStats(c *gin.Context) {
|
||||
Where("status != ?", model.UploadStatusDeleted).
|
||||
Scan(&summary).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(err.Error()))
|
||||
c.JSON(http.StatusOK, response.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -84,7 +83,7 @@ func GetFileStats(c *gin.Context) {
|
||||
Group("type").
|
||||
Scan(&typeRaw).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(err.Error()))
|
||||
c.JSON(http.StatusOK, response.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -113,7 +112,7 @@ func GetFileStats(c *gin.Context) {
|
||||
Where("status != ?", model.UploadStatusDeleted).
|
||||
Scan(&fileRaws).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(err.Error()))
|
||||
c.JSON(http.StatusOK, response.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -154,7 +153,7 @@ func GetFileStats(c *gin.Context) {
|
||||
Where("status != ? AND created_at >= ?", model.UploadStatusDeleted, startTime).
|
||||
Scan(&trendRaws).Error
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, util.Err(err.Error()))
|
||||
c.JSON(http.StatusOK, response.Err(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -185,7 +184,7 @@ func GetFileStats(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, util.OK(fileStatsResponse{
|
||||
c.JSON(http.StatusOK, response.OK(fileStatsResponse{
|
||||
TotalCount: summary.TotalCount,
|
||||
TotalSize: summary.TotalSize,
|
||||
Trend: trend,
|
||||
|
||||
Reference in New Issue
Block a user