ai slop ah
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package downloads
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -10,6 +9,7 @@ import (
|
||||
"github.com/example/sndit/backend/internal/galleries"
|
||||
"github.com/example/sndit/backend/internal/media"
|
||||
"github.com/example/sndit/backend/internal/storage"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@@ -25,80 +25,114 @@ func NewHandler(galleryRepository *galleries.Repository, mediaRepository *media.
|
||||
return &Handler{galleries: galleryRepository, media: mediaRepository, storage: objectStorage, auth: authService, service: service}
|
||||
}
|
||||
|
||||
func (h *Handler) RegisterRoutes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("POST /api/public/galleries/{slug}/media/{mediaId}/download", h.Download)
|
||||
mux.HandleFunc("POST /api/public/galleries/{slug}/download-all", h.DownloadAll)
|
||||
mux.HandleFunc("GET /api/public/galleries/{slug}/download-all/{jobId}", h.DownloadAllStatus)
|
||||
func (h *Handler) RegisterRoutes(router gin.IRouter) {
|
||||
router.POST("/api/public/galleries/:slug/media/:mediaId/download", h.Download)
|
||||
router.POST("/api/public/galleries/:slug/download-all", h.DownloadAll)
|
||||
router.GET("/api/public/galleries/:slug/download-all/:jobId", h.DownloadAllStatus)
|
||||
}
|
||||
|
||||
func (h *Handler) Download(w http.ResponseWriter, r *http.Request) {
|
||||
record, err := h.publicRecord(r)
|
||||
// Download godoc
|
||||
// @Summary Download one public gallery media item
|
||||
// @Tags public downloads
|
||||
// @Produce json
|
||||
// @Param slug path string true "Gallery slug"
|
||||
// @Param mediaId path string true "Media UUID"
|
||||
// @Success 200 {object} map[string]string
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/public/galleries/{slug}/media/{mediaId}/download [post]
|
||||
func (h *Handler) Download(c *gin.Context) {
|
||||
record, err := h.publicRecord(c)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusNotFound, "gallery not found")
|
||||
writeError(c, http.StatusNotFound, "gallery not found")
|
||||
return
|
||||
}
|
||||
if !record.DownloadsEnabled {
|
||||
writeError(w, http.StatusForbidden, "downloads are disabled")
|
||||
writeError(c, http.StatusForbidden, "downloads are disabled")
|
||||
return
|
||||
}
|
||||
mediaID, err := uuid.Parse(r.PathValue("mediaId"))
|
||||
mediaID, err := uuid.Parse(c.Param("mediaId"))
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadRequest, "invalid media id")
|
||||
writeError(c, http.StatusBadRequest, "invalid media id")
|
||||
return
|
||||
}
|
||||
item, err := h.media.GetByID(r.Context(), mediaID)
|
||||
item, err := h.media.GetByID(c.Request.Context(), mediaID)
|
||||
if err != nil || item.GalleryID != record.ID || item.ProcessingStatus != media.StatusReady {
|
||||
writeError(w, http.StatusNotFound, "media not found")
|
||||
writeError(c, http.StatusNotFound, "media not found")
|
||||
return
|
||||
}
|
||||
url, err := h.downloadURL(r, item)
|
||||
url, err := h.downloadURL(c, item)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "could not create download")
|
||||
writeError(c, http.StatusInternalServerError, "could not create download")
|
||||
return
|
||||
}
|
||||
visitorID := h.auth.EnsureVisitor(w, r)
|
||||
_ = h.media.RecordDownload(r.Context(), record.ID, &mediaID, visitorID)
|
||||
writeJSON(w, http.StatusOK, map[string]string{"url": url})
|
||||
visitorID := h.auth.EnsureVisitor(c)
|
||||
_ = h.media.RecordDownload(c.Request.Context(), record.ID, &mediaID, visitorID)
|
||||
writeJSON(c, http.StatusOK, map[string]string{"url": url})
|
||||
}
|
||||
|
||||
func (h *Handler) DownloadAll(w http.ResponseWriter, r *http.Request) {
|
||||
record, err := h.publicRecord(r)
|
||||
// DownloadAll godoc
|
||||
// @Summary Start a public gallery ZIP download
|
||||
// @Tags public downloads
|
||||
// @Produce json
|
||||
// @Param slug path string true "Gallery slug"
|
||||
// @Success 202 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/public/galleries/{slug}/download-all [post]
|
||||
func (h *Handler) DownloadAll(c *gin.Context) {
|
||||
record, err := h.publicRecord(c)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusNotFound, "gallery not found")
|
||||
writeError(c, http.StatusNotFound, "gallery not found")
|
||||
return
|
||||
}
|
||||
if !record.DownloadAllEnabled || !record.DownloadsEnabled {
|
||||
writeError(w, http.StatusForbidden, "gallery downloads are disabled")
|
||||
writeError(c, http.StatusForbidden, "gallery downloads are disabled")
|
||||
return
|
||||
}
|
||||
visitorID := h.auth.EnsureVisitor(w, r)
|
||||
job, err := h.service.Create(r.Context(), record.ID, visitorID)
|
||||
visitorID := h.auth.EnsureVisitor(c)
|
||||
job, err := h.service.Create(c.Request.Context(), record.ID, visitorID)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "could not start gallery download")
|
||||
writeError(c, http.StatusInternalServerError, "could not start gallery download")
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusAccepted, map[string]string{"jobId": job.ID.String(), "status": job.Status})
|
||||
writeJSON(c, http.StatusAccepted, map[string]string{"jobId": job.ID.String(), "status": job.Status})
|
||||
}
|
||||
|
||||
func (h *Handler) DownloadAllStatus(w http.ResponseWriter, r *http.Request) {
|
||||
record, err := h.publicRecord(r)
|
||||
// DownloadAllStatus godoc
|
||||
// @Summary Get public gallery ZIP download status
|
||||
// @Tags public downloads
|
||||
// @Produce json
|
||||
// @Param slug path string true "Gallery slug"
|
||||
// @Param jobId path string true "Download job UUID"
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Failure 400 {object} map[string]string
|
||||
// @Failure 403 {object} map[string]string
|
||||
// @Failure 404 {object} map[string]string
|
||||
// @Failure 500 {object} map[string]string
|
||||
// @Router /api/public/galleries/{slug}/download-all/{jobId} [get]
|
||||
func (h *Handler) DownloadAllStatus(c *gin.Context) {
|
||||
record, err := h.publicRecord(c)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusNotFound, "gallery not found")
|
||||
writeError(c, http.StatusNotFound, "gallery not found")
|
||||
return
|
||||
}
|
||||
if !record.DownloadAllEnabled || !record.DownloadsEnabled {
|
||||
writeError(w, http.StatusForbidden, "gallery downloads are disabled")
|
||||
writeError(c, http.StatusForbidden, "gallery downloads are disabled")
|
||||
return
|
||||
}
|
||||
jobID, err := uuid.Parse(r.PathValue("jobId"))
|
||||
jobID, err := uuid.Parse(c.Param("jobId"))
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadRequest, "invalid download job id")
|
||||
writeError(c, http.StatusBadRequest, "invalid download job id")
|
||||
return
|
||||
}
|
||||
visitorID := h.auth.EnsureVisitor(w, r)
|
||||
job, err := h.service.Get(r.Context(), jobID, record.ID, visitorID)
|
||||
visitorID := h.auth.EnsureVisitor(c)
|
||||
job, err := h.service.Get(c.Request.Context(), jobID, record.ID, visitorID)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusNotFound, "download job not found")
|
||||
writeError(c, http.StatusNotFound, "download job not found")
|
||||
return
|
||||
}
|
||||
response := map[string]any{"jobId": job.ID.String(), "status": job.Status}
|
||||
@@ -106,40 +140,38 @@ func (h *Handler) DownloadAllStatus(w http.ResponseWriter, r *http.Request) {
|
||||
response["error"] = job.Error
|
||||
}
|
||||
if job.Status == StatusReady {
|
||||
url, err := h.storage.CreateDownloadURL(r.Context(), job.StorageKey, time.Hour)
|
||||
url, err := h.storage.CreateDownloadURL(c.Request.Context(), job.StorageKey, time.Hour)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusInternalServerError, "could not create download URL")
|
||||
writeError(c, http.StatusInternalServerError, "could not create download URL")
|
||||
return
|
||||
}
|
||||
response["url"] = url
|
||||
}
|
||||
writeJSON(w, http.StatusOK, response)
|
||||
writeJSON(c, http.StatusOK, response)
|
||||
}
|
||||
|
||||
func (h *Handler) publicRecord(r *http.Request) (galleries.GalleryRecord, error) {
|
||||
record, err := h.galleries.GetPublicBySlug(r.Context(), strings.TrimSpace(r.PathValue("slug")))
|
||||
func (h *Handler) publicRecord(c *gin.Context) (galleries.GalleryRecord, error) {
|
||||
record, err := h.galleries.GetPublicBySlug(c.Request.Context(), strings.TrimSpace(c.Param("slug")))
|
||||
if err != nil || record.IsExpired() {
|
||||
return galleries.GalleryRecord{}, galleries.ErrNotFound
|
||||
}
|
||||
if record.PasswordHash != "" && !h.auth.HasGalleryAccess(r, record.Slug) {
|
||||
if record.PasswordHash != "" && !h.auth.HasGalleryAccess(c, record.Slug) {
|
||||
return galleries.GalleryRecord{}, galleries.ErrNotFound
|
||||
}
|
||||
return record, nil
|
||||
}
|
||||
|
||||
func (h *Handler) downloadURL(r *http.Request, item media.Record) (string, error) {
|
||||
func (h *Handler) downloadURL(c *gin.Context, item media.Record) (string, error) {
|
||||
if item.ExternalURL != "" {
|
||||
return item.ExternalURL, nil
|
||||
}
|
||||
return h.storage.CreateDownloadURL(r.Context(), item.StorageKey, time.Hour)
|
||||
return h.storage.CreateDownloadURL(c.Request.Context(), item.StorageKey, time.Hour)
|
||||
}
|
||||
|
||||
func writeError(w http.ResponseWriter, status int, message string) {
|
||||
writeJSON(w, status, map[string]string{"error": message})
|
||||
func writeError(c *gin.Context, status int, message string) {
|
||||
writeJSON(c, status, map[string]string{"error": message})
|
||||
}
|
||||
|
||||
func writeJSON(w http.ResponseWriter, status int, value any) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.WriteHeader(status)
|
||||
_ = json.NewEncoder(w).Encode(value)
|
||||
func writeJSON(c *gin.Context, status int, value any) {
|
||||
c.JSON(status, value)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user