From c580a7c05d2e18e462dcbec078c34d4627d37c96 Mon Sep 17 00:00:00 2001 From: sysops Date: Sun, 26 Jul 2026 21:50:19 +0200 Subject: [PATCH] =?UTF-8?q?fix(PROJ-72):=20Superadmin=20kann=20Passwort/Ro?= =?UTF-8?q?lle=20von=20Superadmin-Peers=20nicht=20=C3=A4ndern?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SEC-01 Privilegien-Check (roleLevel(target) >= roleLevel(sess)) blockte Superadmin (höchstes Level) bei jedem Ziel-User mit gleichem Level - inklusive anderer Superadmins. Passwort-Reset durch Superadmin schlug dadurch fehl. Superadmin ist jetzt vom Peer-Level-Check ausgenommen, da kein höheres Level existiert. --- internal/api/admin_users_handlers.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/internal/api/admin_users_handlers.go b/internal/api/admin_users_handlers.go index 501253d..dad523e 100644 --- a/internal/api/admin_users_handlers.go +++ b/internal/api/admin_users_handlers.go @@ -155,14 +155,17 @@ func (s *Server) handleUpdateUser(w http.ResponseWriter, r *http.Request) { // SEC-01: Privilege escalation check — caller must not assign a role // at or above their own level, and must not modify users at or above - // their own level. - if roleLevel(target.Role) >= roleLevel(sess.Role) { - writeError(w, http.StatusForbidden, "insufficient privileges to modify this user") - return - } - if req.Role != nil && roleLevel(*req.Role) >= roleLevel(sess.Role) { - writeError(w, http.StatusForbidden, "insufficient privileges to assign this role") - return + // their own level. Superadmin is the top level, so peer (same-level) + // checks would otherwise block superadmin-vs-superadmin management. + if sess.Role != userstore.RoleSuperAdmin { + if roleLevel(target.Role) >= roleLevel(sess.Role) { + writeError(w, http.StatusForbidden, "insufficient privileges to modify this user") + return + } + if req.Role != nil && roleLevel(*req.Role) >= roleLevel(sess.Role) { + writeError(w, http.StatusForbidden, "insufficient privileges to assign this role") + return + } } updated, err := s.users.Update(id, userstore.UpdateUserRequest{