First to Site
Release 3.9

Ordering Portal Impersonation Picker

Searchable paginated user picker on the ordering portal, gated purely on ROLE_ADMIN, with the email allowlist retired

Overview

The ordering portal had an impersonation feature gated by an ORDERING_IMPERSONATION_ALLOWED_EMAILS environment variable - an email allowlist maintained on each host. Any admin not in the allowlist could not impersonate, even if they were legitimately ROLE_ADMIN. The workflow to add a new admin was awkward (env-var edit + deploy) and the allowlist drifted between environments.

Git tag v3.9.0 (part of Release 3.9) retires the env var, centralises impersonation privilege on ROLE_ADMIN, and adds a proper searchable paginated user picker UI.

What Changed

New API Platform resource

ImpersonationUsersResource at GET /v3/api/ordering/impersonations/users. Supports ?page, ?pageSize, ?search query params. Returns {page, pageSize, total, search, items[]}. Secured declaratively with is_granted('ROLE_ADMIN'). The ImpersonationUsersProvider backs it.

Repository queries

UserRepository::findImpersonationTargets(search, limit, offset) and countImpersonationTargets(search) filter to:

  • ROLE_CUSTOMER users
  • status = active
  • Company has Ordering portal access
  • Excluding FTS company (internal staff do not appear as impersonation targets)
  • Excluding the acting admin themselves
  • Search matches across email / first name / last name / company / user group

Retired environment variable

ORDERING_IMPERSONATION_ALLOWED_EMAILS removed from the codebase. Impersonation is now gated purely on ROLE_ADMIN, layered:

  1. Declarative API Platform security on both the Post (start impersonation) and Get (users list) resources.
  2. Explicit role check in ImpersonationStartProcessor::hasImpersonationPrivilege().
  3. OrderController::impersonationIndex() route guard.
  4. Sidebar visibility: the "Impersonation" nav link is hidden from non-admins.

Rewritten UI

The impersonation page is now a paginated table:

  • 25 / 50 / 100 rows per page (dropdown)
  • Debounced search input (300ms)
  • Click-to-impersonate button per row
  • Confirm dialog before starting impersonation
  • Reuses the existing POST /v3/api/ordering/impersonations flow to actually start the session

Migration notes

Any admin who was in the old allowlist but does not actually have ROLE_ADMIN loses impersonation access with this release. Verify via Auth0 role assignments; add ROLE_ADMIN if they legitimately need it.