@@ -8,7 +8,7 @@ import TableCell from "@mui/material/TableCell";
8
8
import TableContainer from "@mui/material/TableContainer" ;
9
9
import TableHead from "@mui/material/TableHead" ;
10
10
import TableRow from "@mui/material/TableRow" ;
11
- import type { Role } from "api/typesGenerated" ;
11
+ import type { OIDCConfig } from "api/typesGenerated" ;
12
12
import { ChooseOne , Cond } from "components/Conditionals/ChooseOne" ;
13
13
import { EmptyState } from "components/EmptyState/EmptyState" ;
14
14
import { Paywall } from "components/Paywall/Paywall" ;
@@ -21,10 +21,10 @@ import type { FC } from "react";
21
21
import { docs } from "utils/docs" ;
22
22
23
23
export type IdpSyncPageViewProps = {
24
- roles : Role [ ] | undefined ;
24
+ oidcConfig : OIDCConfig | undefined ;
25
25
} ;
26
26
27
- export const IdpSyncPageView : FC < IdpSyncPageViewProps > = ( { roles } ) => {
27
+ export const IdpSyncPageView : FC < IdpSyncPageViewProps > = ( { oidcConfig } ) => {
28
28
return (
29
29
< >
30
30
< ChooseOne >
@@ -43,45 +43,93 @@ export const IdpSyncPageView: FC<IdpSyncPageViewProps> = ({ roles }) => {
43
43
< legend css = { styles . legend } > Groups</ legend >
44
44
< Stack direction = { "row" } alignItems = { "center" } spacing = { 3 } >
45
45
< h4 > Sync Field</ h4 >
46
- < p css = { styles . secondary } > groups </ p >
46
+ < p css = { styles . secondary } > { oidcConfig ?. groups_field } </ p >
47
47
< h4 > Regex Filter</ h4 >
48
- < p css = { styles . secondary } > ^Coder-.*$ </ p >
48
+ < p css = { styles . secondary } > { oidcConfig ?. group_regex_filter } </ p >
49
49
< h4 > Auto Create</ h4 >
50
- < p css = { styles . secondary } > false</ p >
50
+ < p css = { styles . secondary } >
51
+ { oidcConfig ?. group_auto_create . toString ( ) }
52
+ </ p >
51
53
</ Stack >
52
54
</ fieldset >
53
55
< fieldset css = { styles . box } >
54
56
< legend css = { styles . legend } > Roles</ legend >
55
57
< Stack direction = { "row" } alignItems = { "center" } spacing = { 3 } >
56
58
< h4 > Sync Field</ h4 >
57
- < p css = { styles . secondary } > roles </ p >
59
+ < p css = { styles . secondary } > { oidcConfig ?. user_role_field } </ p >
58
60
</ Stack >
59
61
</ fieldset >
60
62
</ Stack >
61
- < Stack spacing = { 4 } >
62
- < RoleTable roles = { roles } />
63
- < RoleTable roles = { roles } />
63
+ < Stack spacing = { 6 } >
64
+ < IdpMappingTable
65
+ type = "Role"
66
+ isEmpty = { Boolean (
67
+ ( oidcConfig ?. user_role_mapping &&
68
+ Object . entries ( oidcConfig ?. user_role_mapping ) . length === 0 ) ||
69
+ false ,
70
+ ) }
71
+ >
72
+ < >
73
+ { oidcConfig ?. user_role_mapping &&
74
+ Object . entries ( oidcConfig . user_role_mapping ) . map (
75
+ ( [ idpRole , roles ] ) => (
76
+ < RoleRow
77
+ key = { idpRole }
78
+ idpRole = { idpRole }
79
+ coderRoles = { roles }
80
+ />
81
+ ) ,
82
+ ) }
83
+ </ >
84
+ </ IdpMappingTable >
85
+ < IdpMappingTable
86
+ type = "Group"
87
+ isEmpty = { Boolean (
88
+ ( oidcConfig ?. user_role_mapping &&
89
+ Object . entries ( oidcConfig ?. group_mapping ) . length === 0 ) ||
90
+ false ,
91
+ ) }
92
+ >
93
+ < >
94
+ { oidcConfig ?. user_role_mapping &&
95
+ Object . entries ( oidcConfig . group_mapping ) . map (
96
+ ( [ idpGroup , group ] ) => (
97
+ < GroupRow
98
+ key = { idpGroup }
99
+ idpGroup = { idpGroup }
100
+ coderGroup = { group }
101
+ />
102
+ ) ,
103
+ ) }
104
+ </ >
105
+ </ IdpMappingTable >
64
106
</ Stack >
65
107
</ Cond >
66
108
</ ChooseOne >
67
109
</ >
68
110
) ;
69
111
} ;
70
112
71
- interface RoleTableProps {
72
- roles : Role [ ] | undefined ;
113
+ interface IdpMappingTableProps {
114
+ type : "Role" | "Group" ;
115
+ isEmpty : boolean ;
116
+ children : React . ReactNode ;
73
117
}
74
118
75
- const RoleTable : FC < RoleTableProps > = ( { roles } ) => {
119
+ const IdpMappingTable : FC < IdpMappingTableProps > = ( {
120
+ type,
121
+ isEmpty,
122
+ children,
123
+ } ) => {
76
124
const isLoading = false ;
77
- const isEmpty = Boolean ( roles && roles . length === 0 ) ;
125
+
78
126
return (
79
127
< TableContainer >
80
128
< Table >
81
129
< TableHead >
82
130
< TableRow >
83
- < TableCell width = "45%" > Idp Role </ TableCell >
84
- < TableCell width = "55%" > Coder Role </ TableCell >
131
+ < TableCell width = "45%" > Idp { type } </ TableCell >
132
+ < TableCell width = "55%" > Coder { type } </ TableCell >
85
133
</ TableRow >
86
134
</ TableHead >
87
135
< TableBody >
@@ -94,10 +142,7 @@ const RoleTable: FC<RoleTableProps> = ({ roles }) => {
94
142
< TableRow >
95
143
< TableCell colSpan = { 999 } >
96
144
< EmptyState
97
- message = "No Role Mappings"
98
- description = {
99
- "Configure role sync mappings to manage permissions outside of Coder."
100
- }
145
+ message = { `No ${ type } Mappings` }
101
146
isCompact
102
147
cta = {
103
148
< Button
@@ -106,35 +151,46 @@ const RoleTable: FC<RoleTableProps> = ({ roles }) => {
106
151
href = { docs ( "/admin/auth#group-sync-enterprise" ) }
107
152
target = "_blank"
108
153
>
109
- How to setup IdP role sync
154
+ How to setup IdP { type } sync
110
155
</ Button >
111
156
}
112
157
/>
113
158
</ TableCell >
114
159
</ TableRow >
115
160
</ Cond >
116
161
117
- < Cond >
118
- { roles ?. map ( ( role ) => (
119
- < RoleRow key = { role . name } role = { role } />
120
- ) ) }
121
- </ Cond >
162
+ < Cond > { children } </ Cond >
122
163
</ ChooseOne >
123
164
</ TableBody >
124
165
</ Table >
125
166
</ TableContainer >
126
167
) ;
127
168
} ;
128
169
170
+ interface GroupRowProps {
171
+ idpGroup : string ;
172
+ coderGroup : string ;
173
+ }
174
+
175
+ const GroupRow : FC < GroupRowProps > = ( { idpGroup, coderGroup } ) => {
176
+ return (
177
+ < TableRow data-testid = { `group-${ idpGroup } ` } >
178
+ < TableCell > { idpGroup } </ TableCell >
179
+ < TableCell css = { styles . secondary } > { coderGroup } </ TableCell >
180
+ </ TableRow >
181
+ ) ;
182
+ } ;
183
+
129
184
interface RoleRowProps {
130
- role : Role ;
185
+ idpRole : string ;
186
+ coderRoles : ReadonlyArray < string > ;
131
187
}
132
188
133
- const RoleRow : FC < RoleRowProps > = ( { role } ) => {
189
+ const RoleRow : FC < RoleRowProps > = ( { idpRole , coderRoles } ) => {
134
190
return (
135
- < TableRow data-testid = { `role-${ role . name } ` } >
136
- < TableCell > { role . display_name || role . name } </ TableCell >
137
- < TableCell css = { styles . secondary } > test </ TableCell >
191
+ < TableRow data-testid = { `role-${ idpRole } ` } >
192
+ < TableCell > { idpRole } </ TableCell >
193
+ < TableCell css = { styles . secondary } > coderRoles Placeholder </ TableCell >
138
194
</ TableRow >
139
195
) ;
140
196
} ;
@@ -161,10 +217,10 @@ const styles = {
161
217
secondary : ( theme ) => ( {
162
218
color : theme . palette . text . secondary ,
163
219
} ) ,
164
- fields : ( theme ) => ( {
220
+ fields : ( ) => ( {
165
221
marginBottom : "60px" ,
166
222
} ) ,
167
- legend : ( theme ) => ( {
223
+ legend : ( ) => ( {
168
224
padding : "0px 6px" ,
169
225
fontWeight : 600 ,
170
226
} ) ,
0 commit comments