Update updates a user.
(w http.ResponseWriter, r *http.Request)
| 268 | |
| 269 | // Update updates a user. |
| 270 | func (h *UsersHandler) Update(w http.ResponseWriter, r *http.Request) { |
| 271 | userID := chi.URLParam(r, "userId") |
| 272 | if userID == "" { |
| 273 | Error(w, http.StatusBadRequest, "User ID required") |
| 274 | return |
| 275 | } |
| 276 | |
| 277 | existing, err := h.users.GetByID(r.Context(), userID) |
| 278 | if err != nil || existing == nil { |
| 279 | Error(w, http.StatusNotFound, "User not found") |
| 280 | return |
| 281 | } |
| 282 | |
| 283 | var req struct { |
| 284 | Username *string `json:"username"` |
| 285 | Email *string `json:"email"` |
| 286 | FirstName *string `json:"first_name"` |
| 287 | LastName *string `json:"last_name"` |
| 288 | Role *string `json:"role"` |
| 289 | IsActive *bool `json:"is_active"` |
| 290 | } |
| 291 | if err := decodeJSON(r, &req); err != nil { |
| 292 | Error(w, http.StatusBadRequest, "Invalid request body") |
| 293 | return |
| 294 | } |
| 295 | |
| 296 | // Prevent modifying users with a higher-privilege role than the caller. |
| 297 | callerRole, _ := r.Context().Value(middleware.UserRoleKey).(string) |
| 298 | if roleRank(existing.Role) > roleRank(callerRole) { |
| 299 | Error(w, http.StatusForbidden, "Cannot modify a user with a higher-privilege role") |
| 300 | return |
| 301 | } |
| 302 | if existing.Role == "superadmin" && callerRole != "superadmin" { |
| 303 | perm, permErr := h.permissions.GetByRole(r.Context(), callerRole) |
| 304 | if permErr != nil || perm == nil || !perm.CanManageSuperusers { |
| 305 | Error(w, http.StatusForbidden, "You do not have permission to modify superadmin users") |
| 306 | return |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | // Build update |
| 311 | u := *existing |
| 312 | if req.Username != nil { |
| 313 | u.Username = *req.Username |
| 314 | } |
| 315 | if req.Email != nil { |
| 316 | u.Email = *req.Email |
| 317 | } |
| 318 | if req.FirstName != nil { |
| 319 | u.FirstName = req.FirstName |
| 320 | } |
| 321 | if req.LastName != nil { |
| 322 | u.LastName = req.LastName |
| 323 | } |
| 324 | if req.Role != nil { |
| 325 | // Enforce role escalation protection. |
| 326 | if !h.canAssignRole(r, callerRole, *req.Role) { |
| 327 | Error(w, http.StatusForbidden, "You do not have permission to assign the role: "+*req.Role) |
no test coverage detected