Files
warpbox/lib/server/handlers.go

246 lines
6.0 KiB
Go
Raw Normal View History

package server
import (
"archive/zip"
"fmt"
"io"
"net/http"
"os"
"github.com/gin-gonic/gin"
"warpbox/lib/boxstore"
"warpbox/lib/helpers"
"warpbox/lib/models"
)
func handleIndex(ctx *gin.Context) {
ctx.HTML(http.StatusOK, "index.html", gin.H{})
}
func handleShowBox(ctx *gin.Context) {
boxID := ctx.Param("id")
if !boxstore.ValidBoxID(boxID) {
ctx.String(http.StatusBadRequest, "Invalid box id")
return
}
files, err := boxstore.ListFiles(boxID)
if err != nil {
ctx.String(http.StatusNotFound, "Box not found")
return
}
ctx.HTML(http.StatusOK, "box.html", gin.H{
"BoxID": boxID,
"Files": files,
"FileCount": len(files),
"DownloadAll": "/box/" + boxID + "/download",
"PollMS": helpers.EnvInt("WARPBOX_BOX_POLL_INTERVAL_MS", 5000, 1000),
})
}
func handleBoxStatus(ctx *gin.Context) {
boxID := ctx.Param("id")
if !boxstore.ValidBoxID(boxID) {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid box id"})
return
}
files, err := boxstore.ListFiles(boxID)
if err != nil {
ctx.JSON(http.StatusNotFound, gin.H{"error": "Box not found"})
return
}
ctx.JSON(http.StatusOK, gin.H{"box_id": boxID, "files": files})
}
func handleDownloadBox(ctx *gin.Context) {
boxID := ctx.Param("id")
if !boxstore.ValidBoxID(boxID) {
ctx.String(http.StatusBadRequest, "Invalid box id")
return
}
files, err := boxstore.ListFiles(boxID)
if err != nil {
ctx.String(http.StatusNotFound, "Box not found")
return
}
ctx.Header("Content-Type", "application/zip")
ctx.Header("Content-Disposition", fmt.Sprintf(`attachment; filename="warpbox-%s.zip"`, boxID))
zipWriter := zip.NewWriter(ctx.Writer)
defer zipWriter.Close()
for _, file := range files {
if !file.IsComplete {
continue
}
if err := boxstore.AddFileToZip(zipWriter, boxID, file.Name); err != nil {
ctx.Status(http.StatusInternalServerError)
return
}
}
}
func handleDownloadFile(ctx *gin.Context) {
boxID := ctx.Param("id")
filename, ok := helpers.SafeFilename(ctx.Param("filename"))
if !boxstore.ValidBoxID(boxID) || !ok {
ctx.String(http.StatusBadRequest, "Invalid file")
return
}
path, ok := boxstore.SafeBoxFilePath(boxID, filename)
if !ok {
ctx.String(http.StatusBadRequest, "Invalid file")
return
}
if _, err := os.Stat(path); err != nil {
ctx.String(http.StatusNotFound, "File not found")
return
}
ctx.FileAttachment(path, filename)
}
func handleCreateBox(ctx *gin.Context) {
boxID, err := boxstore.NewBoxID()
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Could not create upload box"})
return
}
if err := os.MkdirAll(boxstore.BoxPath(boxID), 0755); err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Could not prepare upload box"})
return
}
var request models.CreateBoxRequest
if err := ctx.ShouldBindJSON(&request); err != nil && err != io.EOF {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid box payload"})
return
}
files, err := boxstore.CreateManifest(boxID, request.Files)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"box_id": boxID, "box_url": "/box/" + boxID, "files": files})
}
func handleManifestFileUpload(ctx *gin.Context) {
boxID := ctx.Param("id")
fileID := ctx.Param("file_id")
if !boxstore.ValidBoxID(boxID) {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid box id"})
return
}
file, err := ctx.FormFile("file")
if err != nil {
boxstore.MarkFileStatus(boxID, fileID, models.FileStatusFailed)
ctx.JSON(http.StatusBadRequest, gin.H{"error": "No file received"})
return
}
savedFile, err := boxstore.SaveManifestUpload(boxID, fileID, file)
if err != nil {
boxstore.MarkFileStatus(boxID, fileID, models.FileStatusFailed)
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"box_id": boxID, "box_url": "/box/" + boxID, "file": savedFile})
}
func handleFileStatusUpdate(ctx *gin.Context) {
boxID := ctx.Param("id")
fileID := ctx.Param("file_id")
if !boxstore.ValidBoxID(boxID) {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid box id"})
return
}
var request models.UpdateFileStatusRequest
if err := ctx.ShouldBindJSON(&request); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid status payload"})
return
}
file, err := boxstore.MarkFileStatus(boxID, fileID, request.Status)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"file": file})
}
func handleDirectBoxUpload(ctx *gin.Context) {
boxID := ctx.Param("id")
if !boxstore.ValidBoxID(boxID) {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid box id"})
return
}
file, err := ctx.FormFile("file")
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "No file received"})
return
}
savedFile, err := boxstore.SaveUpload(boxID, file)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{"box_id": boxID, "box_url": "/box/" + boxID, "file": savedFile})
}
func handleLegacyUpload(ctx *gin.Context) {
form, err := ctx.MultipartForm()
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "No files received"})
return
}
files := form.File["files"]
if len(files) == 0 {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "No files received"})
return
}
boxID, err := boxstore.NewBoxID()
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Could not create upload box"})
return
}
if err := os.MkdirAll(boxstore.BoxPath(boxID), 0755); err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Could not prepare upload box"})
return
}
savedFiles := make([]models.BoxFile, 0, len(files))
for _, file := range files {
savedFile, err := boxstore.SaveUpload(boxID, file)
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
savedFiles = append(savedFiles, savedFile)
}
ctx.JSON(http.StatusOK, gin.H{"box_id": boxID, "box_url": "/box/" + boxID, "files": savedFiles})
}