Skip to content

Instance/domain admin visibility: roles modal safeguards, consistent badges, role icon - #531

Open
caro3801 wants to merge 12 commits into
mainfrom
feat/wide-role-project-visibility
Open

caro3801 wants to merge 12 commits into
mainfrom
feat/wide-role-project-visibility

Conversation

@caro3801

@caro3801 caro3801 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

⚠️ Relies on backend PR ICIJ/datashare#2439

Summary

  • Roles modal (Settings > Users): the instance-wide grant now omits domain for instance_admin instead of sending *; adds a search filter; confirms (listing what gets revoked) before an instance/domain-wide grant replaces other roles; hides/disables project or domain scope options once a wider role already covers them, with an explanatory tooltip when the picker ends up disabled.
  • Project > Users: a row with an instance/domain admin grant now shows the same read-only badge used in the roles modal instead of a pointless editable dropdown.
  • Projects list: the "Your role" column shows the role's icon again, matching the rest of the app.

Test plan

  • Manually verified in the browser: scope picker disables with tooltip, cascade-confirm modal lists and revokes prior grants, project row badge, role icon on /#/projects

Uploading Screencast from 2026-10-07 10-27-51.webm…

…opes in the roles modal

Fixes the instance-wide grant sending domain=* for instance_admin instead of
omitting it entirely. Adds a search filter over the granted-roles table, a
confirmation step (listing what will be revoked) before an instance/domain-wide
grant replaces a user's other roles, and hides/disables project or domain
scope options once a wider role already covers them, with a tooltip
explaining why.
…ide-role project grant

An instance or domain admin role already covers every project, making a
project-specific dropdown pointless and misleading on that row. Replaces it
with the same read-only badge used in the Settings > Users roles modal
(InstanceUsersRoleBadge), showing only the highest rank when a row somehow
holds both.
The "Your role" column explicitly suppressed DisplayRole's icon, so every row
showed plain text while the role dropdown/badge elsewhere in the app always
pairs the label with its icon.
…a wrapper

b-dropdown sets inheritAttrs:false and spreads attrs onto its outer wrapper,
not the inner toggle button, so a bare `title` bound on DropdownSelector or
ProjectDropdownSelector never reached the focusable control a keyboard or
screen-reader user actually lands on. Adds a `toggleAttrs` passthrough on
DropdownSelector (b-dropdown's own prop for this) and a `title` prop on
ProjectDropdownSelector that forwards it that way.
…Dropdown

ProjectUsersList.vue stopped passing it once a wide-role project row got its
own read-only badge instead of this dropdown; nothing else in src/ passed it
either, leaving the prop, its "Inherited" branch, and the i18n string as
unreachable code.
A domain-admin-only viewer under OAuth always gets an empty scope picker
regardless of the target's grants (no instance/domain entry without
isInstanceAdmin, no project entry under OAuth), but scopePickerDisabledTitle
blamed the target ("already has a role on every project") instead of the
viewer's own permission ceiling. Checks that case first now.

Also documents two known limitations with TODO/comment notes rather than
fixing them (no domain model to filter by yet; the grant-time cascade-revoke
is enforced only in this component, not server-side).
TinyPagination's row-number input is only disabled, not hidden, at zero
rows, so it still shows a literal "0" next to the "of 0 users" label,
reading as "0 of 0 users".
A duplicate username only showed a toast, with no indication on the field
itself; the username input now gets :state="false" and an inline message,
cleared as soon as the username is edited again.
Each item embedded a <strong>verb</strong> as a raw HTML string rendered via
v-html, which vue-i18n flags as an XSS-prone pattern. Reworks each string
around a {verb} slot and renders through i18n-t, same pattern the modal
title already uses for its own embedded component.
type="email" already blocked the save via native checkValidity(), but
nothing in the page said why - only the browser's own tooltip. Adds a
visible inline message, same pattern as the password-mismatch field.
…te text

- Refresh the user data every time the roles modal opens, instead of trusting
  whatever stale `user` prop the parent happened to have (a role changed
  elsewhere, e.g. via the CLI, while the modal sat open went unnoticed).
- Confirm before revoking an instance/domain admin role, since it removes
  access to every project it covered, not just one row; plain project
  revokes stay single-click.
- "This user has no project role grants yet." reworded to "no role grants",
  since the same modal also manages domain and instance grants.
The backend now deletes the grants a wide role replaces when it is
granted: project grants, and domain admin under instance admin. The roles
modal no longer revokes them itself after granting, which also drops the
partial-failure path and its cleanup error toast. The confirmation still
lists what will be replaced, and now says those grants will not come
back if the role is revoked later.
@caro3801 caro3801 self-assigned this Oct 6, 2026
@caro3801
caro3801 requested review from a team and removed request for a team October 6, 2026 16:53

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

1 participant