Skip to content

Commit 76500be

Browse files
committed
chore: enable SBOM and containerd support in Docker builds
Added SBOM (Software Bill of Materials) generation during Docker build to enhance traceability. Refer to Docker documentation on SBOM: docs.docker.com/build/metadata/attestations/sbom Updated Docker build scripts to use BuildKit for provenance and SBOM support: docs.docker.com/build/metadata/attestations Configured Docker daemon to support the Containerd snapshotter feature to improve performance: docs.docker.com/engine/storage/containerd
1 parent 970d792 commit 76500be

File tree

13 files changed

+348
-328
lines changed

13 files changed

+348
-328
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ jobs:
259259
- name: Install Protoc
260260
run: |
261261
mkdir -p /tmp/proto
262-
build /tmp/proto
262+
pushd /tmp/proto
263263
curl -L -o protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v23.4/protoc-23.4-linux-x86_64.zip
264264
unzip protoc.zip
265265
cp -r ./bin/* /usr/local/bin

site/e2e/tests/auditLogs.spec.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
1-
import { type Page, expect, test } from "@playwright/test";
2-
import { users } from "../constants";
3-
import {
4-
createTemplate,
5-
createWorkspace,
6-
currentUser,
7-
login,
8-
requiresLicense,
9-
} from "../helpers";
10-
import { beforeCoderTest } from "../hooks";
1+
import {expect, type Page, test} from "@playwright/test";
2+
import {users} from "../constants";
3+
import {createTemplate, createWorkspace, login, requiresLicense,} from "../helpers";
4+
import {beforeCoderTest} from "../hooks";
115

126
test.describe.configure({ mode: "parallel" });
137

@@ -35,7 +29,6 @@ test("logins are logged", async ({ page }) => {
3529
await page.goto("/audit");
3630
const username = users.auditor.username;
3731

38-
const user = currentUser(page);
3932
const loginMessage = `${username} logged in`;
4033
// Make sure those things we did all actually show up
4134
await resetSearch(page, username);

site/src/pages/GroupsPage/GroupsPage.tsx

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import GroupAdd from "@mui/icons-material/GroupAddOutlined";
2-
import { getErrorMessage } from "api/errors";
3-
import { groupsByOrganization } from "api/queries/groups";
4-
import { organizationsPermissions } from "api/queries/organizations";
5-
import { ErrorAlert } from "components/Alert/ErrorAlert";
6-
import { Button } from "components/Button/Button";
7-
import { EmptyState } from "components/EmptyState/EmptyState";
8-
import { displayError } from "components/GlobalSnackbar/utils";
9-
import { Loader } from "components/Loader/Loader";
10-
import { SettingsHeader } from "components/SettingsHeader/SettingsHeader";
11-
import { Stack } from "components/Stack/Stack";
12-
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
13-
import { type FC, useEffect } from "react";
14-
import { Helmet } from "react-helmet-async";
15-
import { useQuery } from "react-query";
16-
import { Link as RouterLink } from "react-router-dom";
17-
import { pageTitle } from "utils/page";
18-
import { useGroupsSettings } from "./GroupsPageProvider";
2+
import {getErrorMessage} from "api/errors";
3+
import {groupsByOrganization} from "api/queries/groups";
4+
import {organizationsPermissions} from "api/queries/organizations";
5+
import {Button} from "components/Button/Button";
6+
import {EmptyState} from "components/EmptyState/EmptyState";
7+
import {displayError} from "components/GlobalSnackbar/utils";
8+
import {Loader} from "components/Loader/Loader";
9+
import {SettingsHeader} from "components/SettingsHeader/SettingsHeader";
10+
import {Stack} from "components/Stack/Stack";
11+
import {useFeatureVisibility} from "modules/dashboard/useFeatureVisibility";
12+
import {RequirePermission} from "modules/permissions/RequirePermission";
13+
import {type FC, useEffect} from "react";
14+
import {Helmet} from "react-helmet-async";
15+
import {useQuery} from "react-query";
16+
import {Link as RouterLink} from "react-router-dom";
17+
import {pageTitle} from "utils/page";
18+
import {useGroupsSettings} from "./GroupsPageProvider";
1919
import GroupsPageView from "./GroupsPageView";
2020

2121
export const GroupsPage: FC = () => {
@@ -54,16 +54,26 @@ export const GroupsPage: FC = () => {
5454
return <Loader />;
5555
}
5656

57+
const helmet = (
58+
<Helmet>
59+
<title>{pageTitle("Groups")}</title>
60+
</Helmet>
61+
);
62+
5763
const permissions = permissionsQuery.data?.[organization.id];
58-
if (!permissions) {
59-
return <ErrorAlert error={permissionsQuery.error} />;
64+
65+
if (!permissions?.viewGroups) {
66+
return (
67+
<>
68+
{helmet}
69+
<RequirePermission isFeatureVisible={false} />
70+
</>
71+
);
6072
}
6173

6274
return (
6375
<>
64-
<Helmet>
65-
<title>{pageTitle("Groups")}</title>
66-
</Helmet>
76+
{helmet}
6777

6878
<Stack
6979
alignItems="baseline"

site/src/pages/OrganizationSettingsPage/CustomRolesPage/CustomRolesPage.tsx

Lines changed: 69 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
import { getErrorMessage } from "api/errors";
2-
import { deleteOrganizationRole, organizationRoles } from "api/queries/roles";
3-
import type { Role } from "api/typesGenerated";
4-
import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog";
5-
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
6-
import { Loader } from "components/Loader/Loader";
7-
import { SettingsHeader } from "components/SettingsHeader/SettingsHeader";
8-
import { Stack } from "components/Stack/Stack";
9-
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
10-
import { useOrganizationSettings } from "modules/management/OrganizationSettingsLayout";
11-
import { RequirePermission } from "modules/permissions/RequirePermission";
12-
import { type FC, useEffect, useState } from "react";
13-
import { Helmet } from "react-helmet-async";
14-
import { useMutation, useQuery, useQueryClient } from "react-query";
15-
import { useParams } from "react-router-dom";
16-
import { pageTitle } from "utils/page";
1+
import {getErrorMessage} from "api/errors";
2+
import {deleteOrganizationRole, organizationRoles} from "api/queries/roles";
3+
import type {Role} from "api/typesGenerated";
4+
import {DeleteDialog} from "components/Dialogs/DeleteDialog/DeleteDialog";
5+
import {EmptyState} from "components/EmptyState/EmptyState";
6+
import {displayError, displaySuccess} from "components/GlobalSnackbar/utils";
7+
import {SettingsHeader} from "components/SettingsHeader/SettingsHeader";
8+
import {Stack} from "components/Stack/Stack";
9+
import {useFeatureVisibility} from "modules/dashboard/useFeatureVisibility";
10+
import {useOrganizationSettings} from "modules/management/OrganizationSettingsLayout";
11+
import {RequirePermission} from "modules/permissions/RequirePermission";
12+
import {type FC, useEffect, useState} from "react";
13+
import {Helmet} from "react-helmet-async";
14+
import {useMutation, useQuery, useQueryClient} from "react-query";
15+
import {useParams} from "react-router-dom";
16+
import {pageTitle} from "utils/page";
1717
import CustomRolesPageView from "./CustomRolesPageView";
1818

1919
export const CustomRolesPage: FC = () => {
@@ -22,7 +22,7 @@ export const CustomRolesPage: FC = () => {
2222
const { organization: organizationName } = useParams() as {
2323
organization: string;
2424
};
25-
const { organizationPermissions } = useOrganizationSettings();
25+
const { organization, organizationPermissions } = useOrganizationSettings();
2626

2727
const [roleToDelete, setRoleToDelete] = useState<Role>();
2828

@@ -49,65 +49,67 @@ export const CustomRolesPage: FC = () => {
4949
}
5050
}, [organizationRolesQuery.error]);
5151

52-
if (!organizationPermissions) {
53-
return <Loader />;
52+
if (!organization) {
53+
return <EmptyState message="Organization not found" />;
5454
}
5555

5656
return (
57-
<RequirePermission
58-
isFeatureVisible={
59-
organizationPermissions.assignOrgRoles ||
60-
organizationPermissions.createOrgRoles ||
61-
organizationPermissions.viewOrgRoles
62-
}
63-
>
57+
<>
6458
<Helmet>
65-
<title>{pageTitle("Custom Roles")}</title>
59+
<title>
60+
{pageTitle(
61+
"Custom Roles",
62+
organization.display_name || organization.name,
63+
)}
64+
</title>
6665
</Helmet>
67-
68-
<Stack
69-
alignItems="baseline"
70-
direction="row"
71-
justifyContent="space-between"
66+
<RequirePermission
67+
isFeatureVisible={organizationPermissions?.viewOrgRoles ?? false}
7268
>
73-
<SettingsHeader
74-
title="Roles"
75-
description="Manage roles for this organization."
76-
/>
77-
</Stack>
69+
<Stack
70+
alignItems="baseline"
71+
direction="row"
72+
justifyContent="space-between"
73+
>
74+
<SettingsHeader
75+
title="Roles"
76+
description="Manage roles for this organization."
77+
/>
78+
</Stack>
7879

79-
<CustomRolesPageView
80-
builtInRoles={builtInRoles}
81-
customRoles={customRoles}
82-
onDeleteRole={setRoleToDelete}
83-
canAssignOrgRole={organizationPermissions.assignOrgRoles}
84-
canCreateOrgRole={organizationPermissions.createOrgRoles}
85-
isCustomRolesEnabled={isCustomRolesEnabled}
86-
/>
80+
<CustomRolesPageView
81+
builtInRoles={builtInRoles}
82+
customRoles={customRoles}
83+
onDeleteRole={setRoleToDelete}
84+
canAssignOrgRole={organizationPermissions?.assignOrgRoles ?? false}
85+
canCreateOrgRole={organizationPermissions?.createOrgRoles ?? false}
86+
isCustomRolesEnabled={isCustomRolesEnabled}
87+
/>
8788

88-
<DeleteDialog
89-
key={roleToDelete?.name}
90-
isOpen={roleToDelete !== undefined}
91-
confirmLoading={deleteRoleMutation.isLoading}
92-
name={roleToDelete?.name ?? ""}
93-
entity="role"
94-
onCancel={() => setRoleToDelete(undefined)}
95-
onConfirm={async () => {
96-
try {
97-
if (roleToDelete) {
98-
await deleteRoleMutation.mutateAsync(roleToDelete.name);
89+
<DeleteDialog
90+
key={roleToDelete?.name}
91+
isOpen={roleToDelete !== undefined}
92+
confirmLoading={deleteRoleMutation.isLoading}
93+
name={roleToDelete?.name ?? ""}
94+
entity="role"
95+
onCancel={() => setRoleToDelete(undefined)}
96+
onConfirm={async () => {
97+
try {
98+
if (roleToDelete) {
99+
await deleteRoleMutation.mutateAsync(roleToDelete.name);
100+
}
101+
setRoleToDelete(undefined);
102+
await organizationRolesQuery.refetch();
103+
displaySuccess("Custom role deleted successfully!");
104+
} catch (error) {
105+
displayError(
106+
getErrorMessage(error, "Failed to delete custom role"),
107+
);
99108
}
100-
setRoleToDelete(undefined);
101-
await organizationRolesQuery.refetch();
102-
displaySuccess("Custom role deleted successfully!");
103-
} catch (error) {
104-
displayError(
105-
getErrorMessage(error, "Failed to delete custom role"),
106-
);
107-
}
108-
}}
109-
/>
110-
</RequirePermission>
109+
}}
110+
/>
111+
</RequirePermission>
112+
</>
111113
);
112114
};
113115

site/src/pages/OrganizationSettingsPage/IdpSyncPage/IdpSyncPage.tsx

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
import { getErrorMessage } from "api/errors";
2-
import { groupsByOrganization } from "api/queries/groups";
1+
import {getErrorMessage} from "api/errors";
2+
import {groupsByOrganization} from "api/queries/groups";
33
import {
44
groupIdpSyncSettings,
55
organizationIdpSyncClaimFieldValues,
66
patchGroupSyncSettings,
77
patchRoleSyncSettings,
88
roleIdpSyncSettings,
99
} from "api/queries/organizations";
10-
import { organizationRoles } from "api/queries/roles";
11-
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
12-
import { EmptyState } from "components/EmptyState/EmptyState";
13-
import { displayError } from "components/GlobalSnackbar/utils";
14-
import { displaySuccess } from "components/GlobalSnackbar/utils";
15-
import { Link } from "components/Link/Link";
16-
import { Paywall } from "components/Paywall/Paywall";
17-
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
18-
import { useOrganizationSettings } from "modules/management/OrganizationSettingsLayout";
19-
import { type FC, useEffect, useState } from "react";
20-
import { Helmet } from "react-helmet-async";
21-
import { useMutation, useQueries, useQuery, useQueryClient } from "react-query";
22-
import { useParams, useSearchParams } from "react-router-dom";
23-
import { docs } from "utils/docs";
24-
import { pageTitle } from "utils/page";
10+
import {organizationRoles} from "api/queries/roles";
11+
import {ChooseOne, Cond} from "components/Conditionals/ChooseOne";
12+
import {EmptyState} from "components/EmptyState/EmptyState";
13+
import {displayError, displaySuccess} from "components/GlobalSnackbar/utils";
14+
import {Link} from "components/Link/Link";
15+
import {Paywall} from "components/Paywall/Paywall";
16+
import {useFeatureVisibility} from "modules/dashboard/useFeatureVisibility";
17+
import {useOrganizationSettings} from "modules/management/OrganizationSettingsLayout";
18+
import {RequirePermission} from "modules/permissions/RequirePermission";
19+
import {type FC, useEffect, useState} from "react";
20+
import {Helmet} from "react-helmet-async";
21+
import {useMutation, useQueries, useQuery, useQueryClient} from "react-query";
22+
import {useParams, useSearchParams} from "react-router-dom";
23+
import {docs} from "utils/docs";
24+
import {pageTitle} from "utils/page";
2525
import IdpSyncPageView from "./IdpSyncPageView";
2626

2727
export const IdpSyncPage: FC = () => {
@@ -31,8 +31,7 @@ export const IdpSyncPage: FC = () => {
3131
const { organization: organizationName } = useParams() as {
3232
organization: string;
3333
};
34-
const { organizations } = useOrganizationSettings();
35-
const organization = organizations?.find((o) => o.name === organizationName);
34+
const { organization, organizationPermissions } = useOrganizationSettings();
3635
const [groupField, setGroupField] = useState("");
3736
const [roleField, setRoleField] = useState("");
3837

@@ -80,6 +79,23 @@ export const IdpSyncPage: FC = () => {
8079
return <EmptyState message="Organization not found" />;
8180
}
8281

82+
const helmet = (
83+
<Helmet>
84+
<title>
85+
{pageTitle("IdP Sync", organization.display_name || organization.name)}
86+
</title>
87+
</Helmet>
88+
);
89+
90+
if (!organizationPermissions?.viewIdpSyncSettings) {
91+
return (
92+
<>
93+
{helmet}
94+
<RequirePermission isFeatureVisible={false} />
95+
</>
96+
);
97+
}
98+
8399
const patchGroupSyncSettingsMutation = useMutation(
84100
patchGroupSyncSettings(organizationName, queryClient),
85101
);
@@ -103,9 +119,7 @@ export const IdpSyncPage: FC = () => {
103119

104120
return (
105121
<>
106-
<Helmet>
107-
<title>{pageTitle("IdP Sync")}</title>
108-
</Helmet>
122+
{helmet}
109123

110124
<div className="flex flex-col gap-12">
111125
<header className="flex flex-row items-baseline justify-between">

0 commit comments

Comments
 (0)
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