Prevent a super admin from changing their own access level

editUser() let a super user submit any type for any target, including
themselves - accidentally downgrading your own account could lock you
out of admin functions. Self-edits now keep the existing type
regardless of what was submitted; the type radios are disabled in the
UI for that case with an explanatory note.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fo3DiRRpmz2DXjD7Uzhc8u
This commit is contained in:
2026-07-12 09:36:04 +02:00
parent 357aff618c
commit 7967c36a11
2 changed files with 15 additions and 4 deletions
+7 -3
View File
@@ -26,25 +26,29 @@
</div> </div>
<?php if ($_SESSION['type'] === 'super'): ?> <?php if ($_SESSION['type'] === 'super'): ?>
<?php $editing_self = $edit && (int) $user['id'] === (int) $_SESSION['user_id']; ?>
<div class="col-sm-4"> <div class="col-sm-4">
<label for="user-type">User type *</label> <label for="user-type">User type *</label>
<div class="form-group"> <div class="form-group">
<div class="radio"> <div class="radio">
<label class="radio"> <label class="radio">
<input type="radio" name="type" value="super" required="required" <?php echo ($edit && $user['type'] =='super') ? "checked": "" ; ?>/> Super admin</label> <input type="radio" name="type" value="super" required="required" <?php echo ($edit && $user['type'] =='super') ? "checked": "" ; ?> <?php echo $editing_self ? "disabled" : ""; ?>/> Super admin</label>
</div> </div>
<div class="radio"> <div class="radio">
<label class="radio"> <label class="radio">
<input type="radio" name="type" value="admin" required="required" <?php echo ($edit && $user['type'] =='admin') ? "checked": "" ; ?>/> Admin</label> <input type="radio" name="type" value="admin" required="required" <?php echo ($edit && $user['type'] =='admin') ? "checked": "" ; ?> <?php echo $editing_self ? "disabled" : ""; ?>/> Admin</label>
</div> </div>
<div class="radio"> <div class="radio">
<label class="radio"> <label class="radio">
<input type="radio" name="type" value="user" required="required" id="type-user" <?php echo ($edit && $user['type'] =='user') ? "checked": "" ; ?>/> User (read-only)</label> <input type="radio" name="type" value="user" required="required" id="type-user" <?php echo ($edit && $user['type'] =='user') ? "checked": "" ; ?> <?php echo $editing_self ? "disabled" : ""; ?>/> User (read-only)</label>
</div> </div>
</div> </div>
<?php if ($editing_self): ?>
<small class="form-text text-muted">You can't change your own access level.</small>
<?php endif; ?>
</div> </div>
<div class="col-sm-12 mt-2" id="user-view-toggles"> <div class="col-sm-12 mt-2" id="user-view-toggles">
+8 -1
View File
@@ -160,7 +160,14 @@ class Users
'edit' => "true", 'edit' => "true",
)); ));
$requested_type = $_SESSION['type'] === 'admin' ? 'user' : ($input_data['type'] ?? ''); $is_self_edit = (int) $input_data['id'] === (int) $_SESSION['user_id'];
// A user editing their own account keeps their current type, even if a
// different value was submitted - prevents accidentally (or deliberately)
// locking yourself out by downgrading your own access level.
$requested_type = $_SESSION['type'] === 'admin'
? 'user'
: ($is_self_edit ? $target['type'] : ($input_data['type'] ?? ''));
$validation_error = $this->validateUsernameAndType($input_data['username'] ?? '', $requested_type); $validation_error = $this->validateUsernameAndType($input_data['username'] ?? '', $requested_type);
if ($validation_error !== null) { if ($validation_error !== null) {