diff --git a/backend/images/handler.go b/backend/images/handler.go index 35fa794..4815806 100644 --- a/backend/images/handler.go +++ b/backend/images/handler.go @@ -16,6 +16,7 @@ import ( "github.com/charmbracelet/log" "github.com/go-chi/chi/v5" + "github.com/google/uuid" ) type ImageHandler struct { @@ -143,6 +144,37 @@ func (h *ImageHandler) uploadImage(w http.ResponseWriter, r *http.Request) { middleware.WriteJsonOrError(h.logger, userImage, w) } +func (h *ImageHandler) deleteImage(w http.ResponseWriter, r *http.Request) { + stringImageID := chi.URLParam(r, "name") + imageID, err := uuid.Parse(stringImageID) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + ctx := r.Context() + + userID, err := middleware.GetUserID(ctx, h.logger, w) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + isAuthorized := h.imageModel.IsUserAuthorized(ctx, imageID, userID) + if !isAuthorized { + w.WriteHeader(http.StatusUnauthorized) + return + } + + err = h.imageModel.Delete(ctx, imageID) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + w.WriteHeader(http.StatusOK) +} + func (h *ImageHandler) CreateRoutes(r chi.Router) { h.logger.Info("Mounting image router") diff --git a/backend/models/image.go b/backend/models/image.go index 460fa55..987f6f6 100644 --- a/backend/models/image.go +++ b/backend/models/image.go @@ -208,6 +208,15 @@ func (m ImageModel) AddDescription(ctx context.Context, imageId uuid.UUID, descr return err } +func (m ImageModel) Delete(ctx context.Context, imageID uuid.UUID) error { + deleteImageStmt := Image.DELETE(). + WHERE(Image.ID.EQ(UUID(imageID))) + + _, err := deleteImageStmt.ExecContext(ctx, m.dbPool) + + return err +} + func (m ImageModel) IsUserAuthorized(ctx context.Context, imageId uuid.UUID, userId uuid.UUID) bool { getImageUserId := UserImages.SELECT(UserImages.UserID).WHERE(UserImages.ImageID.EQ(UUID(imageId))) diff --git a/frontend/src/network/index.ts b/frontend/src/network/index.ts index da5969c..8672f00 100644 --- a/frontend/src/network/index.ts +++ b/frontend/src/network/index.ts @@ -18,7 +18,7 @@ import { type BaseRequestParams = Partial<{ path: string; body: RequestInit["body"]; - method: "GET" | "POST"; + method: "GET" | "POST" | "DELETE"; }>; // export const base = "https://haystack.johncosta.tech"; @@ -68,6 +68,17 @@ export const sendImageFile = async ( return parse(sendImageResponseValidator, res); }; +export const deleteImage = async ( + imageID: string +): Promise => { + const request = getBaseAuthorizedRequest({ + path: `images/${imageID}`, + method: "DELETE", + }); + + await fetch(request); +} + export class ImageLimitReached extends Error { constructor() { super();