MemberJunction / MemberJunction/MJ

Explorer's User Management screen offers controls that always fail for non-Owner admins

Open
#4,281 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.