Files
Eric Allam 1034b618a4 fix(webapp): let an impersonating admin preview the Queue Metrics UI (#4736)
## Summary

The Queue Metrics dashboard UI is gated by a per-org feature flag, so
there was no way to look at it for a real org without turning it on for
every member of that org. An admin impersonating into an org now sees
the metrics UI there regardless of the flag, so it can be checked
against real data before anyone else in the org sees it.

Nothing changes for a normal session: a member of an org whose flag is
off still gets the classic Queues page, and the gated sub-routes still
404.

## Design

The gate had no request and only resolved the org flag. It now takes the
request and resolves impersonation itself, rather than each caller
computing a boolean and passing it in, so the rule lives in one place
and a new call site cannot forget it. Seven call sites gate on this,
which is exactly why.

Two things narrow the bypass:

- It keys on **impersonation**, not `user.admin`. Impersonation is
scoped to one org and is deliberate; keying on admin status would
silently hand every admin the preview in their own day-to-day orgs.
- It yields to the **view-as-user** toggle. That toggle exists so an
impersonating admin can see what the member sees, and unreleased UI
leaking through it would make it lie. Suppressing a read-only view there
stays inside the display-only contract in `hasAdminDisplayAccess` (added
in #4421).

The bypass also stays behind the gate's existing org-membership lookup.
Since the acting user id is the impersonation target, that lookup is
what keeps the preview confined to the org actually being impersonated
into.

Verified end-to-end against a running instance across the matrix: member
with the flag off gets the classic view and 404s; the same org under
impersonation gets the metrics view and a 200; flipping view-as-user
returns it to the member's exact experience and back; and the flag-on
path is unchanged. An admin who is merely a member, not impersonating,
still gets the classic view.

One thing worth flagging: a few route comments say that with the flag
off no metrics reads fire. That remains true for every member session
and for the org as a whole, but an admin actively previewing does
exercise that org's real Redis and ClickHouse reads. That is inherent to
previewing, and bounded to one admin session.
2026-08-20 15:46:52 +01:00

42 lines
1.6 KiB
TypeScript

/**
* The rule for who sees the Queue Metrics dashboard UI.
*
* Kept pure and free of server-only imports so it can be unit tested directly,
* and so there is one definition of the rule for the server gate to share.
*/
/**
* Resolves the per-org feature flag against the request's impersonation state.
*
* The bypass exists so an admin can preview the UI for a real org before it is
* revealed to that org's members, which the flag alone cannot express: flags are
* org-scoped, so turning one on to look at the UI exposes every member of the org.
*
* It keys on impersonation rather than `user.admin` because impersonation is
* scoped to one org and is a deliberate act, where admin status is neither — an
* admin browsing their own orgs would otherwise silently get the preview
* everywhere.
*
* It yields to `isViewingAsUser`, which is the admin asking to see exactly what
* the member sees; previewing unreleased UI through that toggle would make it
* lie. Suppressing the preview there only ever hides a read-only view, so it
* stays inside the display-only contract that toggle is held to.
*
* The caller is responsible for only reporting `isImpersonating` for an
* impersonation into a member of the org being resolved, so the bypass cannot
* reach across orgs.
*/
export function resolveQueueMetricsUiAccess(options: {
flagEnabled: boolean;
isImpersonating: boolean;
isViewingAsUser: boolean;
}): boolean {
const { flagEnabled, isImpersonating, isViewingAsUser } = options;
if (flagEnabled) {
return true;
}
return isImpersonating && !isViewingAsUser;
}