Skip to content

Commit 894c758

Browse files
authored
feat: display legacy idp mappings in idp sync settings (coder#14866)
Closes coder#14788
1 parent 33988fe commit 894c758

File tree

3 files changed

+92
-16
lines changed

3 files changed

+92
-16
lines changed

site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.stories.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
MockGroup2,
55
MockGroupSyncSettings,
66
MockGroupSyncSettings2,
7+
MockLegacyMappingGroupSyncSettings,
78
MockOrganization,
89
MockRoleSyncSettings,
910
} from "testHelpers/entities";
@@ -74,3 +75,14 @@ export const MissingGroups: Story = {
7475
error: undefined,
7576
},
7677
};
78+
79+
export const WithLegacyMapping: Story = {
80+
args: {
81+
groupSyncSettings: MockLegacyMappingGroupSyncSettings,
82+
roleSyncSettings: MockRoleSyncSettings,
83+
groups: [MockGroup, MockGroup2],
84+
groupsMap,
85+
organization: MockOrganization,
86+
error: undefined,
87+
},
88+
};

site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPageView.tsx

Lines changed: 71 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Interpolation, Theme } from "@emotion/react";
22
import LaunchOutlined from "@mui/icons-material/LaunchOutlined";
33
import Button from "@mui/material/Button";
4+
import Link from "@mui/material/Link";
45
import Skeleton from "@mui/material/Skeleton";
56
import Table from "@mui/material/Table";
67
import TableBody from "@mui/material/TableBody";
@@ -17,6 +18,13 @@ import type {
1718
import { ErrorAlert } from "components/Alert/ErrorAlert";
1819
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
1920
import { EmptyState } from "components/EmptyState/EmptyState";
21+
import {
22+
HelpTooltip,
23+
HelpTooltipContent,
24+
HelpTooltipText,
25+
HelpTooltipTitle,
26+
HelpTooltipTrigger,
27+
} from "components/HelpTooltip/HelpTooltip";
2028
import { Loader } from "components/Loader/Loader";
2129
import { Stack } from "components/Stack/Stack";
2230
import { StatusIndicator } from "components/StatusIndicator/StatusIndicator";
@@ -60,6 +68,9 @@ export const IdpSyncPageView: FC<IdpSyncPageViewProps> = ({
6068
const groupMappingCount = groupSyncSettings?.mapping
6169
? Object.entries(groupSyncSettings.mapping).length
6270
: 0;
71+
const legacyGroupMappingCount = groupSyncSettings?.legacy_group_name_mapping
72+
? Object.entries(groupSyncSettings.legacy_group_name_mapping).length
73+
: 0;
6374
const roleMappingCount = roleSyncSettings?.mapping
6475
? Object.entries(roleSyncSettings.mapping).length
6576
: 0;
@@ -88,22 +99,22 @@ export const IdpSyncPageView: FC<IdpSyncPageViewProps> = ({
8899
{tab === "groups" ? (
89100
<>
90101
<div css={styles.fields}>
91-
<Stack direction={"row"} alignItems={"center"} spacing={6}>
102+
<Stack direction="row" alignItems="center" spacing={6}>
92103
<IdpField
93-
name={"Sync Field"}
104+
name="Sync Field"
94105
fieldText={groupSyncSettings?.field}
95106
showDisabled
96107
/>
97108
<IdpField
98-
name={"Regex Filter"}
109+
name="Regex Filter"
99110
fieldText={
100111
typeof groupSyncSettings?.regex_filter === "string"
101112
? groupSyncSettings.regex_filter
102113
: "none"
103114
}
104115
/>
105116
<IdpField
106-
name={"Auto Create"}
117+
name="Auto Create"
107118
fieldText={
108119
groupSyncSettings?.field
109120
? String(groupSyncSettings?.auto_create_missing_groups)
@@ -126,10 +137,7 @@ export const IdpSyncPageView: FC<IdpSyncPageViewProps> = ({
126137
/>
127138
</Stack>
128139
<Stack spacing={6}>
129-
<IdpMappingTable
130-
type="Group"
131-
isEmpty={Boolean(groupMappingCount === 0)}
132-
>
140+
<IdpMappingTable type="Group" isEmpty={groupMappingCount === 0}>
133141
{groupSyncSettings?.mapping &&
134142
Object.entries(groupSyncSettings.mapping)
135143
.sort()
@@ -141,13 +149,32 @@ export const IdpSyncPageView: FC<IdpSyncPageViewProps> = ({
141149
/>
142150
))}
143151
</IdpMappingTable>
152+
{groupSyncSettings?.legacy_group_name_mapping && (
153+
<section>
154+
<LegacyGroupSyncHeader />
155+
<IdpMappingTable
156+
type="Group"
157+
isEmpty={legacyGroupMappingCount === 0}
158+
>
159+
{Object.entries(groupSyncSettings.legacy_group_name_mapping)
160+
.sort()
161+
.map(([idpGroup, groupId]) => (
162+
<GroupRow
163+
key={idpGroup}
164+
idpGroup={idpGroup}
165+
coderGroup={getGroupNames([groupId])}
166+
/>
167+
))}
168+
</IdpMappingTable>
169+
</section>
170+
)}
144171
</Stack>
145172
</>
146173
) : (
147174
<>
148175
<div css={styles.fields}>
149176
<IdpField
150-
name={"Sync Field"}
177+
name="Sync Field"
151178
fieldText={roleSyncSettings?.field}
152179
showDisabled
153180
/>
@@ -165,10 +192,7 @@ export const IdpSyncPageView: FC<IdpSyncPageViewProps> = ({
165192
type="roles"
166193
/>
167194
</Stack>
168-
<IdpMappingTable
169-
type="Role"
170-
isEmpty={Boolean(roleMappingCount === 0)}
171-
>
195+
<IdpMappingTable type="Role" isEmpty={roleMappingCount === 0}>
172196
{roleSyncSettings?.mapping &&
173197
Object.entries(roleSyncSettings.mapping)
174198
.sort()
@@ -268,7 +292,7 @@ const IdpMappingTable: FC<IdpMappingTableProps> = ({
268292
<Table>
269293
<TableHead>
270294
<TableRow>
271-
<TableCell width="45%">Idp {type}</TableCell>
295+
<TableCell width="45%">IdP {type}</TableCell>
272296
<TableCell width="55%">Coder {type}</TableCell>
273297
</TableRow>
274298
</TableHead>
@@ -359,12 +383,43 @@ const TableLoader = () => {
359383
);
360384
};
361385

386+
const LegacyGroupSyncHeader: FC = () => {
387+
return (
388+
<h4
389+
css={{
390+
fontSize: 20,
391+
fontWeight: 500,
392+
}}
393+
>
394+
<Stack direction="row" alignItems="end" spacing={1}>
395+
<span>Legacy Group Sync Settings</span>
396+
<HelpTooltip>
397+
<HelpTooltipTrigger />
398+
<HelpTooltipContent>
399+
<HelpTooltipTitle>Legacy Group Sync Settings</HelpTooltipTitle>
400+
<HelpTooltipText>
401+
These settings were configured using environment variables, and
402+
only apply to the default organization. It is now recommended to
403+
configure IdP sync via the CLI, which enables sync to be
404+
configured for any organization, and for those settings to be
405+
persisted without manually setting environment variables.{" "}
406+
<Link href={docs("/admin/auth#group-sync-enterprise")}>
407+
Learn more&hellip;
408+
</Link>
409+
</HelpTooltipText>
410+
</HelpTooltipContent>
411+
</HelpTooltip>
412+
</Stack>
413+
</h4>
414+
);
415+
};
416+
362417
const styles = {
363-
fieldText: (theme) => ({
418+
fieldText: {
364419
fontFamily: MONOSPACE_FONT_FAMILY,
365420
whiteSpace: "nowrap",
366421
paddingBottom: ".02rem",
367-
}),
422+
},
368423
fieldLabel: (theme) => ({
369424
color: theme.palette.text.secondary,
370425
}),

site/src/testHelpers/entities.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2618,6 +2618,15 @@ export const MockGroupSyncSettings: TypesGen.GroupSyncSettings = {
26182618
auto_create_missing_groups: false,
26192619
};
26202620

2621+
export const MockLegacyMappingGroupSyncSettings: TypesGen.GroupSyncSettings = {
2622+
...MockGroupSyncSettings,
2623+
mapping: {},
2624+
legacy_group_name_mapping: {
2625+
"idp-group-1": "fbd2116a-8961-4954-87ae-e4575bd29ce0",
2626+
"idp-group-2": "13de3eb4-9b4f-49e7-b0f8-0c3728a0d2e2",
2627+
},
2628+
};
2629+
26212630
export const MockGroupSyncSettings2: TypesGen.GroupSyncSettings = {
26222631
field: "group-test",
26232632
mapping: {

0 commit comments

Comments
 (0)