package routes import ( "log/slog" "net/http" "orbits-server/internal/server/api/assets" "orbits-server/internal/server/bootstrap" "orbits-server/internal/server/service" "path/filepath" "github.com/gin-gonic/gin" "gorm.io/gorm" ) func RegisterFileRoutes(file *gin.RouterGroup, env bootstrap.Environment, db *gorm.DB) { fileService := service.NewFileService(db, env) // prefix: file // for example: /file/ // file download route / display contents file.GET("/:filename", func(c *gin.Context) { fileParam := c.Param("filename") p := filepath.Join(env.ContentDirectory, fileParam) c.File(p) }) // upload route file.POST("/upload", func(c *gin.Context) { fh, err := c.FormFile("file") if err != nil { slog.Debug("no file or file headers provided on the request", "error", err) c.JSON(http.StatusBadRequest, assets.BasicResponse{ Msg: "a file is required", }) return } stream, err := fh.Open() if err != nil { slog.Error("failed to a reader stream") assets.InternalErrorResponse(c) return } defer stream.Close() fileRecord, err := fileService.Create(stream, fh.Filename) if err != nil { slog.Error("failed to enroll file to the database", "error", err) assets.InternalErrorResponse(c) return } // save to filesystem after everything has given a green light if err := c.SaveUploadedFile(fh, fileRecord.FilePath); err != nil { slog.Error("failed to save to disk, rolling back database", "error", err) // rollback db if the write has failed fileService.DeleteByID(fileRecord.ID) // give the response to the client assets.InternalErrorResponse(c) return } slog.Info("saved file to local filesystem and database") c.JSON(http.StatusCreated, assets.BasicResponse{ Msg: "file has succesfully been uploaded", Data: fileRecord, }) }) // delete route file.DELETE("/:filename", func(c *gin.Context) { fileParam := c.Param("filename") fileRecord, err := fileService.DeleteByName(fileParam) if err != nil { slog.Error("file not found", "error", err) c.JSON(http.StatusNotFound, assets.BasicResponse{ Msg: "file was not found", }) return } slog.Info("received a delete request for a file", "file", fileRecord, "filename", fileParam) c.JSON(http.StatusOK, assets.BasicResponse{ Msg: "file deleted succesfully", }) }) // define a route to check what is registered file.GET("/available", func(c *gin.Context) { files, err := fileService.ListFiles() if err != nil { slog.Error("failed to retrieve available files", "error", err) assets.InternalErrorResponse(c) return } c.JSON(http.StatusOK, assets.BasicResponse{ Msg: assets.OkMes, Data: files, }) }) }