Skip to content

feat: disallow UPLOAD_ONLY role from some views (BED-7937)#2944

Merged
dcairnsspecterops merged 8 commits into
mainfrom
BED-7937-gate-upload-only-roles-from-routes
Jul 6, 2026
Merged

feat: disallow UPLOAD_ONLY role from some views (BED-7937)#2944
dcairnsspecterops merged 8 commits into
mainfrom
BED-7937-gate-upload-only-roles-from-routes

Conversation

@dcairnsspecterops

@dcairnsspecterops dcairnsspecterops commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Description

Motivation and Context

We need a repeatable pattern for excluding users with certain roles from accessing given pages. After this PR, we will pass an array disallowedProps then display a badge instead of the route if the user's roles are on that list.

Resolves: BED-7937

How Has This Been Tested?

  • New unit test
  • Manual testing with Upload Only user confirming functionality.

Screenshots (if appropriate):

image
  • Chore (a change that does not modify the application functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Database Migrations

Checklist:

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Route metadata can now include role-based restrictions (role name + notification message).
    • Shared UI utilities now expose additional role-related exports for reuse.
  • Enhancements

    • Protected routes can specify disallowed roles; when matched, the app shows a red badge with the first matching role’s notification instead of rendering the protected content.
    • Route-level restrictions are now forwarded to the authentication guard.
  • Tests

    • Added coverage for blocked vs allowed access based on user roles and route-level restrictions.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change adds disallowedRoles metadata to routable routes, passes it into authenticated route rendering, and shows a badge when the current user matches a disallowed role. It also adds test coverage for the new disallowed-role path.

Changes

Route role metadata and enforcement

Layer / File(s) Summary
Route metadata and role utilities
packages/javascript/bh-shared-ui/src/routes/index.tsx, packages/javascript/bh-shared-ui/src/utils/index.ts
Routable gains optional disallowedRoles metadata, and the shared UI utils barrel re-exports ./roles.
Authenticated route disallowed-role handling
cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.tsx, cmd/ui/src/views/Content.tsx
AuthenticatedRoute accepts and evaluates disallowedRoles, renders a badge for matching roles, and Content forwards route metadata into the wrapper.
Authenticated route tests
cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.test.tsx
Test routes and async cases cover the disallowed-role badge path and the normal authenticated-content path.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested labels: enhancement, user interface

Suggested reviewers: specter-flq, TheNando

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: blocking the UPLOAD_ONLY role from selected views.
Description check ✅ Passed The description follows the template with summary, motivation, testing, screenshots, and issue reference.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch BED-7937-gate-upload-only-roles-from-routes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/javascript/bh-shared-ui/src/routes/index.tsx (1)

70-70: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider using RoleValue type for name instead of plain string.

roles.ts exports a RoleValue type derived from the Roles const map. Typing disallowedRoles[].name against it would prevent typos/drift between route configs and actual role names, rather than allowing any arbitrary string.

♻️ Suggested refactor
+import type { RoleValue } from '../utils/roles';
+
 export type Routable = {
     path: string;
     component: React.LazyExoticComponent<React.FC>;
     authenticationRequired: boolean;
     navigation: boolean;
     exact?: boolean;
-    disallowedRoles?: { name: string; notification: string }[];
+    disallowedRoles?: { name: RoleValue; notification: string }[];
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/javascript/bh-shared-ui/src/routes/index.tsx` at line 70, The
disallowedRoles entry in the route config is using a plain string for the role
name, which can drift from the actual role constants. Update the Route type in
index.tsx so disallowedRoles[].name uses the shared RoleValue type exported from
roles.ts instead of string, and make sure the type is imported and applied
consistently wherever route role names are declared.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/javascript/bh-shared-ui/src/routes/index.tsx`:
- Line 70: The disallowedRoles entry in the route config is using a plain string
for the role name, which can drift from the actual role constants. Update the
Route type in index.tsx so disallowedRoles[].name uses the shared RoleValue type
exported from roles.ts instead of string, and make sure the type is imported and
applied consistently wherever route role names are declared.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 066d6c2f-de05-41da-9879-e06fc0e8a41a

📥 Commits

Reviewing files that changed from the base of the PR and between f0a35b2 and f3a99ab.

📒 Files selected for processing (2)
  • packages/javascript/bh-shared-ui/src/routes/index.tsx
  • packages/javascript/bh-shared-ui/src/utils/index.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.tsx`:
- Around line 45-57: The disallowed-role badge branch in AuthenticatedRoute is
executing before the authentication/session and password-expiry guards, which
can hide the required redirect for expired users. Reorder the logic in
AuthenticatedRoute so the existing auth/session and password-expiry checks run
first, and only evaluate hasDisallowedRoles after those guards have passed; keep
the Badge render tied to the disallowed-role path after the redirect conditions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 773028b5-2e23-4fcd-bb5b-d2465e44d23b

📥 Commits

Reviewing files that changed from the base of the PR and between f3a99ab and e63d47e.

📒 Files selected for processing (2)
  • cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.tsx
  • cmd/ui/src/views/Content.tsx

Comment thread cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.test.tsx (1)

133-185: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor: wrapping render in await act(async () => {...}) may be redundant if the shared render helper from src/test-utils already flushes effects/act internally; not blocking.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.test.tsx` around
lines 133 - 185, The two AuthenticatedRoute tests are unnecessarily wrapping the
shared render helper in await act(async () => {...}), which may be redundant if
src/test-utils already handles act/effect flushing. Remove the extra act wrapper
from these TestRoutes render calls and keep the assertions unchanged, using the
existing render, screen, and window.location.pathname checks to verify behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.test.tsx`:
- Around line 146-150: The mock user role in AuthenticatedRoute.test.tsx does
not match the configured disallowedRoles, so the test is asserting the wrong
branch. Update the mocked role inside the AuthenticatedRoute test to use
DISALLOWED_ROLE_NAME so it matches the disallowedRoles check in
AuthenticatedRoute’s role-matching logic, and keep the assertion aligned with
the badge rendering path rather than the children-rendering path.
- Around line 169-175: The authenticated-user mock is missing roles, which can
still crash when AuthenticatedRoute evaluates disallowedRoles. Update the
component’s roles check in AuthenticatedRoute to guard the lookup with optional
chaining or a default empty array around authState.user?.roles.find, and add
roles: [] to this test fixture so the normal-page path can run without throwing.

---

Nitpick comments:
In `@cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.test.tsx`:
- Around line 133-185: The two AuthenticatedRoute tests are unnecessarily
wrapping the shared render helper in await act(async () => {...}), which may be
redundant if src/test-utils already handles act/effect flushing. Remove the
extra act wrapper from these TestRoutes render calls and keep the assertions
unchanged, using the existing render, screen, and window.location.pathname
checks to verify behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 55681a07-fede-4a4e-ac28-9cd62493b35a

📥 Commits

Reviewing files that changed from the base of the PR and between 3f4dfb7 and 038a0dd.

📒 Files selected for processing (1)
  • cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.test.tsx

@coderabbitai coderabbitai Bot added enhancement New feature or request user interface A pull request containing changes affecting the UI code. labels Jul 6, 2026
@dcairnsspecterops dcairnsspecterops merged commit 7fdb4e6 into main Jul 6, 2026
12 checks passed
@dcairnsspecterops dcairnsspecterops deleted the BED-7937-gate-upload-only-roles-from-routes branch July 6, 2026 23:59
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

enhancement New feature or request user interface A pull request containing changes affecting the UI code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants