admin: let superusers rename accounts
Some checks failed
Build and Deploy to Production / test (push) Successful in 26s
Build and Deploy to Production / build (push) Successful in 1m1s
Build and Deploy to Production / deploy (push) Has been cancelled

ADMIN_USER only seeds the first superuser on an empty table, so renaming
the secret afterwards had no effect and there was no other way to change
a login name. Superusers can now edit usernames in /admin/users,
including their own; sessions key on the user id and survive, duplicates
are refused, and the rename is audited.

Assisted-by: Claude:opus-5
This commit is contained in:
Sergei Poljanski 2026-10-10 08:45:20 +04:00
commit 6094d29a3f
Signed by: asxpi
GPG key ID: 4F8851660FA4121B
4 changed files with 34 additions and 4 deletions

View file

@ -112,6 +112,11 @@ module UsersAdmin
manageable!(user)
self_edit = user.id == current_user.id
before = perm_summary(user)
old_name = user.username
# Superusers may rename accounts; login sessions survive (they key on id).
if current_user.superuser && params[:username] && !params[:username].strip.empty?
user.username = params[:username].strip.downcase
end
user.name = params[:name].to_s.strip
user.email = params[:email].to_s.strip.downcase.then { |e| e.empty? ? nil : e }
unless self_edit # you can't lock yourself out
@ -120,13 +125,16 @@ module UsersAdmin
user.active = active
user.superuser = params[:superuser] == '1' if current_user.superuser
end
if !user.valid? || (user.email && User.exclude(id: user.id).where(email: user.email).any?)
session[:users_flash] = user.errors.full_messages.join('; ').then { |m| m.empty? ? 'Email already in use.' : m }
taken = User.exclude(id: user.id).where(username: user.username).any? ||
(user.email && User.exclude(id: user.id).where(email: user.email).any?)
if !user.valid? || taken
session[:users_flash] = user.errors.full_messages.join('; ').then { |m| m.empty? ? 'Username or email already in use.' : m }
redirect "/admin/users/#{user.id}"
end
perms = permission_params(user) # read before saving changes
user.save
save_permissions!(user, perms) unless user.superuser
audit!('user.rename', user.username, "#{old_name} → #{user.username}") if old_name != user.username
audit!('user.update', user.username, "#{before} → #{perm_summary(user.refresh)}#{' (disabled)' unless user.active}")
session[:users_flash] = 'Saved.'
redirect "/admin/users/#{user.id}"