From 9351e308c1cc5d6971b02685a20dd3e792c6b1ab Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Mon, 27 Jul 2026 21:24:11 +0000 Subject: [PATCH 1/6] fix: allow only template admins/owners to navigate to template version pages --- .../pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx index 3aac57cbae8d4..021458b56112b 100644 --- a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx +++ b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx @@ -7,6 +7,7 @@ import { InfoTooltip } from "#/components/InfoTooltip/InfoTooltip"; import { Pill } from "#/components/Pill/Pill"; import { TableCell } from "#/components/Table/Table"; import { TimelineEntry } from "#/components/Timeline/TimelineEntry"; +import { useAuthenticated } from "#/hooks/useAuthenticated"; import { useClickableTableRow } from "#/hooks/useClickableTableRow"; interface VersionRowProps { @@ -25,6 +26,7 @@ export const VersionRow: FC = ({ onArchiveClick, }) => { const navigate = useNavigate(); + const { permissions } = useAuthenticated(); const clickableProps = useClickableTableRow({ onClick: () => navigate(version.name), @@ -33,7 +35,10 @@ export const VersionRow: FC = ({ const jobStatus = version.job.status; return ( - +
From 21edd5e4a2b99cef54ee872fe876d10c3637fbb8 Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Thu, 30 Jul 2026 22:10:29 +0000 Subject: [PATCH 2/6] fix: set clickable props correctly --- site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx index 021458b56112b..0eb4397905b18 100644 --- a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx +++ b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx @@ -37,7 +37,7 @@ export const VersionRow: FC = ({ return (
From 01cc4d18a80bea1eab78ec4fbe473ebb531ae898 Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Thu, 30 Jul 2026 22:23:23 +0000 Subject: [PATCH 3/6] fix: add auth provider to VersionsTable stories --- .../TemplateVersionsPage/VersionsTable.stories.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx index fecde1b2d7177..6b816f66361a3 100644 --- a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx +++ b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx @@ -5,18 +5,26 @@ import { MockCancelingProvisionerJob, MockFailedProvisionerJob, MockPendingProvisionerJob, + MockPermissions, MockRunningProvisionerJob, MockTemplateVersion, + MockUserOwner, } from "#/testHelpers/entities"; +import { withAuthProvider } from "#/testHelpers/storybook"; import { VersionsTable } from "./VersionsTable"; const meta: Meta = { title: "pages/TemplatePage/VersionsTable", component: VersionsTable, + parameters: { + user: MockUserOwner, + permissions: MockPermissions, + }, args: { onPromoteClick: () => {}, onArchiveClick: () => {}, }, + decorators: [withAuthProvider], }; export default meta; From 642433de9a3d8961907b05ea9630a286a58f6a4e Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Thu, 30 Jul 2026 22:29:21 +0000 Subject: [PATCH 4/6] test: add story for unclickable VersionRow --- .../TemplateVersionsPage/VersionsTable.stories.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx index 6b816f66361a3..bfaddf2f5f4e1 100644 --- a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx +++ b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx @@ -4,6 +4,7 @@ import { MockCanceledProvisionerJob, MockCancelingProvisionerJob, MockFailedProvisionerJob, + MockNoPermissions, MockPendingProvisionerJob, MockPermissions, MockRunningProvisionerJob, @@ -45,6 +46,13 @@ export const Example: Story = { }, }; +export const NoUpdatePermission: Story = { + args: { ...Example.args }, + parameters: { + permissions: MockNoPermissions, + }, +}; + export const NoEditPermission: Story = { args: { ...Example.args, From ca7d5bb47099f5cd3f077c81cc49dc9e5360ba50 Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Thu, 30 Jul 2026 22:37:34 +0000 Subject: [PATCH 5/6] feat: add aria-label to VersionRow --- site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx index 0eb4397905b18..71e39e45ddbaf 100644 --- a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx +++ b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionRow.tsx @@ -37,6 +37,7 @@ export const VersionRow: FC = ({ return ( From fb5c0e3b7301e7a48a52684a35365170c83eefd7 Mon Sep 17 00:00:00 2001 From: Andrew Aquino Date: Thu, 30 Jul 2026 22:40:50 +0000 Subject: [PATCH 6/6] test: add play functions to verify VersionRow's clickability --- .../TemplateVersionsPage/VersionsTable.stories.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx index bfaddf2f5f4e1..7b40e29fc7bc1 100644 --- a/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx +++ b/site/src/pages/TemplatePage/TemplateVersionsPage/VersionsTable.stories.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react-vite"; import { action } from "storybook/actions"; +import { within } from "storybook/test"; import { MockCanceledProvisionerJob, MockCancelingProvisionerJob, @@ -44,6 +45,11 @@ export const Example: Story = { MockTemplateVersion, ], }, + play: async ({ canvasElement }) => { + // With permissions.updateTemplates, VersionRow is a clickable button + const canvas = within(canvasElement); + await canvas.findByRole("button", { name: MockTemplateVersion.name }); + }, }; export const NoUpdatePermission: Story = { @@ -51,6 +57,11 @@ export const NoUpdatePermission: Story = { parameters: { permissions: MockNoPermissions, }, + play: async ({ canvasElement }) => { + // Without permissions.updateTemplates, VersionRow is a non-clickable row + const canvas = within(canvasElement); + await canvas.findByRole("row", { name: MockTemplateVersion.name }); + }, }; export const NoEditPermission: Story = {