MemberJunction / MemberJunction/MJ
Explorer's User Management screen offers controls that always fail for non-Owner admins
- Dominant language
- TSQL
- Stars
- 29
- Forks
- 6
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 323
Description
**Found by** the PR gauntlet on #4275 (`fix/4260-new-user-roles-default`), 2026-09-07. Not caused by that PR in the sense of introducing a bug — that PR fixed the *silent-failure* half of this. What remains is that the screen has no Owner gate at all, which is pre-existing at `f2ec156daf31670b42d7704e994686b09daf14df`.
### Where
`packages/Angular/Explorer/explorer-settings/src/lib/user-management/user-management.component.ts` (whole component; mutating paths at `toggleUserStatus` ~:570)
`packages/Angular/Explorer/explorer-settings/src/lib/user-management/user-dialog/user-dialog.component.ts` (~:199)
### What happens
The screen renders full user-administration controls — edit any user, activate/deactivate any user — for anyone whose role grants update on `MJ: Users`. Since v6.1 the `MJUserEntityServer` guard (issue #4260) refuses every one of those writes for a caller whose `User.Type` is not `'Owner'`. The controls are therefore present, enabled, and guaranteed to fail.
The component has no authorization check of any kind. Its only `Owner` references are display-only: a stat tile counting admins (`this.users.filter(u => u.Type === 'Owner').length`) and a badge `case 'Owner':`.
### Why it matters
On a baseline seed the `Developer` and `Integration` roles hold unfiltered create/update/delete on `MJ: Users`, so a non-Owner administrator reaches this screen in practice. Every save now returns an error banner. The screen's primary function is unavailable to them, and nothing in the UI explains that the requirement is the caller's `Type`, not a missing role — so the natural operator response is to grant *more roles*, which cannot help.
### Repro
```bash
# 1. Sign in to Explorer as a user whose Type is 'User' but who holds the Developer role.
# 2. Settings -> User Management.
# 3. Toggle any other user's active status, or edit any other user and save.
# Observed: an error banner, every time. The controls never become usable.
```
### Evidence
Static verification during the gauntlet: no `Type`/Owner authorization check exists anywhere in `user-management.component.ts`. Server-side refusal messages confirmed live against a running MJAPI:
```
You may only modify your own user record. Changing another user's record requires an Owner.
Only an Owner may delete a user record. MJ deactivates users via IsActive rather than deleting them.
```
### Suggested fix
Gate the screen on the signed-in user's `Type === 'Owner'`, matching however Explorer gates its other Owner-only surfaces. Prefer a read-only presentation over hiding the route entirely: a non-Owner can legitimately *view* the user list, so render the list and disable the mutating controls with a short explanation ("Only an Owner can administer users"), rather than letting them click into guaranteed failures. Put the check in the component (or its route guard), not in the dialog, so both the inline toggle and the edit dialog are covered by one decision.
### Definition of done
- [ ] A failing test that reproduces it, then green
- [ ] For a non-Owner, the mutating controls are disabled or absent and an explanation is shown; for an Owner, behaviour is unchanged
- [ ] Existing suite and gates green; no changed expectation in an existing test
### Verify by
Signing in as a non-Owner with the Developer role: User Management shows the list read-only with the explanation, and offers no control whose save would be refused. Signing in as an Owner: unchanged.
Contributor guide
Research direction
Start in packages/Angular/Explorer/explorer-settings/src/lib/user-management/user-management.component.ts, especially toggleUserStatus, and inspect user-dialog/user-dialog.component.ts around line 199. Check how other Explorer surfaces gate Owner-only actions, then add a failing test and verify that non-Owners see a read-only list with an explanation while Owners retain current behavior. Run the existing suite and project gates to confirm all checks pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- angular, typescript
- Domain
- authorization, frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100