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.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/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.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 c805e33c02cef..1352233bfe597 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.tsx @@ -6,11 +6,14 @@ import { Loader } from "components/Loader/Loader" import { FC, useEffect } from "react" import { useParams } from "react-router-dom" import { firstOrItem } from "util/array" -import { quotaMachine } from "xServices/quotas/quotasXService" 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) && ( + + )} + + + + + + + + + + ) } 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 ProxypFad ProxypFad v3 ProxypFad v4 Proxy
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