fix(users): grant manager Review Queue access, restrict Webhooks to admin
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled

Manager could not see the Review Queue nav item, load the page, or
call mark-reviewed (red_lead/blue_lead/admin only) — added to the
route guard, sidebar visibility, badge query, and the backend
endpoint's role check.

Webhook Configuration was shown to red_lead/blue_lead in Settings
even though the backend already restricted every webhook endpoint to
admin only — the tab is now admin-only in the UI too, matching what
was already enforced server-side.
This commit is contained in:
kitos
2026-07-16 10:31:21 +02:00
parent 0002601b50
commit 0b60531677
6 changed files with 33 additions and 8 deletions
+1 -1
View File
@@ -59,7 +59,7 @@ export default function App() {
<Route
path="/techniques/review-queue"
element={
<ProtectedRoute roles={["admin", "red_lead", "blue_lead"]}>
<ProtectedRoute roles={["admin", "red_lead", "blue_lead", "manager"]}>
<Suspense fallback={<LoadingSpinner text="Loading…" />}><ReviewQueuePage /></Suspense>
</ProtectedRoute>
}
+2 -2
View File
@@ -43,7 +43,7 @@ const mainLinks: NavItem[] = [
icon: Grid3X3,
children: [
{ to: "/matrix", label: "Coverage Matrix", icon: Grid3X3 },
{ to: "/techniques/review-queue", label: "Review Queue", icon: ClipboardCheck, roles: ["admin", "red_lead", "blue_lead"] },
{ to: "/techniques/review-queue", label: "Review Queue", icon: ClipboardCheck, roles: ["admin", "red_lead", "blue_lead", "manager"] },
],
},
{
@@ -159,7 +159,7 @@ export default function Sidebar() {
const isAdmin = role === "admin";
const canSeeReviewQueue =
isAdmin || role === "red_lead" || role === "blue_lead";
isAdmin || role === "red_lead" || role === "blue_lead" || role === "manager";
// Fetch review queue count for the badge (only for roles that can see it)
const { data: reviewQueue } = useQuery({
+2 -1
View File
@@ -336,7 +336,8 @@ export default function ReviewQueuePage() {
const canReview =
user?.role === "admin" ||
user?.role === "red_lead" ||
user?.role === "blue_lead";
user?.role === "blue_lead" ||
user?.role === "manager";
const [expandedId, setExpandedId] = useState<string | null>(null);
+2 -3
View File
@@ -1693,7 +1693,6 @@ export default function SettingsPage() {
const { user } = useAuth();
const role = user?.role ?? "viewer";
const isAdmin = role === "admin";
const isLead = ["admin", "red_lead", "blue_lead"].includes(role);
const [activeTab, setActiveTab] = useState<Tab>("profile");
@@ -1705,7 +1704,7 @@ export default function SettingsPage() {
id: "webhooks",
label: "Webhooks",
icon: Webhook,
show: isLead,
show: isAdmin,
},
{ id: "email", label: "Email / SMTP", icon: Mail, show: isAdmin },
{ id: "jira", label: "Jira", icon: Link2, show: isAdmin },
@@ -1760,7 +1759,7 @@ export default function SettingsPage() {
<NotificationSection />
</Section>
)}
{activeTab === "webhooks" && isLead && (
{activeTab === "webhooks" && isAdmin && (
<Section title="Webhook Configuration" icon={Webhook}>
<WebhooksSection />
</Section>