Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit323559b

Browse files
authored
feat: show warning on unrecognized idp group and role mapping claims (#16485)
1 parent8a3a79f commit323559b

File tree

9 files changed

+191
-65
lines changed

9 files changed

+191
-65
lines changed

‎site/src/api/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -804,7 +804,7 @@ class ApiMethods {
804804
)=>{
805805
constparams=newURLSearchParams();
806806
params.set("claimField",field);
807-
constresponse=awaitthis.axios.get<TypesGen.Response>(
807+
constresponse=awaitthis.axios.get<readonlystring[]>(
808808
`/api/v2/organizations/${organization}/settings/idpsync/field-values?${params}`,
809809
);
810810
returnresponse.data;

‎site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPageView.stories.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
importtype{Meta,StoryObj}from"@storybook/react";
2-
import{userEvent,within}from"@storybook/test";
2+
import{expect,userEvent,within}from"@storybook/test";
33
import{
44
MockOrganization,
55
MockOrganization2,
@@ -45,10 +45,16 @@ export const MissingGroups: Story = {
4545
},
4646
};
4747

48-
exportconstMissingClaim:Story={
48+
exportconstMissingClaims:Story={
4949
args:{
5050
claimFieldValues:[],
5151
},
52+
play:async({ canvasElement})=>{
53+
constuser=userEvent.setup();
54+
constwarning=canvasElement.querySelector(".lucide-triangle-alert")!;
55+
expect(warning).not.toBe(null);
56+
awaituser.hover(warning);
57+
},
5258
};
5359

5460
exportconstAssignDefaultOrgWarningDialog:Story={

‎site/src/pages/DeploymentSettingsPage/IdpOrgSyncPage/IdpOrgSyncPageView.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import{TooltipProvider}from"@radix-ui/react-tooltip";
21
importtype{
32
Organization,
43
OrganizationSyncSettings,
@@ -30,7 +29,6 @@ import {
3029
typeOption,
3130
}from"components/MultiSelectCombobox/MultiSelectCombobox";
3231
import{Spinner}from"components/Spinner/Spinner";
33-
import{Stack}from"components/Stack/Stack";
3432
import{Switch}from"components/Switch/Switch";
3533
import{
3634
Table,
@@ -42,6 +40,7 @@ import {
4240
import{
4341
Tooltip,
4442
TooltipContent,
43+
TooltipProvider,
4544
TooltipTrigger,
4645
}from"components/Tooltip/Tooltip";
4746
import{useFormik}from"formik";

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

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,14 @@ import {
2222
}from"components/MultiSelectCombobox/MultiSelectCombobox";
2323
import{Spinner}from"components/Spinner/Spinner";
2424
import{Switch}from"components/Switch/Switch";
25+
import{
26+
Tooltip,
27+
TooltipContent,
28+
TooltipProvider,
29+
TooltipTrigger,
30+
}from"components/Tooltip/Tooltip";
2531
import{useFormik}from"formik";
26-
import{Plus,Trash}from"lucide-react";
32+
import{Plus,Trash,TriangleAlert}from"lucide-react";
2733
import{typeFC,useId,useState}from"react";
2834
import{docs}from"utils/docs";
2935
import{isUUID}from"utils/uuid";
@@ -32,16 +38,6 @@ import { ExportPolicyButton } from "./ExportPolicyButton";
3238
import{IdpMappingTable}from"./IdpMappingTable";
3339
import{IdpPillList}from"./IdpPillList";
3440

35-
interfaceIdpGroupSyncFormProps{
36-
groupSyncSettings:GroupSyncSettings;
37-
groupsMap:Map<string,string>;
38-
groups:Group[];
39-
groupMappingCount:number;
40-
legacyGroupMappingCount:number;
41-
organization:Organization;
42-
onSubmit:(data:GroupSyncSettings)=>void;
43-
}
44-
4541
constgroupSyncValidationSchema=Yup.object({
4642
field:Yup.string().trim(),
4743
regex_filter:Yup.string().trim(),
@@ -65,15 +61,27 @@ const groupSyncValidationSchema = Yup.object({
6561
.default({}),
6662
});
6763

68-
exportconstIdpGroupSyncForm=({
64+
interfaceIdpGroupSyncFormProps{
65+
groupSyncSettings:GroupSyncSettings;
66+
claimFieldValues:readonlystring[]|undefined;
67+
groupsMap:Map<string,string>;
68+
groups:Group[];
69+
groupMappingCount:number;
70+
legacyGroupMappingCount:number;
71+
organization:Organization;
72+
onSubmit:(data:GroupSyncSettings)=>void;
73+
}
74+
75+
exportconstIdpGroupSyncForm:FC<IdpGroupSyncFormProps>=({
6976
groupSyncSettings,
77+
claimFieldValues,
7078
groupMappingCount,
7179
legacyGroupMappingCount,
7280
groups,
7381
groupsMap,
7482
organization,
7583
onSubmit,
76-
}:IdpGroupSyncFormProps)=>{
84+
})=>{
7785
constform=useFormik<GroupSyncSettings>({
7886
initialValues:{
7987
field:groupSyncSettings?.field??"",
@@ -270,6 +278,7 @@ export const IdpGroupSyncForm = ({
270278
<GroupRow
271279
key={idpGroup}
272280
idpGroup={idpGroup}
281+
exists={claimFieldValues?.includes(idpGroup)}
273282
coderGroup={getGroupNames(groups)}
274283
onDelete={handleDelete}
275284
/>
@@ -288,6 +297,7 @@ export const IdpGroupSyncForm = ({
288297
<GroupRow
289298
key={groupId}
290299
idpGroup={idpGroup}
300+
exists={claimFieldValues?.includes(idpGroup)}
291301
coderGroup={getGroupNames([groupId])}
292302
onDelete={handleDelete}
293303
/>
@@ -303,17 +313,48 @@ export const IdpGroupSyncForm = ({
303313

304314
interfaceGroupRowProps{
305315
idpGroup:string;
316+
exists:boolean|undefined;
306317
coderGroup:readonlystring[];
307318
onDelete:(idpOrg:string)=>void;
308319
}
309320

310-
constGroupRow:FC<GroupRowProps>=({ idpGroup, coderGroup, onDelete})=>{
321+
constGroupRow:FC<GroupRowProps>=({
322+
idpGroup,
323+
exists=true,
324+
coderGroup,
325+
onDelete,
326+
})=>{
311327
return(
312328
<TableRowdata-testid={`group-${idpGroup}`}>
313-
<TableCell>{idpGroup}</TableCell>
329+
<TableCell>
330+
<divclassName="flex flex-row items-center gap-2 text-content-primary">
331+
{idpGroup}
332+
{!exists&&(
333+
<TooltipProvider>
334+
<Tooltip>
335+
<TooltipTriggerasChild>
336+
<TriangleAlertclassName="size-icon-xs cursor-pointer text-content-warning"/>
337+
</TooltipTrigger>
338+
<TooltipContent
339+
align="start"
340+
alignOffset={-8}
341+
sideOffset={8}
342+
className="p-2 text-xs text-content-secondary max-w-sm"
343+
>
344+
This value has not be seen in the specified claim field
345+
before. You might want to check your IdP configuration and
346+
ensure that this value is not misspelled.
347+
</TooltipContent>
348+
</Tooltip>
349+
</TooltipProvider>
350+
)}
351+
</div>
352+
</TableCell>
353+
314354
<TableCell>
315355
<IdpPillListroles={coderGroup}/>
316356
</TableCell>
357+
317358
<TableCell>
318359
<Button
319360
variant="outline"

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

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,20 @@ import {
99
typeOption,
1010
}from"components/MultiSelectCombobox/MultiSelectCombobox";
1111
import{Spinner}from"components/Spinner/Spinner";
12+
import{
13+
Tooltip,
14+
TooltipContent,
15+
TooltipProvider,
16+
TooltipTrigger,
17+
}from"components/Tooltip/Tooltip";
1218
import{useFormik}from"formik";
13-
import{Plus,Trash}from"lucide-react";
19+
import{Plus,Trash,TriangleAlert}from"lucide-react";
1420
import{typeFC,useId,useState}from"react";
1521
import*asYupfrom"yup";
1622
import{ExportPolicyButton}from"./ExportPolicyButton";
1723
import{IdpMappingTable}from"./IdpMappingTable";
1824
import{IdpPillList}from"./IdpPillList";
1925

20-
interfaceIdpRoleSyncFormProps{
21-
roleSyncSettings:RoleSyncSettings;
22-
roleMappingCount:number;
23-
organization:Organization;
24-
roles:Role[];
25-
onSubmit:(data:RoleSyncSettings)=>void;
26-
}
27-
2826
constroleSyncValidationSchema=Yup.object({
2927
field:Yup.string().trim(),
3028
regex_filter:Yup.string().trim(),
@@ -48,13 +46,23 @@ const roleSyncValidationSchema = Yup.object({
4846
.default({}),
4947
});
5048

51-
exportconstIdpRoleSyncForm=({
49+
interfaceIdpRoleSyncFormProps{
50+
roleSyncSettings:RoleSyncSettings;
51+
claimFieldValues:readonlystring[]|undefined;
52+
roleMappingCount:number;
53+
organization:Organization;
54+
roles:Role[];
55+
onSubmit:(data:RoleSyncSettings)=>void;
56+
}
57+
58+
exportconstIdpRoleSyncForm:FC<IdpRoleSyncFormProps>=({
5259
roleSyncSettings,
60+
claimFieldValues,
5361
roleMappingCount,
5462
organization,
5563
roles,
5664
onSubmit,
57-
}:IdpRoleSyncFormProps)=>{
65+
})=>{
5866
constform=useFormik<RoleSyncSettings>({
5967
initialValues:{
6068
field:roleSyncSettings?.field??"",
@@ -210,6 +218,7 @@ export const IdpRoleSyncForm = ({
210218
<RoleRow
211219
key={idpRole}
212220
idpRole={idpRole}
221+
exists={claimFieldValues?.includes(idpRole)}
213222
coderRoles={roles}
214223
onDelete={handleDelete}
215224
/>
@@ -222,17 +231,48 @@ export const IdpRoleSyncForm = ({
222231

223232
interfaceRoleRowProps{
224233
idpRole:string;
234+
exists:boolean|undefined;
225235
coderRoles:readonlystring[];
226236
onDelete:(idpOrg:string)=>void;
227237
}
228238

229-
constRoleRow:FC<RoleRowProps>=({ idpRole, coderRoles, onDelete})=>{
239+
constRoleRow:FC<RoleRowProps>=({
240+
idpRole,
241+
exists=true,
242+
coderRoles,
243+
onDelete,
244+
})=>{
230245
return(
231246
<TableRowdata-testid={`role-${idpRole}`}>
232-
<TableCell>{idpRole}</TableCell>
247+
<TableCell>
248+
<divclassName="flex flex-row items-center gap-2 text-content-primary">
249+
{idpRole}
250+
{!exists&&(
251+
<TooltipProvider>
252+
<Tooltip>
253+
<TooltipTriggerasChild>
254+
<TriangleAlertclassName="size-icon-xs cursor-pointer text-content-warning"/>
255+
</TooltipTrigger>
256+
<TooltipContent
257+
align="start"
258+
alignOffset={-8}
259+
sideOffset={8}
260+
className="p-2 text-xs text-content-secondary max-w-sm"
261+
>
262+
This value has not be seen in the specified claim field
263+
before. You might want to check your IdP configuration and
264+
ensure that this value is not misspelled.
265+
</TooltipContent>
266+
</Tooltip>
267+
</TooltipProvider>
268+
)}
269+
</div>
270+
</TableCell>
271+
233272
<TableCell>
234273
<IdpPillListroles={coderRoles}/>
235274
</TableCell>
275+
236276
<TableCell>
237277
<Button
238278
variant="outline"

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { getErrorMessage } from "api/errors";
22
import{groupsByOrganization}from"api/queries/groups";
33
import{
44
groupIdpSyncSettings,
5+
organizationIdpSyncClaimFieldValues,
56
patchGroupSyncSettings,
67
patchRoleSyncSettings,
78
roleIdpSyncSettings,
@@ -17,8 +18,8 @@ import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
1718
import{useOrganizationSettings}from"modules/management/OrganizationSettingsLayout";
1819
importtype{FC}from"react";
1920
import{Helmet}from"react-helmet-async";
20-
import{useMutation,useQueries,useQueryClient}from"react-query";
21-
import{useParams}from"react-router-dom";
21+
import{useMutation,useQueries,useQuery,useQueryClient}from"react-query";
22+
import{useParams,useSearchParams}from"react-router-dom";
2223
import{docs}from"utils/docs";
2324
import{pageTitle}from"utils/page";
2425
importIdpSyncPageViewfrom"./IdpSyncPageView";
@@ -47,6 +48,19 @@ export const IdpSyncPage: FC = () => {
4748
],
4849
});
4950

51+
const[searchParams]=useSearchParams();
52+
consttab=searchParams.get("tab")||"groups";
53+
constfield=
54+
tab==="groups"
55+
?groupIdpSyncSettingsQuery.data?.field
56+
:roleIdpSyncSettingsQuery.data?.field;
57+
58+
constfieldValuesQuery=useQuery(
59+
field
60+
?organizationIdpSyncClaimFieldValues(organizationName,field)
61+
:{enabled:false},
62+
);
63+
5064
if(!organization){
5165
return<EmptyStatemessage="Organization not found"/>;
5266
}
@@ -99,8 +113,10 @@ export const IdpSyncPage: FC = () => {
99113
</Cond>
100114
<Cond>
101115
<IdpSyncPageView
116+
tab={tab}
102117
groupSyncSettings={groupIdpSyncSettingsQuery.data}
103118
roleSyncSettings={roleIdpSyncSettingsQuery.data}
119+
claimFieldValues={fieldValuesQuery.data}
104120
groups={groupsQuery.data}
105121
groupsMap={groupsMap}
106122
roles={rolesQuery.data}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp