update: allow deleting form with responses, block editing form with responses
Docker Build and Push / Build and Push Docker Image (push) Successful in 17m21s
Docker Build and Push / Build and Push Docker Image (push) Successful in 17m21s
This commit is contained in:
@@ -2,7 +2,7 @@ BEGIN;
|
|||||||
|
|
||||||
CREATE TABLE form_responses (
|
CREATE TABLE form_responses (
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
form_id UUID NOT NULL REFERENCES forms(id) ON DELETE RESTRICT,
|
form_id UUID NOT NULL REFERENCES forms(id) ON DELETE CASCADE,
|
||||||
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||||
submitted_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
submitted_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
);
|
);
|
||||||
|
|||||||
+15
-15
@@ -354,7 +354,7 @@ func (h *Handler) FormGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
// FormPut updates an existing form
|
// FormPut updates an existing form
|
||||||
//
|
//
|
||||||
// @Summary Update a form
|
// @Summary Update a form
|
||||||
// @Description Replace a form's title, description, and questions. Only the form owner can update it
|
// @Description Replace a form's title, description, and questions. Only the form owner can update it. Editing is blocked if the form already has responses
|
||||||
// @Tags forms
|
// @Tags forms
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
@@ -366,6 +366,7 @@ func (h *Handler) FormGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
// @Failure 401 {string} string "Unauthorized"
|
// @Failure 401 {string} string "Unauthorized"
|
||||||
// @Failure 403 {string} string "Forbidden (not the form owner)"
|
// @Failure 403 {string} string "Forbidden (not the form owner)"
|
||||||
// @Failure 404 {string} string "Form not found"
|
// @Failure 404 {string} string "Form not found"
|
||||||
|
// @Failure 409 {string} string "Conflict (form already has responses)"
|
||||||
// @Failure 500 {string} string "Internal server error"
|
// @Failure 500 {string} string "Internal server error"
|
||||||
// @Router /api/form/{id} [put]
|
// @Router /api/form/{id} [put]
|
||||||
func (h *Handler) FormPut(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) FormPut(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -410,6 +411,18 @@ func (h *Handler) FormPut(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasResponses, err := h.repository.FormHasResponses(ctx, formID)
|
||||||
|
if err != nil {
|
||||||
|
internalServerError(w, err)
|
||||||
|
log.Printf("failed to check responses: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if hasResponses {
|
||||||
|
w.WriteHeader(http.StatusConflict)
|
||||||
|
_, _ = w.Write([]byte("form already has responses and cannot be edited"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
updated, err := h.repository.UpdateForm(ctx, repository.UpdateFormParams{
|
updated, err := h.repository.UpdateForm(ctx, repository.UpdateFormParams{
|
||||||
ID: formID,
|
ID: formID,
|
||||||
Title: req.Title,
|
Title: req.Title,
|
||||||
@@ -450,7 +463,7 @@ func (h *Handler) FormPut(w http.ResponseWriter, r *http.Request) {
|
|||||||
// FormDelete deletes a form
|
// FormDelete deletes a form
|
||||||
//
|
//
|
||||||
// @Summary Delete a form
|
// @Summary Delete a form
|
||||||
// @Description Delete a form by ID. Only the form owner can delete it. Deletion is blocked if the form already has responses
|
// @Description Delete a form by ID. Only the form owner can delete it
|
||||||
// @Tags forms
|
// @Tags forms
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security BearerAuth
|
||||||
@@ -460,7 +473,6 @@ func (h *Handler) FormPut(w http.ResponseWriter, r *http.Request) {
|
|||||||
// @Failure 401 {string} string "Unauthorized"
|
// @Failure 401 {string} string "Unauthorized"
|
||||||
// @Failure 403 {string} string "Forbidden (not the form owner)"
|
// @Failure 403 {string} string "Forbidden (not the form owner)"
|
||||||
// @Failure 404 {string} string "Form not found"
|
// @Failure 404 {string} string "Form not found"
|
||||||
// @Failure 409 {string} string "Conflict (form already has responses)"
|
|
||||||
// @Failure 500 {string} string "Internal server error"
|
// @Failure 500 {string} string "Internal server error"
|
||||||
// @Router /api/form/{id} [delete]
|
// @Router /api/form/{id} [delete]
|
||||||
func (h *Handler) FormDelete(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) FormDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -494,18 +506,6 @@ func (h *Handler) FormDelete(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hasResponses, err := h.repository.FormHasResponses(ctx, formID)
|
|
||||||
if err != nil {
|
|
||||||
internalServerError(w, err)
|
|
||||||
log.Printf("failed to check responses: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if hasResponses {
|
|
||||||
w.WriteHeader(http.StatusConflict)
|
|
||||||
_, _ = w.Write([]byte("form already has responses and cannot be deleted"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := h.repository.DeleteForm(ctx, formID); err != nil {
|
if err := h.repository.DeleteForm(ctx, formID); err != nil {
|
||||||
internalServerError(w, err)
|
internalServerError(w, err)
|
||||||
log.Printf("failed to delete form: %s", err)
|
log.Printf("failed to delete form: %s", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user