backend/internal/api/routes/files.go

209 lines
5.4 KiB
Go

package routes
import (
"os"
"path/filepath"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
"stereo.cat/backend/internal/auth"
"stereo.cat/backend/internal/types"
)
func RegisterFileRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) {
api.POST("/upload", auth.JwtMiddleware(cfg.JWTSecret), func(c *gin.Context) {
claims := c.MustGet("claims").(jwt.MapClaims)
user := claims["user"].(auth.User)
uid := user.ID
if uid == "" {
c.JSON(401, gin.H{"error": "unauthorized"})
return
}
file, err := c.FormFile("file")
if err != nil {
c.JSON(400, gin.H{"error": "file is required"})
return
}
filePath := filepath.Join(cfg.ImagePath, uid, file.Filename)
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
c.JSON(500, gin.H{"error": "failed to create directory"})
return
}
if err := c.SaveUploadedFile(file, filePath); err != nil {
c.JSON(500, gin.H{"error": "failed to save file"})
return
}
if file.Size <= 0 {
c.JSON(400, gin.H{"error": "file size must be greater than zero"})
return
}
fileMeta := types.File{
Name: file.Filename,
Owner: uid,
CreatedAt: time.Now(),
Size: file.Size,
}
if err := cfg.Database.Create(&fileMeta).Error; err != nil {
c.JSON(500, gin.H{"error": "failed to save file metadata"})
return
}
c.JSON(200, gin.H{"message": "file uploaded successfully", "name": fileMeta.Name})
})
// api.DELETE("/delete", auth.JwtMiddleware(cfg.JWTSecret), func(c *gin.Context) {
// claims := c.MustGet("claims").(jwt.MapClaims)
// user := claims["user"].(auth.User)
// uid := user.ID
// if uid == "" {
// c.JSON(401, gin.H{"error": "unauthorized"})
// return
// }
// var response struct {
// Name string `json:"name" binding:"required"`
// ID string `json:"id" binding:"required"`
// }
// if err := c.ShouldBindJSON(&response); err != nil {
// c.JSON(400, gin.H{"error": "name is required"})
// return
// }
// name := response.Name
// if name == "" {
// c.JSON(400, gin.H{"error": "name cannot be empty"})
// return
// }
// resID := response.ID
// if resID == "" {
// c.JSON(400, gin.H{"error": "id cannot be empty"})
// return
// }
// if resID != uid {
// c.JSON(403, gin.H{"error": "you can only delete your own files"})
// return
// }
// filePath := filepath.Join(cfg.ImagePath, uid, name)
// if err := os.Remove(filePath); err != nil {
// c.JSON(500, gin.H{"error": "failed to delete file"})
// return
// }
// if err := cfg.Database.Where("name = ?", name).Where("owner = ?", uid).Delete(&types.File{}).Error; err != nil {
// c.JSON(500, gin.H{"error": "failed to delete file metadata"})
// return
// }
// c.JSON(200, gin.H{"message": "file deleted successfully"})
// })
api.DELETE("/:uid/:name", auth.JwtMiddleware(cfg.JWTSecret), func(c *gin.Context) {
claims := c.MustGet("claims").(jwt.MapClaims)
user := claims["user"].(auth.User)
uid := c.Param("uid")
uid = strings.TrimSpace(uid)
if uid == "" {
c.JSON(400, gin.H{"error": "uid is required"})
return
}
if uid != user.ID {
c.JSON(403, gin.H{"error": "you can only delete your own files"})
return
}
filename := c.Param("name")
filename = strings.TrimSpace(filename)
if filename == "" {
c.JSON(400, gin.H{"error": "filename is required"})
return
}
path := filepath.Join(cfg.ImagePath, uid, filename)
if _, err := os.Stat(path); os.IsNotExist(err) {
c.JSON(404, gin.H{"error": "file not found"})
return
}
if err := os.Remove(path); err != nil {
c.JSON(500, gin.H{"error": "failed to delete file"})
return
}
if err := cfg.Database.Where("owner = ? AND name = ?", uid, filename).Delete(&types.File{}).Error; err != nil {
c.JSON(500, gin.H{"error": "failed to delete file metadata"})
return
}
c.JSON(200, gin.H{"message": "file deleted successfully"})
})
api.GET("/:uid/:name", func(c *gin.Context) {
uid := c.Param("uid")
uid = strings.TrimSpace(uid)
if uid == "" {
c.JSON(400, gin.H{"error": "uid is required"})
return
}
filename := c.Param("name")
filename = strings.TrimSpace(filename)
safe := ""
for _, r := range filename {
if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') ||
(r >= '0' && r <= '9') || r == '_' || r == '.' || r == '-' {
safe += string(r)
} else {
safe += "_"
}
}
filename = safe
// parts := strings.SplitN(name, "_", 2)
// if len(parts) != 2 {
// c.JSON(400, gin.H{"error": "invalid file name"})
// return
// }
// uid, filename := parts[0], parts[1]
// if uid == "" || filename == "" {
// c.JSON(400, gin.H{"error": "invalid file name"})
// return
// }
path := filepath.Join(cfg.ImagePath, uid, filename)
if _, err := os.Stat(path); err != nil {
c.JSON(404, gin.H{"error": "file not found"})
return
}
c.File(path)
})
api.GET("/list", auth.JwtMiddleware(cfg.JWTSecret), func(c *gin.Context) {
claims := c.MustGet("claims").(jwt.MapClaims)
user := claims["user"].(auth.User)
var files []types.File
if err := cfg.Database.Where("owner = ?", user.ID).Find(&files).Error; err != nil {
c.JSON(500, gin.H{"error": "failed to retrieve files"})
return
}
c.JSON(200, files)
})
}