Files
spsays-bff/internal/handler/feedback.go
T
2026-05-31 14:54:15 +05:30

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)
}