ALL 0.1.0 Code
This commit is contained in:
590
server/internal/handlers/files.go
Normal file
590
server/internal/handlers/files.go
Normal file
@@ -0,0 +1,590 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/fpmb/server/internal/database"
|
||||
"github.com/fpmb/server/internal/models"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
func storageBase(ctx context.Context, projectID primitive.ObjectID) (string, error) {
|
||||
var project models.Project
|
||||
if err := database.GetCollection("projects").FindOne(ctx, bson.M{"_id": projectID}).Decode(&project); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if project.TeamID == primitive.NilObjectID {
|
||||
return filepath.Join("../data/users", project.CreatedBy.Hex()), nil
|
||||
}
|
||||
return filepath.Join("../data/teams", project.TeamID.Hex()), nil
|
||||
}
|
||||
|
||||
func ListFiles(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
projectID, err := primitive.ObjectIDFromHex(c.Params("projectId"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid project ID"})
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if _, err := getProjectRole(ctx, projectID, userID); err != nil {
|
||||
log.Printf("ListFiles getProjectRole error: %v (projectID=%s userID=%s)", err, projectID.Hex(), userID.Hex())
|
||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Access denied"})
|
||||
}
|
||||
|
||||
filter := bson.M{"project_id": projectID}
|
||||
if parentID := c.Query("parent_id"); parentID != "" {
|
||||
oid, err := primitive.ObjectIDFromHex(parentID)
|
||||
if err == nil {
|
||||
filter["parent_id"] = oid
|
||||
}
|
||||
} else {
|
||||
filter["parent_id"] = bson.M{"$exists": false}
|
||||
}
|
||||
|
||||
cursor, err := database.GetCollection("files").Find(ctx, filter,
|
||||
options.Find().SetSort(bson.D{{Key: "type", Value: -1}, {Key: "name", Value: 1}}))
|
||||
if err != nil {
|
||||
log.Printf("ListFiles Find error: %v (filter=%v)", err, filter)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to fetch files"})
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
var files []models.File
|
||||
cursor.All(ctx, &files)
|
||||
if files == nil {
|
||||
files = []models.File{}
|
||||
}
|
||||
return c.JSON(files)
|
||||
}
|
||||
|
||||
func CreateFolder(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
projectID, err := primitive.ObjectIDFromHex(c.Params("projectId"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid project ID"})
|
||||
}
|
||||
|
||||
var body struct {
|
||||
Name string `json:"name"`
|
||||
ParentID string `json:"parent_id"`
|
||||
}
|
||||
if err := c.BodyParser(&body); err != nil || body.Name == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Name is required"})
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
roleFlags, err := getProjectRole(ctx, projectID, userID)
|
||||
if err != nil || !hasPermission(roleFlags, RoleEditor) {
|
||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Insufficient permissions"})
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
file := &models.File{
|
||||
ID: primitive.NewObjectID(),
|
||||
ProjectID: projectID,
|
||||
Name: body.Name,
|
||||
Type: "folder",
|
||||
CreatedBy: userID,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if body.ParentID != "" {
|
||||
if oid, err := primitive.ObjectIDFromHex(body.ParentID); err == nil {
|
||||
file.ParentID = &oid
|
||||
}
|
||||
}
|
||||
|
||||
database.GetCollection("files").InsertOne(ctx, file)
|
||||
return c.Status(fiber.StatusCreated).JSON(file)
|
||||
}
|
||||
|
||||
func UploadFile(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
projectID, err := primitive.ObjectIDFromHex(c.Params("projectId"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid project ID"})
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
roleFlags, err := getProjectRole(ctx, projectID, userID)
|
||||
if err != nil || !hasPermission(roleFlags, RoleEditor) {
|
||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Insufficient permissions"})
|
||||
}
|
||||
|
||||
fh, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "No file provided"})
|
||||
}
|
||||
|
||||
base, err := storageBase(ctx, projectID)
|
||||
if err != nil {
|
||||
log.Printf("UploadFile storageBase error: %v (projectID=%s)", err, projectID.Hex())
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to resolve storage path"})
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(base, 0755); err != nil {
|
||||
log.Printf("UploadFile MkdirAll error: %v (base=%s)", err, base)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to create storage directory"})
|
||||
}
|
||||
|
||||
filename := fh.Filename
|
||||
ext := filepath.Ext(filename)
|
||||
stem := filename[:len(filename)-len(ext)]
|
||||
destPath := filepath.Join(base, filename)
|
||||
for n := 2; ; n++ {
|
||||
if _, statErr := os.Stat(destPath); statErr != nil {
|
||||
break
|
||||
}
|
||||
filename = fmt.Sprintf("%s (%d)%s", stem, n, ext)
|
||||
destPath = filepath.Join(base, filename)
|
||||
}
|
||||
|
||||
if err := c.SaveFile(fh, destPath); err != nil {
|
||||
log.Printf("UploadFile SaveFile error: %v (destPath=%s)", err, destPath)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to save file"})
|
||||
}
|
||||
|
||||
relPath := destPath[len("../data/"):]
|
||||
|
||||
now := time.Now()
|
||||
file := &models.File{
|
||||
ID: primitive.NewObjectID(),
|
||||
ProjectID: projectID,
|
||||
Name: fh.Filename,
|
||||
Type: "file",
|
||||
SizeBytes: fh.Size,
|
||||
StorageURL: relPath,
|
||||
CreatedBy: userID,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
parentID := c.FormValue("parent_id")
|
||||
if parentID != "" {
|
||||
if oid, err := primitive.ObjectIDFromHex(parentID); err == nil {
|
||||
file.ParentID = &oid
|
||||
}
|
||||
}
|
||||
|
||||
database.GetCollection("files").InsertOne(ctx, file)
|
||||
return c.Status(fiber.StatusCreated).JSON(file)
|
||||
}
|
||||
|
||||
func ListTeamFiles(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
teamID, err := primitive.ObjectIDFromHex(c.Params("teamId"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid team ID"})
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if _, err := getTeamRole(ctx, teamID, userID); err != nil {
|
||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Access denied"})
|
||||
}
|
||||
|
||||
filter := bson.M{"team_id": teamID}
|
||||
if parentID := c.Query("parent_id"); parentID != "" {
|
||||
oid, err := primitive.ObjectIDFromHex(parentID)
|
||||
if err == nil {
|
||||
filter["parent_id"] = oid
|
||||
}
|
||||
} else {
|
||||
filter["parent_id"] = bson.M{"$exists": false}
|
||||
}
|
||||
|
||||
cursor, err := database.GetCollection("files").Find(ctx, filter,
|
||||
options.Find().SetSort(bson.D{{Key: "type", Value: -1}, {Key: "name", Value: 1}}))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to fetch files"})
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
var files []models.File
|
||||
cursor.All(ctx, &files)
|
||||
if files == nil {
|
||||
files = []models.File{}
|
||||
}
|
||||
return c.JSON(files)
|
||||
}
|
||||
|
||||
func CreateTeamFolder(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
teamID, err := primitive.ObjectIDFromHex(c.Params("teamId"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid team ID"})
|
||||
}
|
||||
|
||||
var body struct {
|
||||
Name string `json:"name"`
|
||||
ParentID string `json:"parent_id"`
|
||||
}
|
||||
if err := c.BodyParser(&body); err != nil || body.Name == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Name is required"})
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
roleFlags, err := getTeamRole(ctx, teamID, userID)
|
||||
if err != nil || !hasPermission(roleFlags, RoleEditor) {
|
||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Insufficient permissions"})
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
file := &models.File{
|
||||
ID: primitive.NewObjectID(),
|
||||
TeamID: teamID,
|
||||
Name: body.Name,
|
||||
Type: "folder",
|
||||
CreatedBy: userID,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if body.ParentID != "" {
|
||||
if oid, err := primitive.ObjectIDFromHex(body.ParentID); err == nil {
|
||||
file.ParentID = &oid
|
||||
}
|
||||
}
|
||||
|
||||
database.GetCollection("files").InsertOne(ctx, file)
|
||||
return c.Status(fiber.StatusCreated).JSON(file)
|
||||
}
|
||||
|
||||
func UploadTeamFile(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
teamID, err := primitive.ObjectIDFromHex(c.Params("teamId"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid team ID"})
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
roleFlags, err := getTeamRole(ctx, teamID, userID)
|
||||
if err != nil || !hasPermission(roleFlags, RoleEditor) {
|
||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Insufficient permissions"})
|
||||
}
|
||||
|
||||
fh, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "No file provided"})
|
||||
}
|
||||
|
||||
base := filepath.Join("../data/teams", teamID.Hex(), "files")
|
||||
if err := os.MkdirAll(base, 0755); err != nil {
|
||||
log.Printf("UploadTeamFile MkdirAll error: %v (base=%s)", err, base)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to create storage directory"})
|
||||
}
|
||||
|
||||
filename := fh.Filename
|
||||
ext := filepath.Ext(filename)
|
||||
stem := filename[:len(filename)-len(ext)]
|
||||
destPath := filepath.Join(base, filename)
|
||||
for n := 2; ; n++ {
|
||||
if _, statErr := os.Stat(destPath); statErr != nil {
|
||||
break
|
||||
}
|
||||
filename = fmt.Sprintf("%s (%d)%s", stem, n, ext)
|
||||
destPath = filepath.Join(base, filename)
|
||||
}
|
||||
|
||||
if err := c.SaveFile(fh, destPath); err != nil {
|
||||
log.Printf("UploadTeamFile SaveFile error: %v (destPath=%s)", err, destPath)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to save file"})
|
||||
}
|
||||
|
||||
relPath := destPath[len("../data/"):]
|
||||
|
||||
now := time.Now()
|
||||
file := &models.File{
|
||||
ID: primitive.NewObjectID(),
|
||||
TeamID: teamID,
|
||||
Name: fh.Filename,
|
||||
Type: "file",
|
||||
SizeBytes: fh.Size,
|
||||
StorageURL: relPath,
|
||||
CreatedBy: userID,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
parentID := c.FormValue("parent_id")
|
||||
if parentID != "" {
|
||||
if oid, err := primitive.ObjectIDFromHex(parentID); err == nil {
|
||||
file.ParentID = &oid
|
||||
}
|
||||
}
|
||||
|
||||
database.GetCollection("files").InsertOne(ctx, file)
|
||||
return c.Status(fiber.StatusCreated).JSON(file)
|
||||
}
|
||||
|
||||
func ListUserFiles(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
filter := bson.M{"user_id": userID}
|
||||
if parentID := c.Query("parent_id"); parentID != "" {
|
||||
oid, err := primitive.ObjectIDFromHex(parentID)
|
||||
if err == nil {
|
||||
filter["parent_id"] = oid
|
||||
}
|
||||
} else {
|
||||
filter["parent_id"] = bson.M{"$exists": false}
|
||||
}
|
||||
|
||||
cursor, err := database.GetCollection("files").Find(ctx, filter,
|
||||
options.Find().SetSort(bson.D{{Key: "type", Value: -1}, {Key: "name", Value: 1}}))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to fetch files"})
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
|
||||
var files []models.File
|
||||
cursor.All(ctx, &files)
|
||||
if files == nil {
|
||||
files = []models.File{}
|
||||
}
|
||||
return c.JSON(files)
|
||||
}
|
||||
|
||||
func CreateUserFolder(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
var body struct {
|
||||
Name string `json:"name"`
|
||||
ParentID string `json:"parent_id"`
|
||||
}
|
||||
if err := c.BodyParser(&body); err != nil || body.Name == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Name is required"})
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
file := &models.File{
|
||||
ID: primitive.NewObjectID(),
|
||||
UserID: userID,
|
||||
Name: body.Name,
|
||||
Type: "folder",
|
||||
CreatedBy: userID,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if body.ParentID != "" {
|
||||
if oid, err := primitive.ObjectIDFromHex(body.ParentID); err == nil {
|
||||
file.ParentID = &oid
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
database.GetCollection("files").InsertOne(ctx, file)
|
||||
return c.Status(fiber.StatusCreated).JSON(file)
|
||||
}
|
||||
|
||||
func UploadUserFile(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
fh, err := c.FormFile("file")
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "No file provided"})
|
||||
}
|
||||
|
||||
base := filepath.Join("../data/users", userID.Hex(), "files")
|
||||
if err := os.MkdirAll(base, 0755); err != nil {
|
||||
log.Printf("UploadUserFile MkdirAll error: %v (base=%s)", err, base)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to create storage directory"})
|
||||
}
|
||||
|
||||
filename := fh.Filename
|
||||
ext := filepath.Ext(filename)
|
||||
stem := filename[:len(filename)-len(ext)]
|
||||
destPath := filepath.Join(base, filename)
|
||||
for n := 2; ; n++ {
|
||||
if _, statErr := os.Stat(destPath); statErr != nil {
|
||||
break
|
||||
}
|
||||
filename = fmt.Sprintf("%s (%d)%s", stem, n, ext)
|
||||
destPath = filepath.Join(base, filename)
|
||||
}
|
||||
|
||||
if err := c.SaveFile(fh, destPath); err != nil {
|
||||
log.Printf("UploadUserFile SaveFile error: %v (destPath=%s)", err, destPath)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to save file"})
|
||||
}
|
||||
|
||||
relPath := destPath[len("../data/"):]
|
||||
|
||||
now := time.Now()
|
||||
file := &models.File{
|
||||
ID: primitive.NewObjectID(),
|
||||
UserID: userID,
|
||||
Name: fh.Filename,
|
||||
Type: "file",
|
||||
SizeBytes: fh.Size,
|
||||
StorageURL: relPath,
|
||||
CreatedBy: userID,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
parentID := c.FormValue("parent_id")
|
||||
if parentID != "" {
|
||||
if oid, err := primitive.ObjectIDFromHex(parentID); err == nil {
|
||||
file.ParentID = &oid
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
database.GetCollection("files").InsertOne(ctx, file)
|
||||
return c.Status(fiber.StatusCreated).JSON(file)
|
||||
}
|
||||
|
||||
func DownloadFile(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
fileID, err := primitive.ObjectIDFromHex(c.Params("fileId"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid file ID"})
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var file models.File
|
||||
if err := database.GetCollection("files").FindOne(ctx, bson.M{"_id": fileID}).Decode(&file); err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "File not found"})
|
||||
}
|
||||
|
||||
if file.TeamID != primitive.NilObjectID {
|
||||
if _, err := getTeamRole(ctx, file.TeamID, userID); err != nil {
|
||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Access denied"})
|
||||
}
|
||||
} else if file.UserID != primitive.NilObjectID {
|
||||
if file.UserID != userID {
|
||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Access denied"})
|
||||
}
|
||||
} else {
|
||||
if _, err := getProjectRole(ctx, file.ProjectID, userID); err != nil {
|
||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Access denied"})
|
||||
}
|
||||
}
|
||||
|
||||
if file.Type == "folder" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Cannot download a folder"})
|
||||
}
|
||||
|
||||
diskPath := filepath.Join("../data", file.StorageURL)
|
||||
if _, err := os.Stat(diskPath); err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "File not found on disk"})
|
||||
}
|
||||
|
||||
c.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, file.Name))
|
||||
return c.SendFile(diskPath)
|
||||
}
|
||||
|
||||
func DeleteFile(c *fiber.Ctx) error {
|
||||
userID, err := primitive.ObjectIDFromHex(c.Locals("user_id").(string))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid user"})
|
||||
}
|
||||
|
||||
fileID, err := primitive.ObjectIDFromHex(c.Params("fileId"))
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid file ID"})
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var file models.File
|
||||
if err := database.GetCollection("files").FindOne(ctx, bson.M{"_id": fileID}).Decode(&file); err != nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "File not found"})
|
||||
}
|
||||
|
||||
var roleFlags int
|
||||
if file.TeamID != primitive.NilObjectID {
|
||||
roleFlags, err = getTeamRole(ctx, file.TeamID, userID)
|
||||
} else if file.UserID != primitive.NilObjectID {
|
||||
if file.UserID == userID {
|
||||
roleFlags = RoleOwner
|
||||
} else {
|
||||
err = fmt.Errorf("access denied")
|
||||
}
|
||||
} else {
|
||||
roleFlags, err = getProjectRole(ctx, file.ProjectID, userID)
|
||||
}
|
||||
if err != nil || !hasPermission(roleFlags, RoleEditor) {
|
||||
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Insufficient permissions"})
|
||||
}
|
||||
|
||||
database.GetCollection("files").DeleteOne(ctx, bson.M{"_id": fileID})
|
||||
|
||||
if file.Type == "folder" {
|
||||
database.GetCollection("files").DeleteMany(ctx, bson.M{"parent_id": fileID})
|
||||
} else if file.StorageURL != "" {
|
||||
os.Remove(filepath.Join("../data", file.StorageURL))
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{"message": "Deleted"})
|
||||
}
|
||||
Reference in New Issue
Block a user