add auth
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/prabhupadasays/spsays-bff/internal/middleware"
|
||||
"github.com/prabhupadasays/spsays-bff/internal/service"
|
||||
"github.com/prabhupadasays/spsays-bff/pkg/response"
|
||||
)
|
||||
|
||||
// UserHandler exposes profile-edit + avatar-presign endpoints.
|
||||
// All routes here sit behind middleware.RequireAuth.
|
||||
type UserHandler struct {
|
||||
svc *service.UserService
|
||||
}
|
||||
|
||||
func NewUserHandler(svc *service.UserService) *UserHandler {
|
||||
return &UserHandler{svc: svc}
|
||||
}
|
||||
|
||||
// updateProfileReq accepts partial updates. Use pointers so the JSON decoder
|
||||
// can tell "client explicitly sent null" from "field not present" — the
|
||||
// service treats nil-name as "leave alone" and ""-name as an error.
|
||||
type updateProfileReq struct {
|
||||
Name *string `json:"name"`
|
||||
AvatarURL *string `json:"avatar_url"`
|
||||
}
|
||||
|
||||
// UpdateProfile patches name and/or avatar.
|
||||
func (h *UserHandler) UpdateProfile(w http.ResponseWriter, r *http.Request) {
|
||||
uid := middleware.UserID(r.Context())
|
||||
|
||||
var req updateProfileReq
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
response.Error(w, http.StatusBadRequest, "invalid JSON body")
|
||||
return
|
||||
}
|
||||
|
||||
u, err := h.svc.UpdateProfile(r.Context(), uid, req.Name, req.AvatarURL)
|
||||
if err != nil {
|
||||
response.Error(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
response.JSON(w, http.StatusOK, u)
|
||||
}
|
||||
|
||||
type presignReq struct {
|
||||
ContentType string `json:"content_type"`
|
||||
}
|
||||
|
||||
type presignResp struct {
|
||||
UploadURL string `json:"upload_url"`
|
||||
PublicURL string `json:"public_url"`
|
||||
}
|
||||
|
||||
// AvatarPresign returns a one-shot R2 PUT URL the browser uses to upload.
|
||||
// The frontend then PATCHes /users/me with the returned public_url to
|
||||
// persist the new avatar on the user row.
|
||||
func (h *UserHandler) AvatarPresign(w http.ResponseWriter, r *http.Request) {
|
||||
uid := middleware.UserID(r.Context())
|
||||
|
||||
var req presignReq
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
response.Error(w, http.StatusBadRequest, "invalid JSON body")
|
||||
return
|
||||
}
|
||||
ct := strings.TrimSpace(req.ContentType)
|
||||
if ct == "" {
|
||||
response.Error(w, http.StatusBadRequest, "content_type is required")
|
||||
return
|
||||
}
|
||||
|
||||
upload, public, err := h.svc.AvatarPresign(r.Context(), uid, ct)
|
||||
if err != nil {
|
||||
// Differentiate "feature off" from "bad content type" so the frontend
|
||||
// can show a useful message.
|
||||
if strings.Contains(err.Error(), "not configured") {
|
||||
response.Error(w, http.StatusServiceUnavailable, err.Error())
|
||||
return
|
||||
}
|
||||
response.Error(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
response.JSON(w, http.StatusOK, presignResp{UploadURL: upload, PublicURL: public})
|
||||
}
|
||||
Reference in New Issue
Block a user