Skip to content

Commit 234c606

Browse files
committed
fix: apply changes from previous PR
1 parent 498e7ba commit 234c606

File tree

17 files changed

+130
-108
lines changed

17 files changed

+130
-108
lines changed

site/e2e/global.setup.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ test("setup deployment", async ({ page }) => {
3535
expect(constants.license.split(".").length).toBe(3); // otherwise it's invalid
3636

3737
await page.goto("/deployment/licenses", { waitUntil: "domcontentloaded" });
38+
await expect(page).toHaveTitle("License Settings - Coder");
3839

3940
await page.getByText("Add a license").click();
4041
await page.getByRole("textbox").fill(constants.license);

site/jest.setup.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import "@testing-library/jest-dom";
22
import "jest-location-mock";
33
import { cleanup } from "@testing-library/react";
4-
import crypto from "crypto";
4+
import crypto from "node:crypto";
55
import { useMemo } from "react";
66
import type { Region } from "api/typesGenerated";
77
import type { ProxyLatencyReport } from "contexts/useProxyLatency";
@@ -48,9 +48,7 @@ global.ResizeObserver = require("resize-observer-polyfill");
4848
// Polyfill the getRandomValues that is used on utils/random.ts
4949
Object.defineProperty(global.self, "crypto", {
5050
value: {
51-
getRandomValues: function (buffer: Buffer) {
52-
return crypto.randomFillSync(buffer);
53-
},
51+
getRandomValues: crypto.randomFillSync,
5452
},
5553
});
5654

@@ -72,5 +70,5 @@ afterEach(() => {
7270
// Clean up after the tests are finished.
7371
afterAll(() => server.close());
7472

75-
// This is needed because we are compiling under `--isolatedModules`
73+
// biome-ignore lint/complexity/noUselessEmptyExport: This is needed because we are compiling under `--isolatedModules`
7674
export {};

site/src/contexts/auth/permissions.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { AuthorizationCheck } from "api/typesGenerated";
2+
13
export const checks = {
24
viewAllUsers: "viewAllUsers",
35
updateUsers: "updateUsers",
@@ -11,13 +13,20 @@ export const checks = {
1113
viewUpdateCheck: "viewUpdateCheck",
1214
viewExternalAuthConfig: "viewExternalAuthConfig",
1315
viewDeploymentStats: "viewDeploymentStats",
16+
readWorkspaceProxies: "readWorkspaceProxies",
1417
editWorkspaceProxies: "editWorkspaceProxies",
1518
createOrganization: "createOrganization",
1619
editAnyOrganization: "editAnyOrganization",
1720
viewAnyGroup: "viewAnyGroup",
1821
createGroup: "createGroup",
1922
viewAllLicenses: "viewAllLicenses",
20-
} as const;
23+
viewNotificationTemplate: "viewNotificationTemplate",
24+
} as const satisfies Record<string, string>;
25+
26+
// Type expression seems a little redundant (`keyof typeof checks` has the same
27+
// result), just because each key-value pair is currently symmetrical; this may
28+
// change down the line
29+
type PermissionValue = (typeof checks)[keyof typeof checks];
2130

2231
export const permissionsToCheck = {
2332
[checks.viewAllUsers]: {
@@ -94,6 +103,12 @@ export const permissionsToCheck = {
94103
},
95104
action: "read",
96105
},
106+
[checks.readWorkspaceProxies]: {
107+
object: {
108+
resource_type: "workspace_proxy",
109+
},
110+
action: "read",
111+
},
97112
[checks.editWorkspaceProxies]: {
98113
object: {
99114
resource_type: "workspace_proxy",
@@ -116,7 +131,6 @@ export const permissionsToCheck = {
116131
[checks.viewAnyGroup]: {
117132
object: {
118133
resource_type: "group",
119-
org_id: "any",
120134
},
121135
action: "read",
122136
},
@@ -132,6 +146,12 @@ export const permissionsToCheck = {
132146
},
133147
action: "read",
134148
},
135-
} as const;
149+
[checks.viewNotificationTemplate]: {
150+
object: {
151+
resource_type: "notification_template",
152+
},
153+
action: "read",
154+
},
155+
} as const satisfies Record<PermissionValue, AuthorizationCheck>;
136156

137-
export type Permissions = Record<keyof typeof permissionsToCheck, boolean>;
157+
export type Permissions = Record<PermissionValue, boolean>;

site/src/modules/management/DeploymentSettingsProvider.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const useDeploymentSettings = (): DeploymentSettingsValue => {
2020
const context = useContext(DeploymentSettingsContext);
2121
if (!context) {
2222
throw new Error(
23-
"useDeploymentSettings should be used inside of DeploymentSettingsLayout",
23+
`${useDeploymentSettings.name} should be used inside of ${DeploymentSettingsProvider.name}`,
2424
);
2525
}
2626

@@ -39,6 +39,9 @@ const DeploymentSettingsProvider: FC = () => {
3939
permissions.editAnyOrganization ||
4040
permissions.viewAnyAuditLog;
4141

42+
// Not a huge problem to unload the content in the event of an error,
43+
// because the sidebar rendering isn't tied to this. Even if the user hits
44+
// a 403 error, they'll still have navigation options
4245
if (deploymentConfigQuery.error) {
4346
return <ErrorAlert error={deploymentConfigQuery.error} />;
4447
}

site/src/modules/management/ManagementSettingsLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ const ManagementSettingsLayout: FC = () => {
7474
<Margins>
7575
<Stack css={{ padding: "48px 0" }} direction="row" spacing={6}>
7676
<Sidebar />
77-
<main css={{ width: "100%" }}>
77+
<main css={{ flexGrow: 1 }}>
7878
<Suspense fallback={<Loader />}>
7979
<Outlet />
8080
</Suspense>

site/src/modules/management/SidebarView.stories.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Meta, StoryObj } from "@storybook/react";
22
import {
3+
MockNoPermissions,
34
MockOrganization,
45
MockOrganization2,
56
MockPermissions,
@@ -96,7 +97,7 @@ export const NoDeploymentValues: Story = {
9697

9798
export const NoPermissions: Story = {
9899
args: {
99-
permissions: {},
100+
permissions: MockNoPermissions,
100101
},
101102
};
102103

site/src/modules/management/SidebarView.tsx

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ import { Loader } from "components/Loader/Loader";
1212
import { Sidebar as BaseSidebar } from "components/Sidebar/Sidebar";
1313
import { Stack } from "components/Stack/Stack";
1414
import { UserAvatar } from "components/UserAvatar/UserAvatar";
15+
import type { Permissions } from "contexts/auth/permissions";
1516
import { type ClassName, useClassName } from "hooks/useClassName";
1617
import { useDashboard } from "modules/dashboard/useDashboard";
17-
import { linkToUsers } from "modules/navigation";
1818
import type { FC, ReactNode } from "react";
1919
import { Link, NavLink } from "react-router-dom";
2020

@@ -30,7 +30,7 @@ interface SidebarProps {
3030
/** Organizations and their permissions or undefined if still fetching. */
3131
organizations: OrganizationWithPermissions[] | undefined;
3232
/** Site-wide permissions. */
33-
permissions: AuthorizationResponse;
33+
permissions: Permissions;
3434
}
3535

3636
/**
@@ -72,7 +72,7 @@ interface DeploymentSettingsNavigationProps {
7272
/** Whether a deployment setting page is being viewed. */
7373
active: boolean;
7474
/** Site-wide permissions. */
75-
permissions: AuthorizationResponse;
75+
permissions: Permissions;
7676
}
7777

7878
/**
@@ -130,10 +130,11 @@ const DeploymentSettingsNavigation: FC<DeploymentSettingsNavigationProps> = ({
130130
{permissions.viewDeploymentValues && (
131131
<SidebarNavSubItem href="network">Network</SidebarNavSubItem>
132132
)}
133-
{/* All users can view workspace regions. */}
134-
<SidebarNavSubItem href="workspace-proxies">
135-
Workspace Proxies
136-
</SidebarNavSubItem>
133+
{permissions.readWorkspaceProxies && (
134+
<SidebarNavSubItem href="workspace-proxies">
135+
Workspace Proxies
136+
</SidebarNavSubItem>
137+
)}
137138
{permissions.viewDeploymentValues && (
138139
<SidebarNavSubItem href="security">Security</SidebarNavSubItem>
139140
)}
@@ -145,12 +146,14 @@ const DeploymentSettingsNavigation: FC<DeploymentSettingsNavigationProps> = ({
145146
{permissions.viewAllUsers && (
146147
<SidebarNavSubItem href="users">Users</SidebarNavSubItem>
147148
)}
148-
<SidebarNavSubItem href="notifications">
149-
<Stack direction="row" alignItems="center" spacing={1}>
150-
<span>Notifications</span>
151-
<FeatureStageBadge contentType="beta" size="sm" />
152-
</Stack>
153-
</SidebarNavSubItem>
149+
{permissions.viewNotificationTemplate && (
150+
<SidebarNavSubItem href="notifications">
151+
<Stack direction="row" alignItems="center" spacing={1}>
152+
<span>Notifications</span>
153+
<FeatureStageBadge contentType="beta" size="sm" />
154+
</Stack>
155+
</SidebarNavSubItem>
156+
)}
154157
</Stack>
155158
)}
156159
</div>
@@ -167,7 +170,7 @@ interface OrganizationsSettingsNavigationProps {
167170
/** Organizations and their permissions or undefined if still fetching. */
168171
organizations: OrganizationWithPermissions[] | undefined;
169172
/** Site-wide permissions. */
170-
permissions: AuthorizationResponse;
173+
permissions: Permissions;
171174
}
172175

173176
/**
@@ -241,8 +244,6 @@ interface OrganizationSettingsNavigationProps {
241244
const OrganizationSettingsNavigation: FC<
242245
OrganizationSettingsNavigationProps
243246
> = ({ active, organization }) => {
244-
const { experiments } = useDashboard();
245-
246247
return (
247248
<>
248249
<SidebarNavItem

site/src/pages/DeploymentSettingsPage/ExternalAuthSettingsPage/ExternalAuthSettingsPage.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,7 @@ const ExternalAuthSettingsPage: FC = () => {
1313
<Helmet>
1414
<title>{pageTitle("External Authentication Settings")}</title>
1515
</Helmet>
16-
17-
{deploymentConfig ? (
18-
<ExternalAuthSettingsPageView config={deploymentConfig.config} />
19-
) : (
20-
<Loader />
21-
)}
16+
<ExternalAuthSettingsPageView config={deploymentConfig.config} />
2217
</>
2318
);
2419
};

site/src/pages/DeploymentSettingsPage/GeneralSettingsPage/GeneralSettingsPage.tsx

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { deploymentDAUs } from "api/queries/deployment";
22
import { entitlements } from "api/queries/entitlements";
33
import { availableExperiments, experiments } from "api/queries/experiments";
4-
import { Loader } from "components/Loader/Loader";
54
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
65
import type { FC } from "react";
76
import { Helmet } from "react-helmet-async";
@@ -30,18 +29,14 @@ const GeneralSettingsPage: FC = () => {
3029
<Helmet>
3130
<title>{pageTitle("General Settings")}</title>
3231
</Helmet>
33-
{deploymentConfig ? (
34-
<GeneralSettingsPageView
35-
deploymentOptions={deploymentConfig.options}
36-
deploymentDAUs={deploymentDAUsQuery.data}
37-
deploymentDAUsError={deploymentDAUsQuery.error}
38-
entitlements={entitlementsQuery.data}
39-
invalidExperiments={invalidExperiments}
40-
safeExperiments={safeExperiments}
41-
/>
42-
) : (
43-
<Loader />
44-
)}
32+
<GeneralSettingsPageView
33+
deploymentOptions={deploymentConfig.options}
34+
deploymentDAUs={deploymentDAUsQuery.data}
35+
deploymentDAUsError={deploymentDAUsQuery.error}
36+
entitlements={entitlementsQuery.data}
37+
invalidExperiments={invalidExperiments}
38+
safeExperiments={safeExperiments}
39+
/>
4540
</>
4641
);
4742
};

site/src/pages/DeploymentSettingsPage/NetworkSettingsPage/NetworkSettingsPage.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,7 @@ const NetworkSettingsPage: FC = () => {
1313
<Helmet>
1414
<title>{pageTitle("Network Settings")}</title>
1515
</Helmet>
16-
17-
{deploymentConfig ? (
18-
<NetworkSettingsPageView options={deploymentConfig.options} />
19-
) : (
20-
<Loader />
21-
)}
16+
<NetworkSettingsPageView options={deploymentConfig.options} />
2217
</>
2318
);
2419
};

site/src/pages/DeploymentSettingsPage/NotificationsPage/NotificationsPage.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ import { Section } from "pages/UserSettingsPage/Section";
1111
import type { FC } from "react";
1212
import { Helmet } from "react-helmet-async";
1313
import { useQueries } from "react-query";
14-
import { useSearchParams } from "react-router-dom";
1514
import { deploymentGroupHasParent } from "utils/deployOptions";
1615
import { pageTitle } from "utils/page";
1716
import OptionsTable from "../OptionsTable";
1817
import { NotificationEvents } from "./NotificationEvents";
1918
import { useDeploymentSettings } from "modules/management/DeploymentSettingsProvider";
19+
import { useSearchParamsKey } from "hooks/useSearchParamsKey";
2020

2121
export const NotificationsPage: FC = () => {
22-
const [searchParams] = useSearchParams();
2322
const { deploymentConfig } = useDeploymentSettings();
2423
const [templatesByGroup, dispatchMethods] = useQueries({
2524
queries: [
@@ -30,10 +29,12 @@ export const NotificationsPage: FC = () => {
3029
notificationDispatchMethods(),
3130
],
3231
});
33-
const ready =
34-
templatesByGroup.data && dispatchMethods.data && deploymentConfig;
35-
const tab = searchParams.get("tab") || "events";
32+
const tabState = useSearchParamsKey({
33+
key: "tab",
34+
defaultValue: "events",
35+
});
3636

37+
const ready = !!(templatesByGroup.data && dispatchMethods.data);
3738
return (
3839
<>
3940
<Helmet>
@@ -45,7 +46,7 @@ export const NotificationsPage: FC = () => {
4546
layout="fluid"
4647
featureStage={"beta"}
4748
>
48-
<Tabs active={tab}>
49+
<Tabs active={tabState.value}>
4950
<TabsList>
5051
<TabLink to="?tab=events" value="events">
5152
Events
@@ -58,7 +59,7 @@ export const NotificationsPage: FC = () => {
5859

5960
<div css={styles.content}>
6061
{ready ? (
61-
tab === "events" ? (
62+
tabState.value === "events" ? (
6263
<NotificationEvents
6364
templatesByGroup={templatesByGroup.data}
6465
deploymentConfig={deploymentConfig.config}
@@ -71,7 +72,7 @@ export const NotificationsPage: FC = () => {
7172
/>
7273
) : (
7374
<OptionsTable
74-
options={deploymentConfig?.options.filter((o) =>
75+
options={deploymentConfig.options.filter((o) =>
7576
deploymentGroupHasParent(o.group, "Notifications"),
7677
)}
7778
/>

site/src/pages/DeploymentSettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPage.tsx

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { Loader } from "components/Loader/Loader";
21
import { useDashboard } from "modules/dashboard/useDashboard";
32
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
43
import type { FC } from "react";
@@ -17,16 +16,11 @@ const ObservabilitySettingsPage: FC = () => {
1716
<Helmet>
1817
<title>{pageTitle("Observability Settings")}</title>
1918
</Helmet>
20-
21-
{deploymentConfig ? (
22-
<ObservabilitySettingsPageView
23-
options={deploymentConfig.options}
24-
featureAuditLogEnabled={entitlements.features.audit_log.enabled}
25-
isPremium={hasPremiumLicense}
26-
/>
27-
) : (
28-
<Loader />
29-
)}
19+
<ObservabilitySettingsPageView
20+
options={deploymentConfig.options}
21+
featureAuditLogEnabled={entitlements.features.audit_log.enabled}
22+
isPremium={hasPremiumLicense}
23+
/>
3024
</>
3125
);
3226
};

site/src/pages/DeploymentSettingsPage/SecuritySettingsPage/SecuritySettingsPage.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,10 @@ const SecuritySettingsPage: FC = () => {
1515
<Helmet>
1616
<title>{pageTitle("Security Settings")}</title>
1717
</Helmet>
18-
19-
{deploymentConfig ? (
20-
<SecuritySettingsPageView
21-
options={deploymentConfig.options}
22-
featureBrowserOnlyEnabled={entitlements.features.browser_only.enabled}
23-
/>
24-
) : (
25-
<Loader />
26-
)}
18+
<SecuritySettingsPageView
19+
options={deploymentConfig.options}
20+
featureBrowserOnlyEnabled={entitlements.features.browser_only.enabled}
21+
/>
2722
</>
2823
);
2924
};

0 commit comments

Comments
 (0)