141 lines
4.8 KiB
Go

package files
import (
"context"
"donat-widget/internal/model"
"github.com/labstack/echo/v4"
"log/slog"
"net/http"
)
// AddNewFile godoc
// @Summary Add new File
// @Description Add new File. The entity type defaults to 'widget' if not specified.
// @Tags Files
// @Accept multipart/form-data
// @Produce json
// @Security BearerAuth
// @Param new_file formData file true "New file to upload"
// @Param entity formData string false "Optional entity type (defaults to 'widget')"
// @Success 200 {object} model.DataFile "File has been uploaded successfully!"
// @Failure 400 {object} echo.HTTPError "Bad request (e.g., missing file, invalid form data)"
// @Failure 401 {object} echo.HTTPError "Unauthorized or expired token"
// @Failure 422 {object} echo.HTTPError "Validation error (specific cases, might overlap with 400/500)"
// @Failure 500 {object} echo.HTTPError "Internal server error (e.g., failed to save file, DB error)"
// @Router /files [post]
func AddNewFile(fileService model.FileService) echo.HandlerFunc {
return func(request echo.Context) error {
ctx := context.Background()
authData, err := fileService.CheckToken(request)
if err != nil {
slog.Error("Authentication failed", "error", err)
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized: "+err.Error())
}
entity := request.FormValue("entity")
if entity == "" {
entity = "widget"
slog.Info("Entity parameter not provided, defaulting to 'widget'")
}
newFile, err := request.FormFile("new_file")
if err != nil {
if err == http.ErrMissingFile {
slog.Error("Missing 'new_file' in form data", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "Required form field 'new_file' is missing")
}
slog.Error("Failed to get file from form", "error", err)
return echo.NewHTTPError(http.StatusBadRequest, "Cannot process uploaded file: "+err.Error())
}
fileId, err := fileService.AddNewFile(
ctx,
*newFile,
authData.AccountID,
entity,
)
if err != nil {
slog.Error("Failed to add new file via service", "entity", entity, "accountID", authData.AccountID, "error", err)
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to save file: "+err.Error())
}
slog.Info("File added successfully", "fileId", fileId, "entity", entity, "accountID", authData.AccountID)
fileResponse, err := fileService.GetFileInfo(ctx, fileId)
if err != nil {
slog.Error("Failed to get file info after adding", "fileId", fileId, "error", err)
return echo.NewHTTPError(http.StatusInternalServerError, "File saved, but failed to retrieve info: "+err.Error())
}
return request.JSON(http.StatusOK, fileResponse)
}
}
// GetFile godoc
// @Summary Get a file
// @Description Retrieve a file by its ID
// @Tags Files
// @Accept json
// @Produce octet-stream
// @Param file_id path string true "File ID" format:"uuid"
// @Success 200 {file} binary "File content"
// @Failure 400 {object} echo.HTTPError "Bad request"
// @Failure 401 {object} echo.HTTPError "Unauthorized or expired token"
// @Failure 404 {object} echo.HTTPError "File not found"
// @Router /files/{file_id} [get]
func GetFile(fileService model.FileService) echo.HandlerFunc {
return func(request echo.Context) error {
ctx := context.Background()
fileID := request.Param("file_id")
file, fileType, err := fileService.GetByID(ctx, fileID)
if err != nil {
slog.Error(err.Error())
return echo.NewHTTPError(http.StatusNotFound, "File not found")
}
return request.Blob(http.StatusOK, fileType, file)
}
}
// GetWidgetFiles godoc
// @Summary Get all widget files
// @Description Retrieve all widget files, filtered by type if specified
// @Tags Files
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param type query string false "File type (audio or image)" Enums(audio, image)
// @Success 200 {array} model.DataFile "List of files"
// @Failure 400 {object} echo.HTTPError "Bad request"
// @Failure 401 {object} echo.HTTPError "Unauthorized or expired token"
// @Router /files/widgets [get]
func GetWidgetFiles(fileService model.FileService) echo.HandlerFunc {
return func(request echo.Context) error {
ctx := context.Background()
fileType := request.QueryParam("type")
if fileType != "" && fileType != "audio" && fileType != "image" {
return echo.NewHTTPError(http.StatusUnprocessableEntity, "Invalid file type")
}
authData, err := fileService.CheckToken(request)
if err != nil {
slog.Error(err.Error())
return echo.NewHTTPError(http.StatusUnauthorized, err.Error())
}
widgetFiles, err := fileService.WidgetsFiles(
ctx,
fileType,
authData.AccountID,
)
if err != nil {
slog.Error(err.Error())
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to retrieve files")
}
return request.JSON(http.StatusOK, widgetFiles)
}
}