2025-08-04 17:45:44 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
2025-08-22 10:11:07 +02:00
|
|
|
"backend/queries"
|
2025-08-04 17:45:44 +02:00
|
|
|
"fmt"
|
|
|
|
|
"log"
|
|
|
|
|
"mime/multipart"
|
|
|
|
|
"net/http"
|
|
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
|
|
|
|
"slices"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/labstack/echo/v4"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Upload saves a file to the storage directory.
|
|
|
|
|
func Upload(file *multipart.FileHeader, from_admin bool) (string, error) {
|
|
|
|
|
log.Printf("Uploading file: %s", file.Filename)
|
2025-08-22 10:11:07 +02:00
|
|
|
|
|
|
|
|
newId, err := queries.StorageNewId()
|
2025-08-04 17:45:44 +02:00
|
|
|
if err != nil {
|
2025-08-22 10:11:07 +02:00
|
|
|
return "", err
|
2025-08-04 17:45:44 +02:00
|
|
|
}
|
2025-08-22 10:11:07 +02:00
|
|
|
|
2025-08-04 17:45:44 +02:00
|
|
|
err = Storage.Add(file, newId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
//if !from_admin , expires in 60 days
|
|
|
|
|
var expiresAt *time.Time
|
|
|
|
|
if !from_admin {
|
|
|
|
|
exp := time.Now().AddDate(0, 2, 0) // 60 days
|
|
|
|
|
expiresAt = &exp
|
|
|
|
|
} else {
|
|
|
|
|
expiresAt = nil
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-22 10:11:07 +02:00
|
|
|
err = queries.StorageUpdate(newId, file.Filename, filepath.Ext(file.Filename), from_admin, expiresAt)
|
2025-08-04 17:45:44 +02:00
|
|
|
if err != nil {
|
2025-08-22 10:11:07 +02:00
|
|
|
return "", err
|
2025-08-04 17:45:44 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-22 10:11:07 +02:00
|
|
|
err = queries.StorageDeleteUnused()
|
2025-08-04 17:45:44 +02:00
|
|
|
if err != nil {
|
2025-08-22 10:11:07 +02:00
|
|
|
return "", err
|
2025-08-04 17:45:44 +02:00
|
|
|
}
|
|
|
|
|
return newId, nil
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func StorageAuth(c echo.Context) error {
|
|
|
|
|
token := c.Request().URL.Query().Get("token")
|
|
|
|
|
if len(token) < 1 {
|
|
|
|
|
return c.String(http.StatusUnauthorized, "Unauthorized")
|
|
|
|
|
}
|
2025-08-22 10:11:07 +02:00
|
|
|
err := queries.StorageCheckToken(token)
|
2025-08-04 17:45:44 +02:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-22 10:11:07 +02:00
|
|
|
err = queries.StorageCleanExpiredTokens(token)
|
2025-08-04 17:45:44 +02:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func RemoveFromDb(ref string) error {
|
|
|
|
|
|
2025-08-22 10:11:07 +02:00
|
|
|
return queries.StorageDelete(ref)
|
2025-08-04 17:45:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func RemoveExpired() error {
|
|
|
|
|
//get all expired files
|
2025-08-22 10:11:07 +02:00
|
|
|
items_db, err := queries.StorageGetExpiredFiles()
|
2025-08-04 17:45:44 +02:00
|
|
|
if err != nil {
|
2025-08-22 10:11:07 +02:00
|
|
|
return err
|
2025-08-04 17:45:44 +02:00
|
|
|
}
|
2025-08-22 10:11:07 +02:00
|
|
|
|
2025-08-04 17:45:44 +02:00
|
|
|
for _, item := range items_db {
|
|
|
|
|
formattedName := item.Id + item.Ext
|
|
|
|
|
err = Storage.Delete(formattedName)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("failed to delete file %s: %w", formattedName, err)
|
|
|
|
|
}
|
2025-08-22 10:11:07 +02:00
|
|
|
err = queries.StorageDelete(item.Id)
|
2025-08-04 17:45:44 +02:00
|
|
|
if err != nil {
|
2025-08-22 10:11:07 +02:00
|
|
|
return err
|
2025-08-04 17:45:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func CheckConcruency() error {
|
2025-08-22 10:11:07 +02:00
|
|
|
items_db, err := queries.StorageGet_min()
|
2025-08-04 17:45:44 +02:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
files, err := Storage.List()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if len(items_db) != len(files) {
|
|
|
|
|
var founds []string
|
|
|
|
|
for _, item := range items_db {
|
|
|
|
|
formattedName := item.Id + item.Ext
|
|
|
|
|
found := slices.Contains(files, formattedName)
|
|
|
|
|
if found {
|
|
|
|
|
founds = append(founds, formattedName)
|
|
|
|
|
} else {
|
2025-08-22 10:11:07 +02:00
|
|
|
err := queries.StorageDelete(item.Id)
|
2025-08-04 17:45:44 +02:00
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for _, file := range files {
|
|
|
|
|
found := slices.Contains(founds, file)
|
|
|
|
|
if !found {
|
|
|
|
|
fmt.Printf("File %v not found in db\n", file)
|
|
|
|
|
//TODO decidere se eliminarlo
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TempFolderCleaner() error {
|
|
|
|
|
files, err := os.ReadDir(filepath.Join(storagepath, "/tmp/"))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
fmt.Println("Temp files: ", len(files))
|
|
|
|
|
if len(files) >= tempStorageLimit {
|
|
|
|
|
|
|
|
|
|
var oldest_Time time.Time
|
|
|
|
|
var oldest_File string
|
|
|
|
|
for _, file := range files {
|
|
|
|
|
file_infos, err := file.Info()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if oldest_Time.IsZero() || file_infos.ModTime().Before(oldest_Time) {
|
|
|
|
|
oldest_Time = file_infos.ModTime()
|
|
|
|
|
oldest_File = file.Name()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
err = os.Remove(filepath.Join(storagepath, "/tmp/", oldest_File))
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ROUTES
|
|
|
|
|
func StorageRoutes(e *echo.Echo) {
|
|
|
|
|
|
|
|
|
|
e.GET("/storage/list", func(c echo.Context) error {
|
|
|
|
|
filenames, err := Storage.List()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return c.String(http.StatusInternalServerError, err.Error())
|
|
|
|
|
}
|
|
|
|
|
return c.JSON(http.StatusOK, filenames)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
e.GET("/storage/get/:filename", func(c echo.Context) error {
|
|
|
|
|
err := TempFolderCleaner()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return c.String(http.StatusInternalServerError, "Failed to clean temp folder: "+err.Error())
|
|
|
|
|
}
|
|
|
|
|
err = StorageAuth(c)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return c.JSON(http.StatusUnauthorized, "Unauthorized: "+err.Error())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filename := c.Param("filename")
|
|
|
|
|
path, err := Storage.Get(filename)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return c.String(http.StatusInternalServerError, "Failed to get file: "+err.Error())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return c.File(path)
|
|
|
|
|
})
|
|
|
|
|
e.POST("/storage/upload", func(c echo.Context) error {
|
|
|
|
|
fmt.Println("Uploading file")
|
|
|
|
|
|
|
|
|
|
err := StorageAuth(c)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return c.String(http.StatusInternalServerError, "Failed to verify Auth: "+err.Error())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
from_admin := c.QueryParam("from_admin") == "true"
|
|
|
|
|
file, err := c.FormFile("file")
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fileId, err := Upload(file, from_admin)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return c.String(http.StatusInternalServerError, "Failed to upload file: "+err.Error())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return c.String(http.StatusOK, fileId)
|
|
|
|
|
})
|
|
|
|
|
e.DELETE("/storage/delete/:filename", func(c echo.Context) error {
|
|
|
|
|
err := StorageAuth(c)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return c.String(http.StatusInternalServerError, "Failed to verify Auth: "+err.Error())
|
|
|
|
|
}
|
|
|
|
|
filename := c.Param("filename")
|
|
|
|
|
|
|
|
|
|
err = Storage.Delete(filename)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return c.String(http.StatusInternalServerError, "Failed to remove file / file not found: "+err.Error())
|
|
|
|
|
}
|
|
|
|
|
return c.String(http.StatusOK, "File removed")
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
e.GET("/storage/remove-expired", func(c echo.Context) error {
|
|
|
|
|
|
|
|
|
|
err := RemoveExpired()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return c.String(http.StatusInternalServerError, "Failed to remove files / files not found: "+err.Error())
|
|
|
|
|
}
|
|
|
|
|
return c.String(http.StatusOK, "File removed")
|
|
|
|
|
|
|
|
|
|
})
|
|
|
|
|
e.GET("/storage/test", func(c echo.Context) error {
|
|
|
|
|
err := CheckConcruency()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return c.String(http.StatusInternalServerError, "Failed to check concruency: "+err.Error())
|
|
|
|
|
}
|
|
|
|
|
return c.String(http.StatusOK, "OK")
|
|
|
|
|
})
|
|
|
|
|
}
|