Files
warpbox-dev/backend/libs/handlers/upload.go

99 lines
2.6 KiB
Go
Raw Normal View History

package handlers
import (
"errors"
"fmt"
"mime/multipart"
"net/http"
"strconv"
"strings"
"warpbox.dev/backend/libs/helpers"
"warpbox.dev/backend/libs/jobs"
"warpbox.dev/backend/libs/services"
)
func (a *App) Upload(w http.ResponseWriter, r *http.Request) {
user, loggedIn := a.currentUser(r)
isAdminUpload := loggedIn && user.Role == services.UserRoleAdmin
if !isAdminUpload {
r.Body = http.MaxBytesReader(w, r.Body, a.uploadService.MaxUploadSize()*8)
}
parseLimit := a.uploadService.MaxUploadSize() * 8
if isAdminUpload {
parseLimit = 32 << 20
}
if err := r.ParseMultipartForm(parseLimit); err != nil {
helpers.WriteJSONError(w, http.StatusBadRequest, "upload form could not be read")
return
}
files := uploadFiles(r)
var ownerID string
var collectionID string
if loggedIn {
ownerID = user.ID
collectionID = r.FormValue("collection_id")
if !a.authService.CollectionOwnedBy(collectionID, user.ID) {
helpers.WriteJSONError(w, http.StatusForbidden, "collection not found")
return
}
}
result, err := a.uploadService.CreateBox(files, services.UploadOptions{
MaxDays: parseInt(r.FormValue("max_days")),
MaxDownloads: parseInt(r.FormValue("max_downloads")),
Password: r.FormValue("password"),
ObfuscateMetadata: r.FormValue("obfuscate_metadata") == "on",
OwnerID: ownerID,
CollectionID: collectionID,
SkipSizeLimit: isAdminUpload,
})
if err != nil {
a.logger.Warn("upload failed", "source", "user-upload", "severity", "warn", "code", 4001, "error", err.Error())
helpers.WriteJSONError(w, http.StatusBadRequest, err.Error())
return
}
jobs.GenerateThumbnailsForBoxAsync(a.uploadService, a.logger, result.BoxID)
if wantsJSON(r) {
helpers.WriteJSON(w, http.StatusCreated, result)
return
}
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusCreated)
_, _ = fmt.Fprintln(w, result.BoxURL)
}
func parseInt(value string) int {
if value == "" {
return 0
}
parsed, err := strconv.Atoi(value)
if err != nil {
return 0
}
return parsed
}
func statusForDownloadError(err error) int {
if errors.Is(err, http.ErrMissingFile) {
return http.StatusNotFound
}
return http.StatusForbidden
}
func uploadFiles(r *http.Request) []*multipart.FileHeader {
if r.MultipartForm == nil {
return nil
}
files := make([]*multipart.FileHeader, 0)
files = append(files, r.MultipartForm.File["file"]...)
files = append(files, r.MultipartForm.File["sharex"]...)
return files
}
func wantsJSON(r *http.Request) bool {
return strings.Contains(strings.ToLower(r.Header.Get("Accept")), "application/json")
}