Initial commit: 网络验证平台
This commit is contained in:
@@ -0,0 +1,827 @@
|
||||
package developer
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"verification-platform-backend/internal/database"
|
||||
"verification-platform-backend/internal/middleware"
|
||||
"verification-platform-backend/internal/model"
|
||||
"verification-platform-backend/internal/service"
|
||||
"verification-platform-backend/pkg/response"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func SetupCloudRoutes(r *gin.RouterGroup) {
|
||||
cloudConstants := r.Group("/cloud-constants")
|
||||
{
|
||||
cloudConstants.GET("", handleGetCloudConstants)
|
||||
cloudConstants.GET("/:id", handleGetCloudConstant)
|
||||
cloudConstants.GET("/:id/download", handleDownloadCloudConstant)
|
||||
cloudConstants.POST("", handleCreateCloudConstant)
|
||||
cloudConstants.POST("/upload", handleUploadCloudConstant)
|
||||
cloudConstants.PUT("/:id", handleUpdateCloudConstant)
|
||||
cloudConstants.DELETE("/:id", handleDeleteCloudConstant)
|
||||
}
|
||||
|
||||
cloudVariables := r.Group("/cloud-variables")
|
||||
{
|
||||
cloudVariables.GET("", handleGetCloudVariables)
|
||||
cloudVariables.GET("/:id", handleGetCloudVariable)
|
||||
cloudVariables.GET("/:id/download", handleDownloadCloudVariable)
|
||||
cloudVariables.POST("", handleCreateCloudVariable)
|
||||
cloudVariables.POST("/upload", handleUploadCloudVariable)
|
||||
cloudVariables.PUT("/:id", handleUpdateCloudVariable)
|
||||
cloudVariables.DELETE("/:id", handleDeleteCloudVariable)
|
||||
cloudVariables.GET("/:id/records", handleGetCloudVariableRecords)
|
||||
cloudVariables.DELETE("/:id/records", handleDeleteCloudVariableRecords)
|
||||
}
|
||||
}
|
||||
|
||||
func handleGetCloudConstants(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
appID := c.Query("app_id")
|
||||
|
||||
var constants []model.CloudConstant
|
||||
query := database.DB.Where("user_id = ?", userID)
|
||||
if appID != "" {
|
||||
query = query.Where("app_id = ?", appID)
|
||||
}
|
||||
if err := query.Find(&constants).Error; err != nil {
|
||||
response.Error(c, 500, "获取云端常量失败")
|
||||
return
|
||||
}
|
||||
response.Success(c, gin.H{
|
||||
"constants": constants,
|
||||
"total": len(constants),
|
||||
})
|
||||
}
|
||||
|
||||
func handleGetCloudConstant(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
id := c.Param("id")
|
||||
|
||||
var constant model.CloudConstant
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).First(&constant).Error; err != nil {
|
||||
response.Error(c, 404, "云端常量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, constant)
|
||||
}
|
||||
|
||||
func handleCreateCloudConstant(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
|
||||
var req struct {
|
||||
AppID uint `json:"app_id"`
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
VarType string `json:"var_type"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Key == "" {
|
||||
response.Error(c, 400, "变量名不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Status != "active" && req.Status != "inactive" {
|
||||
req.Status = "active"
|
||||
}
|
||||
|
||||
if req.VarType == "" {
|
||||
req.VarType = "string"
|
||||
}
|
||||
|
||||
constant := model.CloudConstant{
|
||||
UserID: userID,
|
||||
AppID: &req.AppID,
|
||||
Key: req.Key,
|
||||
Value: req.Value,
|
||||
VarType: req.VarType,
|
||||
Description: req.Description,
|
||||
Status: req.Status,
|
||||
}
|
||||
|
||||
if err := database.DB.Create(&constant).Error; err != nil {
|
||||
response.Error(c, 500, "创建云端常量失败")
|
||||
return
|
||||
}
|
||||
|
||||
service.LogOperation(c, "create", "cloud_constant", &constant.ID, fmt.Sprintf("创建云端常量: %s", constant.Key), nil)
|
||||
|
||||
response.Success(c, constant)
|
||||
}
|
||||
|
||||
func handleUpdateCloudConstant(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
|
||||
var req struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
VarType string `json:"var_type"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
id := c.Param("id")
|
||||
var constant model.CloudConstant
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).First(&constant).Error; err != nil {
|
||||
response.Error(c, 404, "云端常量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
constant.Key = req.Key
|
||||
constant.Value = req.Value
|
||||
constant.VarType = req.VarType
|
||||
constant.Description = req.Description
|
||||
if req.Status == "active" || req.Status == "inactive" {
|
||||
constant.Status = req.Status
|
||||
}
|
||||
|
||||
if err := database.DB.Save(&constant).Error; err != nil {
|
||||
response.Error(c, 500, "更新云端常量失败")
|
||||
return
|
||||
}
|
||||
|
||||
service.LogOperation(c, "update", "cloud_constant", &constant.ID, fmt.Sprintf("更新云端常量: %s", constant.Key), nil)
|
||||
|
||||
response.Success(c, constant)
|
||||
}
|
||||
|
||||
func handleDeleteCloudConstant(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
|
||||
id := c.Param("id")
|
||||
|
||||
var constant model.CloudConstant
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).First(&constant).Error; err != nil {
|
||||
response.Error(c, 404, "云端常量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
if constant.VarType == "binary" && constant.FilePath != "" {
|
||||
if err := middleware.UpdateStorageUsed(userID, constant.FileSize, "delete"); err != nil {
|
||||
fmt.Printf("更新存储使用量失败: %v\n", err)
|
||||
}
|
||||
filePath := strings.TrimPrefix(constant.FilePath, "/")
|
||||
if _, err := os.Stat(filePath); err == nil {
|
||||
os.Remove(filePath)
|
||||
}
|
||||
}
|
||||
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).Delete(&model.CloudConstant{}).Error; err != nil {
|
||||
response.Error(c, 500, "删除云端常量失败")
|
||||
return
|
||||
}
|
||||
|
||||
service.LogOperation(c, "delete", "cloud_constant", &constant.ID, fmt.Sprintf("删除云端常量: %s", constant.Key), nil)
|
||||
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
func handleUploadCloudConstant(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
|
||||
file, header, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
response.Error(c, 400, "请选择要上传的文件")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
appIDStr := c.PostForm("app_id")
|
||||
key := c.PostForm("key")
|
||||
description := c.PostForm("description")
|
||||
status := c.PostForm("status")
|
||||
|
||||
if appIDStr == "" {
|
||||
response.Error(c, 400, "请选择应用")
|
||||
return
|
||||
}
|
||||
|
||||
if key == "" {
|
||||
response.Error(c, 400, "请输入变量名")
|
||||
return
|
||||
}
|
||||
|
||||
var appID uint
|
||||
fmt.Sscanf(appIDStr, "%d", &appID)
|
||||
|
||||
if status != "active" && status != "inactive" {
|
||||
status = "active"
|
||||
}
|
||||
|
||||
var user model.User
|
||||
if err := database.DB.First(&user, userID).Error; err != nil {
|
||||
response.Error(c, 500, "获取用户信息失败")
|
||||
return
|
||||
}
|
||||
|
||||
if user.CurrentPackageID != nil {
|
||||
var permission model.PackagePermission
|
||||
if err := database.DB.Where("package_id = ?", user.CurrentPackageID).First(&permission).Error; err == nil {
|
||||
maxStorageBytes := int64(permission.MaxStorage) * 1024 * 1024
|
||||
if user.StorageUsed+header.Size > maxStorageBytes {
|
||||
usedMB := float64(user.StorageUsed) / 1024 / 1024
|
||||
maxMB := float64(permission.MaxStorage)
|
||||
response.Error(c, 403, fmt.Sprintf("存储空间不足,已使用 %.2f MB / %.2f MB", usedMB, maxMB))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uploadDir := "uploads/cloud-files"
|
||||
if err := os.MkdirAll(uploadDir, 0755); err != nil {
|
||||
response.Error(c, 500, "创建上传目录失败")
|
||||
return
|
||||
}
|
||||
|
||||
ext := filepath.Ext(header.Filename)
|
||||
filename := fmt.Sprintf("%d_%d%s", userID, time.Now().UnixNano(), ext)
|
||||
filePath := filepath.Join(uploadDir, filename)
|
||||
|
||||
dst, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
response.Error(c, 500, "创建文件失败")
|
||||
return
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
hash := md5.New()
|
||||
multiWriter := io.MultiWriter(dst, hash)
|
||||
if _, err := io.Copy(multiWriter, file); err != nil {
|
||||
response.Error(c, 500, "保存文件失败")
|
||||
return
|
||||
}
|
||||
fileMD5 := hex.EncodeToString(hash.Sum(nil))
|
||||
|
||||
fileURL := "/uploads/cloud-files/" + filename
|
||||
|
||||
mimeType := header.Header.Get("Content-Type")
|
||||
if mimeType == "" {
|
||||
mimeType = "application/octet-stream"
|
||||
}
|
||||
|
||||
constant := model.CloudConstant{
|
||||
UserID: userID,
|
||||
AppID: &appID,
|
||||
Key: key,
|
||||
Value: fileURL,
|
||||
VarType: "binary",
|
||||
FilePath: fileURL,
|
||||
FileSize: header.Size,
|
||||
MimeType: mimeType,
|
||||
OriginalName: header.Filename,
|
||||
FileMD5: fileMD5,
|
||||
Description: description,
|
||||
Status: status,
|
||||
}
|
||||
|
||||
if err := database.DB.Create(&constant).Error; err != nil {
|
||||
os.Remove(filePath)
|
||||
response.Error(c, 500, "创建云端常量失败")
|
||||
return
|
||||
}
|
||||
|
||||
if err := middleware.UpdateStorageUsed(userID, header.Size, "upload"); err != nil {
|
||||
fmt.Printf("更新存储使用量失败: %v\n", err)
|
||||
}
|
||||
|
||||
usage := model.StorageUsage{
|
||||
UserID: userID,
|
||||
ApplicationID: &appID,
|
||||
ResourceType: "cloud_constant",
|
||||
ResourceID: constant.ID,
|
||||
FileName: header.Filename,
|
||||
FileSize: header.Size,
|
||||
Action: "upload",
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
database.DB.Create(&usage)
|
||||
|
||||
service.LogOperation(c, "create", "cloud_constant", &constant.ID, fmt.Sprintf("上传文件常量: %s", constant.Key), nil)
|
||||
|
||||
response.Success(c, constant)
|
||||
}
|
||||
|
||||
func handleDownloadCloudConstant(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
id := c.Param("id")
|
||||
|
||||
var constant model.CloudConstant
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).First(&constant).Error; err != nil {
|
||||
response.Error(c, 404, "云端常量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
if constant.VarType != "binary" || constant.FilePath == "" {
|
||||
response.Error(c, 400, "该常量不是文件类型")
|
||||
return
|
||||
}
|
||||
|
||||
filePath := constant.FilePath
|
||||
if strings.HasPrefix(filePath, "/") {
|
||||
filePath = filePath[1:]
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
response.Error(c, 404, "文件不存在")
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Description", "File Transfer")
|
||||
c.Header("Content-Type", "application/octet-stream")
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", constant.OriginalName))
|
||||
c.Header("Content-Transfer-Encoding", "binary")
|
||||
c.Header("Expires", "0")
|
||||
c.Header("Cache-Control", "must-revalidate")
|
||||
c.Header("Pragma", "public")
|
||||
c.FileAttachment(filePath, constant.OriginalName)
|
||||
}
|
||||
|
||||
func handleGetCloudVariables(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
appID := c.Query("app_id")
|
||||
|
||||
var variables []model.CloudVariable
|
||||
query := database.DB.Where("user_id = ?", userID)
|
||||
if appID != "" {
|
||||
query = query.Where("app_id = ?", appID)
|
||||
}
|
||||
if err := query.Find(&variables).Error; err != nil {
|
||||
response.Error(c, 500, "获取云端变量失败")
|
||||
return
|
||||
}
|
||||
response.Success(c, gin.H{
|
||||
"variables": variables,
|
||||
"total": len(variables),
|
||||
})
|
||||
}
|
||||
|
||||
func handleGetCloudVariable(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
id := c.Param("id")
|
||||
|
||||
var variable model.CloudVariable
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).First(&variable).Error; err != nil {
|
||||
response.Error(c, 404, "云端变量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, variable)
|
||||
}
|
||||
|
||||
func handleCreateCloudVariable(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
|
||||
var req struct {
|
||||
AppID uint `json:"app_id"`
|
||||
Key string `json:"key"`
|
||||
DefaultValue string `json:"default_value"`
|
||||
VarType string `json:"var_type"`
|
||||
DataType string `json:"data_type"`
|
||||
MaxRecords int `json:"max_records"`
|
||||
Scope string `json:"scope"`
|
||||
WritePermission string `json:"write_permission"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Key == "" {
|
||||
response.Error(c, 400, "变量名不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Scope != "app" && req.Scope != "user" {
|
||||
req.Scope = "app"
|
||||
}
|
||||
|
||||
if req.WritePermission != "developer" && req.WritePermission != "user" && req.WritePermission != "app_user" {
|
||||
req.WritePermission = "developer"
|
||||
}
|
||||
|
||||
if req.Status != "active" && req.Status != "inactive" {
|
||||
req.Status = "active"
|
||||
}
|
||||
|
||||
if req.VarType == "" {
|
||||
req.VarType = "string"
|
||||
}
|
||||
|
||||
if req.DataType != "single" && req.DataType != "stream" {
|
||||
req.DataType = "single"
|
||||
}
|
||||
|
||||
variable := model.CloudVariable{
|
||||
UserID: userID,
|
||||
AppID: &req.AppID,
|
||||
Key: req.Key,
|
||||
DefaultValue: req.DefaultValue,
|
||||
VarType: req.VarType,
|
||||
DataType: req.DataType,
|
||||
MaxRecords: req.MaxRecords,
|
||||
Scope: req.Scope,
|
||||
WritePermission: req.WritePermission,
|
||||
Description: req.Description,
|
||||
Status: req.Status,
|
||||
}
|
||||
|
||||
if err := database.DB.Create(&variable).Error; err != nil {
|
||||
response.Error(c, 500, "创建云端变量失败")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, variable)
|
||||
}
|
||||
|
||||
func handleUpdateCloudVariable(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
|
||||
var req struct {
|
||||
Key string `json:"key"`
|
||||
DefaultValue string `json:"default_value"`
|
||||
VarType string `json:"var_type"`
|
||||
DataType string `json:"data_type"`
|
||||
MaxRecords int `json:"max_records"`
|
||||
WritePermission string `json:"write_permission"`
|
||||
Description string `json:"description"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
id := c.Param("id")
|
||||
var variable model.CloudVariable
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).First(&variable).Error; err != nil {
|
||||
response.Error(c, 404, "云端变量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
variable.Key = req.Key
|
||||
variable.DefaultValue = req.DefaultValue
|
||||
variable.VarType = req.VarType
|
||||
if req.DataType == "single" || req.DataType == "stream" {
|
||||
variable.DataType = req.DataType
|
||||
}
|
||||
variable.MaxRecords = req.MaxRecords
|
||||
if req.WritePermission == "developer" || req.WritePermission == "user" || req.WritePermission == "app_user" {
|
||||
variable.WritePermission = req.WritePermission
|
||||
}
|
||||
variable.Description = req.Description
|
||||
if req.Status == "active" || req.Status == "inactive" {
|
||||
variable.Status = req.Status
|
||||
}
|
||||
|
||||
if err := database.DB.Save(&variable).Error; err != nil {
|
||||
response.Error(c, 500, "更新云端变量失败")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, variable)
|
||||
}
|
||||
|
||||
func handleDeleteCloudVariable(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
|
||||
id := c.Param("id")
|
||||
|
||||
var variable model.CloudVariable
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).First(&variable).Error; err != nil {
|
||||
response.Error(c, 404, "云端变量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
if variable.VarType == "binary" && variable.FilePath != "" {
|
||||
if err := middleware.UpdateStorageUsed(userID, variable.FileSize, "delete"); err != nil {
|
||||
fmt.Printf("更新存储使用量失败: %v\n", err)
|
||||
}
|
||||
filePath := strings.TrimPrefix(variable.FilePath, "/")
|
||||
if _, err := os.Stat(filePath); err == nil {
|
||||
os.Remove(filePath)
|
||||
}
|
||||
}
|
||||
|
||||
if err := database.DB.Delete(&variable).Error; err != nil {
|
||||
response.Error(c, 500, "删除云端变量失败")
|
||||
return
|
||||
}
|
||||
response.Success(c, nil)
|
||||
}
|
||||
|
||||
func handleUploadCloudVariable(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
|
||||
file, header, err := c.Request.FormFile("file")
|
||||
if err != nil {
|
||||
response.Error(c, 400, "请选择要上传的文件")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
appIDStr := c.PostForm("app_id")
|
||||
key := c.PostForm("key")
|
||||
description := c.PostForm("description")
|
||||
status := c.PostForm("status")
|
||||
scope := c.PostForm("scope")
|
||||
writePermission := c.PostForm("write_permission")
|
||||
|
||||
if appIDStr == "" {
|
||||
response.Error(c, 400, "请选择应用")
|
||||
return
|
||||
}
|
||||
|
||||
if key == "" {
|
||||
response.Error(c, 400, "请输入变量名")
|
||||
return
|
||||
}
|
||||
|
||||
var appID uint
|
||||
fmt.Sscanf(appIDStr, "%d", &appID)
|
||||
|
||||
if status != "active" && status != "inactive" {
|
||||
status = "active"
|
||||
}
|
||||
|
||||
if scope != "app" && scope != "user" {
|
||||
scope = "app"
|
||||
}
|
||||
|
||||
if writePermission != "developer" && writePermission != "user" {
|
||||
writePermission = "developer"
|
||||
}
|
||||
|
||||
var user model.User
|
||||
if err := database.DB.First(&user, userID).Error; err != nil {
|
||||
response.Error(c, 500, "获取用户信息失败")
|
||||
return
|
||||
}
|
||||
|
||||
if user.CurrentPackageID != nil {
|
||||
var permission model.PackagePermission
|
||||
if err := database.DB.Where("package_id = ?", user.CurrentPackageID).First(&permission).Error; err == nil {
|
||||
maxStorageBytes := int64(permission.MaxStorage) * 1024 * 1024
|
||||
if user.StorageUsed+header.Size > maxStorageBytes {
|
||||
usedMB := float64(user.StorageUsed) / 1024 / 1024
|
||||
maxMB := float64(permission.MaxStorage)
|
||||
response.Error(c, 403, fmt.Sprintf("存储空间不足,已使用 %.2f MB / %.2f MB", usedMB, maxMB))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uploadDir := "uploads/cloud-files"
|
||||
if err := os.MkdirAll(uploadDir, 0755); err != nil {
|
||||
response.Error(c, 500, "创建上传目录失败")
|
||||
return
|
||||
}
|
||||
|
||||
ext := filepath.Ext(header.Filename)
|
||||
filename := fmt.Sprintf("%d_%d%s", userID, time.Now().UnixNano(), ext)
|
||||
filePath := filepath.Join(uploadDir, filename)
|
||||
|
||||
dst, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
response.Error(c, 500, "创建文件失败")
|
||||
return
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
hash := md5.New()
|
||||
multiWriter := io.MultiWriter(dst, hash)
|
||||
if _, err := io.Copy(multiWriter, file); err != nil {
|
||||
response.Error(c, 500, "保存文件失败")
|
||||
return
|
||||
}
|
||||
fileMD5 := hex.EncodeToString(hash.Sum(nil))
|
||||
|
||||
fileURL := "/uploads/cloud-files/" + filename
|
||||
|
||||
mimeType := header.Header.Get("Content-Type")
|
||||
if mimeType == "" {
|
||||
mimeType = "application/octet-stream"
|
||||
}
|
||||
|
||||
variable := model.CloudVariable{
|
||||
UserID: userID,
|
||||
AppID: &appID,
|
||||
Key: key,
|
||||
DefaultValue: fileURL,
|
||||
VarType: "binary",
|
||||
FilePath: fileURL,
|
||||
FileSize: header.Size,
|
||||
MimeType: mimeType,
|
||||
OriginalName: header.Filename,
|
||||
FileMD5: fileMD5,
|
||||
Scope: scope,
|
||||
WritePermission: writePermission,
|
||||
Description: description,
|
||||
Status: status,
|
||||
}
|
||||
|
||||
if err := database.DB.Create(&variable).Error; err != nil {
|
||||
os.Remove(filePath)
|
||||
response.Error(c, 500, "创建云端变量失败")
|
||||
return
|
||||
}
|
||||
|
||||
if err := middleware.UpdateStorageUsed(userID, header.Size, "upload"); err != nil {
|
||||
fmt.Printf("更新存储使用量失败: %v\n", err)
|
||||
}
|
||||
|
||||
usage := model.StorageUsage{
|
||||
UserID: userID,
|
||||
ApplicationID: &appID,
|
||||
ResourceType: "cloud_variable",
|
||||
ResourceID: variable.ID,
|
||||
FileName: header.Filename,
|
||||
FileSize: header.Size,
|
||||
Action: "upload",
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
database.DB.Create(&usage)
|
||||
|
||||
service.LogOperation(c, "create", "cloud_variable", &variable.ID, fmt.Sprintf("上传文件变量: %s", variable.Key), nil)
|
||||
|
||||
response.Success(c, variable)
|
||||
}
|
||||
|
||||
func handleDownloadCloudVariable(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
id := c.Param("id")
|
||||
|
||||
var variable model.CloudVariable
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).First(&variable).Error; err != nil {
|
||||
response.Error(c, 404, "云端变量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
if variable.VarType != "binary" || variable.FilePath == "" {
|
||||
response.Error(c, 400, "该变量不是文件类型")
|
||||
return
|
||||
}
|
||||
|
||||
filePath := variable.FilePath
|
||||
if strings.HasPrefix(filePath, "/") {
|
||||
filePath = filePath[1:]
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
response.Error(c, 404, "文件不存在")
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Description", "File Transfer")
|
||||
c.Header("Content-Type", "application/octet-stream")
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", variable.OriginalName))
|
||||
c.Header("Content-Transfer-Encoding", "binary")
|
||||
c.Header("Expires", "0")
|
||||
c.Header("Cache-Control", "must-revalidate")
|
||||
c.Header("Pragma", "public")
|
||||
c.FileAttachment(filePath, variable.OriginalName)
|
||||
}
|
||||
|
||||
func handleGetCloudVariableRecords(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
id := c.Param("id")
|
||||
|
||||
var variable model.CloudVariable
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).First(&variable).Error; err != nil {
|
||||
response.Error(c, 404, "云端变量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
if variable.DataType != "stream" {
|
||||
response.Error(c, 400, "该变量不是流水类型")
|
||||
return
|
||||
}
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 20
|
||||
}
|
||||
|
||||
userIDFilter := c.Query("user_id")
|
||||
startDate := c.Query("start_date")
|
||||
endDate := c.Query("end_date")
|
||||
|
||||
var total int64
|
||||
query := database.DB.Model(&model.CloudVariableRecord{}).Where("cloud_variable_id = ?", variable.ID)
|
||||
if userIDFilter != "" {
|
||||
query = query.Where("app_user_id = ?", userIDFilter)
|
||||
}
|
||||
if startDate != "" {
|
||||
query = query.Where("created_at >= ?", startDate+" 00:00:00")
|
||||
}
|
||||
if endDate != "" {
|
||||
query = query.Where("created_at <= ?", endDate+" 23:59:59")
|
||||
}
|
||||
query.Count(&total)
|
||||
|
||||
var records []model.CloudVariableRecord
|
||||
offset := (page - 1) * pageSize
|
||||
if err := query.Order("created_at DESC").Limit(pageSize).Offset(offset).Find(&records).Error; err != nil {
|
||||
response.Error(c, 500, "获取记录失败")
|
||||
return
|
||||
}
|
||||
|
||||
result := make([]gin.H, len(records))
|
||||
for i, r := range records {
|
||||
var data map[string]interface{}
|
||||
json.Unmarshal([]byte(r.Data), &data)
|
||||
record := gin.H{
|
||||
"id": r.ID,
|
||||
"data": data,
|
||||
"created_at": r.CreatedAt,
|
||||
}
|
||||
if r.AppUserID != nil {
|
||||
record["user_id"] = r.AppUserID
|
||||
var appUser model.AppUser
|
||||
if err := database.DB.Select("id, username").First(&appUser, *r.AppUserID).Error; err == nil {
|
||||
record["user"] = gin.H{
|
||||
"id": appUser.ID,
|
||||
"username": appUser.Username,
|
||||
}
|
||||
}
|
||||
}
|
||||
result[i] = record
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"records": result,
|
||||
"total": total,
|
||||
"page": page,
|
||||
"page_size": pageSize,
|
||||
"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
|
||||
})
|
||||
}
|
||||
|
||||
func handleDeleteCloudVariableRecords(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
id := c.Param("id")
|
||||
|
||||
var variable model.CloudVariable
|
||||
if err := database.DB.Where("id = ? AND user_id = ?", id, userID).First(&variable).Error; err != nil {
|
||||
response.Error(c, 404, "云端变量不存在")
|
||||
return
|
||||
}
|
||||
|
||||
if variable.DataType != "stream" {
|
||||
response.Error(c, 400, "该变量不是流水类型")
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
IDs []uint `json:"ids"`
|
||||
Before string `json:"before"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
if len(req.IDs) > 0 {
|
||||
if err := database.DB.Where("cloud_variable_id = ? AND id IN ?", variable.ID, req.IDs).Delete(&model.CloudVariableRecord{}).Error; err != nil {
|
||||
response.Error(c, 500, "删除记录失败")
|
||||
return
|
||||
}
|
||||
} else if req.Before != "" {
|
||||
if err := database.DB.Where("cloud_variable_id = ? AND created_at < ?", variable.ID, req.Before).Delete(&model.CloudVariableRecord{}).Error; err != nil {
|
||||
response.Error(c, 500, "删除记录失败")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
response.Error(c, 400, "请指定要删除的记录")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user