MCPcopy
hub / github.com/PatchMon/PatchMon / ResetPassword

Method ResetPassword

server-source-code/internal/handler/users.go:467–537  ·  view source on GitHub ↗

ResetPassword resets a user's password.

(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

465
466// ResetPassword resets a user's password.
467func (h *UsersHandler) ResetPassword(w http.ResponseWriter, r *http.Request) {
468 userID := chi.URLParam(r, "userId")
469 var req struct {
470 NewPassword string `json:"newPassword"`
471 }
472 if err := decodeJSON(r, &req); err != nil {
473 Error(w, http.StatusBadRequest, "Invalid request body")
474 return
475 }
476 if req.NewPassword == "" {
477 Error(w, http.StatusBadRequest, "New password is required")
478 return
479 }
480
481 existing, err := h.users.GetByID(r.Context(), userID)
482 if err != nil || existing == nil {
483 Error(w, http.StatusNotFound, "User not found")
484 return
485 }
486 if !existing.IsActive {
487 Error(w, http.StatusBadRequest, "Cannot reset password for inactive user")
488 return
489 }
490
491 // Prevent resetting the password of users with a higher-privilege role.
492 callerRole, _ := r.Context().Value(middleware.UserRoleKey).(string)
493 if roleRank(existing.Role) > roleRank(callerRole) {
494 Error(w, http.StatusForbidden, "Cannot reset password for a user with a higher-privilege role")
495 return
496 }
497 if existing.Role == "superadmin" && callerRole != "superadmin" {
498 perm, permErr := h.permissions.GetByRole(r.Context(), callerRole)
499 if permErr != nil || perm == nil || !perm.CanManageSuperusers {
500 Error(w, http.StatusForbidden, "You do not have permission to reset superadmin passwords")
501 return
502 }
503 }
504
505 if err := ValidatePasswordPolicy(h.resolved, req.NewPassword); err != nil {
506 Error(w, http.StatusBadRequest, err.Error())
507 return
508 }
509
510 hash, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), 12)
511 if err != nil {
512 Error(w, http.StatusInternalServerError, "Failed to hash password")
513 return
514 }
515
516 if err := h.users.UpdatePassword(r.Context(), userID, string(hash)); err != nil {
517 Error(w, http.StatusInternalServerError, "Failed to reset password")
518 return
519 }
520
521 // Revoke all sessions and trusted devices for the target user after password
522 // reset. An admin reset is the canonical post-compromise action; leaving
523 // either surface alive would let an attacker retain access despite the reset.
524 if err := h.sessions.RevokeAllForUser(r.Context(), userID, ""); err != nil && h.log != nil {

Callers

nothing calls this directly

Calls 11

decodeJSONFunction · 0.85
ErrorFunction · 0.85
roleRankFunction · 0.85
ValidatePasswordPolicyFunction · 0.85
GetByRoleMethod · 0.80
ErrorMethod · 0.80
JSONFunction · 0.70
UpdatePasswordMethod · 0.65
GetByIDMethod · 0.45
ValueMethod · 0.45
RevokeAllForUserMethod · 0.45

Tested by

no test coverage detected