From 07c6164cebe747891cf875d83c22ff18f934bb49 Mon Sep 17 00:00:00 2001 From: kitos Date: Fri, 29 May 2026 15:47:08 +0200 Subject: [PATCH] fix(permissions): hide action buttons for unauthorized roles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TestCatalogPage: 'Use Template' button had no role check — any user (including viewer/blue_tech/red_tech) could see and click it, which would fail at the backend (POST /tests/from-template requires red_lead|blue_lead). Added canUseTemplate check; button hidden for viewer, blue_tech, red_tech. TechniqueDetailPage: 'Run This Test' / 'Re-run' buttons in the Available Templates section also had no role check. Added canRunTemplate (same criteria: admin|red_lead|blue_lead). The 'View test' button for active tests remains visible to everyone (read-only navigation). Principle: if a user cannot perform the action, the button does not appear — no permission error messages, just absence of the control. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/pages/TechniqueDetailPage.tsx | 8 ++++-- frontend/src/pages/TestCatalogPage.tsx | 29 ++++++++++++++++------ 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/frontend/src/pages/TechniqueDetailPage.tsx b/frontend/src/pages/TechniqueDetailPage.tsx index c575fb3..a3513bf 100644 --- a/frontend/src/pages/TechniqueDetailPage.tsx +++ b/frontend/src/pages/TechniqueDetailPage.tsx @@ -158,6 +158,10 @@ export default function TechniqueDetailPage() { const canReview = user?.role === "admin" || user?.role === "red_lead" || user?.role === "blue_lead"; + // Same roles that can create tests (mirrors backend POST /tests/from-template) + const canRunTemplate = + user?.role === "admin" || user?.role === "red_lead" || user?.role === "blue_lead"; + const { data: technique, isLoading, @@ -584,7 +588,7 @@ export default function TechniqueDetailPage() { View test - ) : ( + ) : canRunTemplate ? ( - )} + ) : null} ); diff --git a/frontend/src/pages/TestCatalogPage.tsx b/frontend/src/pages/TestCatalogPage.tsx index 14a3077..b82db71 100644 --- a/frontend/src/pages/TestCatalogPage.tsx +++ b/frontend/src/pages/TestCatalogPage.tsx @@ -14,6 +14,7 @@ import { import { getTemplates } from "../api/test-templates"; import TestFromTemplateForm from "../components/TestFromTemplateForm"; import type { TestTemplateSummary } from "../types/models"; +import { useAuth } from "../context/AuthContext"; // ── Constants ────────────────────────────────────────────────────── @@ -75,6 +76,13 @@ export default function TestCatalogPage() { const navigate = useNavigate(); const { templateId } = useParams<{ templateId: string }>(); const [searchParams, setSearchParams] = useSearchParams(); + const { user } = useAuth(); + + // Only leads and admins can create tests from templates + const canUseTemplate = + user?.role === "admin" || + user?.role === "red_lead" || + user?.role === "blue_lead"; const [search, setSearch] = useState(searchParams.get("search") || ""); const [source, setSource] = useState(searchParams.get("source") || ""); @@ -236,6 +244,7 @@ export default function TestCatalogPage() { navigate(`/test-catalog/${tpl.id}/use`)} /> ))} @@ -286,9 +295,11 @@ export default function TestCatalogPage() { function TemplateCard({ template, + canUse, onUse, }: { template: TestTemplateSummary; + canUse: boolean; onUse: () => void; }) { return ( @@ -341,14 +352,16 @@ function TemplateCard({ {/* Spacer */}
- {/* Action */} - + {/* Action — only visible to users who can create tests */} + {canUse && ( + + )}
); }