Files
sure/test/system/admin_user_removals_test.rb
T
bb835b9793 feat: Super Admins can Delete Users and Modify Families/Groups (#2868)
* Add admin family management features and tests

- Implement FamiliesController with destroy action to delete unused families.
- Add localization for success and error messages related to family deletion.
- Create FamiliesControllerTest to ensure proper functionality of family deletion.
- Update UserPolicyTest to include permissions for super admins to delete users.
- Enhance UsersControllerTest with tests for user family management, including moving users between families and creating new families.

* feat(users): enhance user management with family transfer validation and improved delete warnings

* Simplify user management actions column and combine family options

Move heavy user edit forms from table rows into a DS::Popover action
menu, add role badges to the user column, combine family migration and
creation inputs with a Stimulus controller, enable self-family
transfer for super admins, and add safety guards against demoting the
last super admin in the system.

* feat: add authentication type pills to admin user index to display SSO and local login status

* Add set password feature for local users in admin user management

- Add password field in action popover for users with local password login
- Enforce all registration password criteria (min 8 chars, mixed case, digit, special char)
- Block simultaneous family and password updates with clear error
- Show descriptive success notifications (role, password, both, family)
- Ignore password param for SSO-only users
- Add comprehensive tests for all password validation paths

* Resolve DS Drift Patrol findings and CI scan failures

- Wrap auth-type pills in DS::Tooltip instead of native title= attribute

- Add actions.manage_user key to locale and drop redundant default: fallbacks

- Fix RuboCop style offenses in Admin::UsersController

- Update Brakeman ignore entry fingerprint for Admin::UsersController#user_params

* fix: update badge query to target DS::Pill structure

* Fix DS::Tooltip misuse hiding SSO auth-type pill in admin users view

The SSO pill was passed as a block to DS::Tooltip, which caused it to
render inside the hidden div[role="tooltip"] instead of being visible.
The text: option ("SSO Provider: ...") was also silently ignored because
tooltip_content returns content (the block) over @text when a block is
given.

Fix: render the SSO/Local+SSO pill directly as visible content and pass
DS::Tooltip with no block so text: is used as the tooltip popup. An info
icon now appears next to the pill and shows the provider name on hover.

Fixes test: Admin::UsersControllerTest#test_index_renders_auth_type_pills_for_local_and_sso_users

* Remove redundant default: fallback from role pill i18n lookup

All admin.users.index.roles.{guest,member,admin,super_admin} keys are
defined in the locale file and used elsewhere in the same view without
a default:. The fallback was redundant for every valid role and would
silently mask a missing or renamed key instead of raising in
development.

Drop the default: user.role.humanize argument so that any future
missing key surfaces immediately as I18n::MissingTranslationData.

* Revert unrelated JS/schema/split churn; fix transfer_to_family! default role

- Revert 62 JS files (Biome formatter and unrelated controller changes)
- Revert db/schema.rb dump churn (no new migrations in this branch)
- Revert unrelated split transaction view changes (edit/new.html.erb)
- Fix User#transfer_to_family! role default: role: role evaluates to nil
  when omitted; use explicit self.role to read model attribute

Keeps the PR focused on user/family management (~18-20 files).

* Fix last login and session count in admin user management

Store last_login_at and sessions_count directly on the users table
so they remain accurate after a user logs out.

- Add migration to add last_login_at (datetime) and sessions_count
  (integer, default 0) columns to users, with backfill from sessions
- Add counter_cache: :sessions_count to Session#belongs_to :user so
  the count auto-increments/decrements on session create/destroy
- Add after_create callback on Session to stamp user.last_login_at
- Update Admin::UsersController to read both values from users table
  instead of aggregating Session rows (which disappear on logout)

* Fix user management PR pending CI items

* Keep test current session after sign in

* Address PR review comments for user transfers

* refactor: update user removal label to "Delete User" and standardize component attribute naming

* Address PR Review Feedback for User Management

* test: Fix families and users controller tests for user management PR

* Limit PR 2868 schema diff

* Fix PR 2868 user management CI failures

---------

Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: sure-admin <sure-admin@splashblot.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2026-08-28 23:10:09 +02:00

53 lines
1.5 KiB
Ruby

require "application_system_test_case"
class AdminUserRemovalsTest < ApplicationSystemTestCase
include ActiveJob::TestHelper
setup do
@admin = users(:sure_support_staff)
@target = users(:family_member)
@target_email = @target.email
@identity = @target.oidc_identities.first!
@provider = @identity.provider
@uid = @identity.uid
end
test "super admin confirms removal and the SSO identity cannot return" do
sign_in @admin
visit admin_users_path
find("details", text: @target.family.name).find("summary").click
within find("tr", text: @target_email) do
find("button[aria-haspopup='dialog']").click
end
click_on "Delete User"
within "dialog[open]" do
assert_text "This immediately revokes access"
fill_in "User email", with: @target_email
click_on "Permanently remove user"
end
assert_text "User access revoked and permanent deletion scheduled."
assert_not @target.reload.active?
assert_empty @target.sessions
assert_empty @target.oidc_identities
assert SsoIdentityBlock.blocked?(provider: @provider, uid: @uid)
OmniAuth.config.mock_auth[:openid_connect] = OmniAuth::AuthHash.new(
provider: @provider,
uid: @uid,
info: { email: @target_email, name: "Removed SSO User" }
)
visit "/auth/openid_connect/callback"
assert_current_path new_session_path
assert_text "Could not authenticate via OpenID Connect."
assert_not User.exists?(email: @target_email)
ensure
OmniAuth.config.mock_auth[:openid_connect] = nil
end
end