From 7dfad65496755ee5e7966820d0c5df664a1e6b5f Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Fri, 24 Mar 2023 19:00:11 +0000 Subject: [PATCH 1/2] fix(UI): redirect if user is not permissioned to see workspace --- site/src/hooks/useReadPagePermissions.ts | 27 ++++++ site/src/pages/AuditPage/AuditPage.tsx | 51 ++++++---- .../src/pages/WorkspacePage/WorkspacePage.tsx | 95 +++++++++++-------- 3 files changed, 114 insertions(+), 59 deletions(-) create mode 100644 site/src/hooks/useReadPagePermissions.ts diff --git a/site/src/hooks/useReadPagePermissions.ts b/site/src/hooks/useReadPagePermissions.ts new file mode 100644 index 0000000000000..b1b199cda214a --- /dev/null +++ b/site/src/hooks/useReadPagePermissions.ts @@ -0,0 +1,27 @@ +import { useQuery } from "@tanstack/react-query" +import { checkAuthorization } from "api/api" + +export const useReadPagePermissions = ( + resource_type: string, + resource_id?: string, + enabled = true, +) => { + const queryKey = ["readPagePermissions", resource_type, resource_id] + const params = { + checks: { + readPagePermissions: { + object: { + resource_type, + resource_id, + }, + action: "read", + }, + }, + } + + return useQuery({ + queryKey, + queryFn: () => checkAuthorization(params), + enabled, + }) +} diff --git a/site/src/pages/AuditPage/AuditPage.tsx b/site/src/pages/AuditPage/AuditPage.tsx index d06808cb630ca..b8c22addb4ec1 100644 --- a/site/src/pages/AuditPage/AuditPage.tsx +++ b/site/src/pages/AuditPage/AuditPage.tsx @@ -11,8 +11,15 @@ import { pageTitle } from "util/page" import { auditMachine } from "xServices/audit/auditXService" import { PaginationMachineRef } from "xServices/pagination/paginationXService" import { AuditPageView } from "./AuditPageView" +import { RequirePermission } from "components/RequirePermission/RequirePermission" +import { useReadPagePermissions } from "hooks/useReadPagePermissions" +import { Loader } from "components/Loader/Loader" const AuditPage: FC = () => { + // we call the below hook to make sure the user has access to view the page + const { data: permissions, isLoading: isLoadingPermissions } = + useReadPagePermissions("audit_log") + const [searchParams, setSearchParams] = useSearchParams() const filter = searchParams.get("filter") ?? "" const [auditState, auditSend] = useMachine(auditMachine, { @@ -28,26 +35,34 @@ const AuditPage: FC = () => { const { auditLogs, count, apiError } = auditState.context const paginationRef = auditState.context.paginationRef as PaginationMachineRef - const { audit_log: isAuditLogVisible } = useFeatureVisibility() + const { audit_log: isAuditLogEnabled } = useFeatureVisibility() + + if (!permissions || isLoadingPermissions) { + return + } return ( - <> - - {pageTitle("Audit")} - - { - auditSend("FILTER", { filter }) - }} - paginationRef={paginationRef} - isNonInitialPage={nonInitialPage(searchParams)} - isAuditLogVisible={isAuditLogVisible} - error={apiError} - /> - + + <> + + {pageTitle("Audit")} + + { + auditSend("FILTER", { filter }) + }} + paginationRef={paginationRef} + isNonInitialPage={nonInitialPage(searchParams)} + isAuditLogVisible={isAuditLogEnabled} + error={apiError} + /> + + ) } diff --git a/site/src/pages/WorkspacePage/WorkspacePage.tsx b/site/src/pages/WorkspacePage/WorkspacePage.tsx index 1fae46c62c795..b94358345955a 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.tsx @@ -9,8 +9,11 @@ import { firstOrItem } from "util/array" import { workspaceMachine } from "xServices/workspace/workspaceXService" import { WorkspaceReadyPage } from "./WorkspaceReadyPage" import { quotaMachine } from "xServices/quotas/quotasXService" +import { RequirePermission } from "components/RequirePermission/RequirePermission" +import { useReadPagePermissions } from "hooks/useReadPagePermissions" export const WorkspacePage: FC = () => { + const styles = useStyles() const { username: usernameQueryParam, workspace: workspaceQueryParam } = useParams() const username = firstOrItem(usernameQueryParam, null) @@ -23,9 +26,13 @@ export const WorkspacePage: FC = () => { getTemplateParametersWarning, checkPermissionsError, } = workspaceState.context + + // we call the below hook to make sure the user has access to view the page + const { data: permissions, isLoading: isLoadingPermissions } = + useReadPagePermissions("workspace", workspace?.id) + const [quotaState, quotaSend] = useMachine(quotaMachine) const { getQuotaError } = quotaState.context - const styles = useStyles() /** * Get workspace, template, and organization on mount and whenever workspaceId changes. @@ -41,47 +48,53 @@ export const WorkspacePage: FC = () => { username && quotaSend({ type: "GET_QUOTA", username }) }, [username, quotaSend]) + if (!permissions || isLoadingPermissions) { + return + } + return ( - - -
- {Boolean(getWorkspaceError) && ( - - )} - {Boolean(getTemplateWarning) && ( - - )} - {Boolean(getTemplateParametersWarning) && ( - - )} - {Boolean(checkPermissionsError) && ( - - )} - {Boolean(getQuotaError) && ( - - )} -
-
- - - - - - -
+ + + +
+ {Boolean(getWorkspaceError) && ( + + )} + {Boolean(getTemplateWarning) && ( + + )} + {Boolean(getTemplateParametersWarning) && ( + + )} + {Boolean(checkPermissionsError) && ( + + )} + {Boolean(getQuotaError) && ( + + )} +
+
+ + + + + + +
+
) } From 0a4e0ef1bfcf8f70d9107b40853db210483fdde3 Mon Sep 17 00:00:00 2001 From: Kira Pilot Date: Sun, 26 Mar 2023 23:01:18 +0000 Subject: [PATCH 2/2] fix tests --- site/src/pages/AuditPage/AuditPage.test.tsx | 4 ++++ site/src/pages/WorkspacePage/WorkspacePage.test.tsx | 6 ++++++ site/src/pages/WorkspacePage/WorkspacePage.tsx | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/site/src/pages/AuditPage/AuditPage.test.tsx b/site/src/pages/AuditPage/AuditPage.test.tsx index 3305243739e47..5883a0bfd1b8f 100644 --- a/site/src/pages/AuditPage/AuditPage.test.tsx +++ b/site/src/pages/AuditPage/AuditPage.test.tsx @@ -48,6 +48,10 @@ describe("AuditPage", () => { const mock = jest.spyOn(CreateDayString, "createDayString") mock.mockImplementation(() => "a minute ago") + jest.spyOn(API, "checkAuthorization").mockResolvedValue({ + readPagePermissions: true, + }) + // Mock the entitlements server.use( rest.get("/api/v2/entitlements", (req, res, ctx) => { diff --git a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx index dbb2408be7cd6..4c6f7eba2bc57 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx @@ -31,6 +31,9 @@ const { t } = i18next // It renders the workspace page and waits for it be loaded const renderWorkspacePage = async () => { + jest.spyOn(api, "checkAuthorization").mockResolvedValue({ + readPagePermissions: true, + }) jest.spyOn(api, "getTemplate").mockResolvedValueOnce(MockTemplate) jest.spyOn(api, "getTemplateVersionRichParameters").mockResolvedValueOnce([]) renderWithAuth(, { @@ -191,6 +194,9 @@ describe("WorkspacePage", () => { it("updates the parameters when they are missing during update", async () => { // Setup mocks const user = userEvent.setup() + jest.spyOn(api, "checkAuthorization").mockResolvedValue({ + readPagePermissions: true, + }) jest .spyOn(api, "getWorkspaceByOwnerAndName") .mockResolvedValueOnce(MockOutdatedWorkspace) diff --git a/site/src/pages/WorkspacePage/WorkspacePage.tsx b/site/src/pages/WorkspacePage/WorkspacePage.tsx index 97346f4baa18a..1352233bfe597 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.tsx @@ -53,7 +53,7 @@ export const WorkspacePage: FC = () => { } return ( - +
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy