71 lines
2.1 KiB
Go
71 lines
2.1 KiB
Go
package handler
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/prabhupadasays/spsays-bff/internal/middleware"
|
|
"github.com/prabhupadasays/spsays-bff/internal/service"
|
|
"github.com/prabhupadasays/spsays-bff/pkg/response"
|
|
"github.com/prabhupadasays/spsays-bff/pkg/validator"
|
|
)
|
|
|
|
// FeedbackHandler exposes POST /api/v1/feedback. The router wraps it
|
|
// with OptionalAuth so a session cookie populates user_id when one is
|
|
// present, and anonymous callers are still accepted (they have to
|
|
// supply contact_email instead).
|
|
type FeedbackHandler struct{ svc *service.FeedbackService }
|
|
|
|
func NewFeedbackHandler(svc *service.FeedbackService) *FeedbackHandler {
|
|
return &FeedbackHandler{svc: svc}
|
|
}
|
|
|
|
type submitFeedbackReq struct {
|
|
Category string `json:"category"`
|
|
Message string `json:"message"`
|
|
ContactEmail *string `json:"contact_email,omitempty"`
|
|
}
|
|
|
|
func (h *FeedbackHandler) Submit(w http.ResponseWriter, r *http.Request) {
|
|
var req submitFeedbackReq
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
response.Error(w, http.StatusBadRequest, "invalid JSON body")
|
|
return
|
|
}
|
|
|
|
v := validator.New()
|
|
validator.Required(v, "category", req.Category)
|
|
validator.Required(v, "message", req.Message)
|
|
validator.MaxLength(v, "message", req.Message, 5000)
|
|
if !v.Valid() {
|
|
response.Error(w, http.StatusBadRequest, v.Error())
|
|
return
|
|
}
|
|
|
|
// OptionalAuth seeds user_id when a valid session cookie was
|
|
// present; "" means anonymous.
|
|
uid := middleware.UserID(r.Context())
|
|
var userIDPtr *string
|
|
if uid != "" {
|
|
userIDPtr = &uid
|
|
}
|
|
|
|
// Soft-validate the contact email for the anonymous path. Authed
|
|
// callers' contact_email is ignored downstream, so skip the check.
|
|
if userIDPtr == nil && req.ContactEmail != nil && *req.ContactEmail != "" {
|
|
ev := validator.New()
|
|
validator.Email(ev, "contact_email", *req.ContactEmail)
|
|
if !ev.Valid() {
|
|
response.Error(w, http.StatusBadRequest, ev.Error())
|
|
return
|
|
}
|
|
}
|
|
|
|
f, err := h.svc.Submit(r.Context(), userIDPtr, req.Category, req.Message, req.ContactEmail)
|
|
if err != nil {
|
|
response.Error(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
response.JSON(w, http.StatusCreated, f)
|
|
}
|