Public errors now emit code, safe message, and request_id while keeping the legacy error field. Raw SQL, paths, tokens, and XSS payloads are stripped; the frontend branches on code instead of substring matching. Co-authored-by: Cursor <cursoragent@cursor.com>
88 lines
2.4 KiB
Go
88 lines
2.4 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
)
|
|
|
|
type userProfilePatch struct {
|
|
Name *string `json:"name,omitempty"`
|
|
Email *string `json:"email,omitempty"`
|
|
Locale *string `json:"locale,omitempty"`
|
|
Timezone *string `json:"timezone,omitempty"`
|
|
}
|
|
|
|
// handleMeProfile GET/PATCH /api/v1/me/profile
|
|
func (s *Server) handleMeProfile(w http.ResponseWriter, r *http.Request) {
|
|
user, ok := s.requirePrincipal(w, r)
|
|
if !ok {
|
|
return
|
|
}
|
|
switch r.Method {
|
|
case http.MethodGet:
|
|
writeJSONResponse(w, http.StatusOK, map[string]any{
|
|
"id": user.ID, "username": user.Username, "name": user.Name,
|
|
"email": user.Email, "locale": user.Locale, "timezone": user.Timezone,
|
|
"department": user.Department, "employee_id": user.EmployeeID, "position": user.Position,
|
|
})
|
|
case http.MethodPatch:
|
|
var patch userProfilePatch
|
|
if err := json.NewDecoder(r.Body).Decode(&patch); err != nil {
|
|
writeSafeError(w, r, http.StatusBadRequest, "invalid body")
|
|
return
|
|
}
|
|
updated := *user
|
|
if patch.Name != nil {
|
|
updated.Name = *patch.Name
|
|
}
|
|
if patch.Email != nil {
|
|
updated.Email = *patch.Email
|
|
}
|
|
if patch.Locale != nil {
|
|
updated.Locale = *patch.Locale
|
|
}
|
|
if patch.Timezone != nil {
|
|
updated.Timezone = *patch.Timezone
|
|
}
|
|
saved, err := s.authSvc.UpdateUserProfile(r.Context(), &updated)
|
|
if err != nil {
|
|
writeSafeError(w, r, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
writeJSONResponse(w, http.StatusOK, saved)
|
|
default:
|
|
writeSafeError(w, r, http.StatusMethodNotAllowed, "method not allowed")
|
|
}
|
|
}
|
|
|
|
// handleMePreferences GET/PUT /api/v1/me/preferences
|
|
func (s *Server) handleMePreferences(w http.ResponseWriter, r *http.Request) {
|
|
user, ok := s.requirePrincipal(w, r)
|
|
if !ok {
|
|
return
|
|
}
|
|
switch r.Method {
|
|
case http.MethodGet:
|
|
prefs, err := s.authSvc.GetUserPreferences(r.Context(), user.ID)
|
|
if err != nil {
|
|
writeSafeError(w, r, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
writeJSONResponse(w, http.StatusOK, prefs)
|
|
case http.MethodPut:
|
|
var body map[string]any
|
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
|
writeSafeError(w, r, http.StatusBadRequest, "invalid body")
|
|
return
|
|
}
|
|
prefs, err := s.authSvc.SaveUserPreferences(r.Context(), user.ID, body)
|
|
if err != nil {
|
|
writeSafeError(w, r, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
writeJSONResponse(w, http.StatusOK, prefs)
|
|
default:
|
|
writeSafeError(w, r, http.StatusMethodNotAllowed, "method not allowed")
|
|
}
|
|
}
|