@@ -14,6 +14,9 @@ import { Stack } from "../Stack/Stack"
14
14
import { ErrorAlert } from "components/Alert/ErrorAlert"
15
15
import { hasApiFieldErrors , isApiError } from "api/errors"
16
16
import MenuItem from "@mui/material/MenuItem"
17
+ import { makeStyles } from "@mui/styles"
18
+ import { Theme } from "@mui/material/styles"
19
+ import Link from "@mui/material/Link"
17
20
18
21
export const Language = {
19
22
emailLabel : "Email" ,
@@ -26,6 +29,37 @@ export const Language = {
26
29
cancel : "Cancel" ,
27
30
}
28
31
32
+ export const authMethodLanguage = {
33
+ password : {
34
+ displayName : "Password" ,
35
+ description : "Use an email address and password to login" ,
36
+ } ,
37
+ oidc : {
38
+ displayName : "OpenID Connect" ,
39
+ description : "Use an OpenID Connect provider for authentication" ,
40
+ } ,
41
+ github : {
42
+ displayName : "Github" ,
43
+ description : "Use Github OAuth for authentication" ,
44
+ } ,
45
+ none : {
46
+ displayName : "None" ,
47
+ description : (
48
+ < >
49
+ Disable authentication for this user (See the{ " " }
50
+ < Link
51
+ target = "_blank"
52
+ rel = "noopener"
53
+ href = "https://coder.com/docs/v2/latest/admin/auth#disable-built-in-authentication"
54
+ >
55
+ documentation
56
+ </ Link > { " " }
57
+ for more details)
58
+ </ >
59
+ ) ,
60
+ } ,
61
+ }
62
+
29
63
export interface CreateUserFormProps {
30
64
onSubmit : ( user : TypesGen . CreateUserRequest ) => void
31
65
onCancel : ( ) => void
@@ -46,22 +80,9 @@ const validationSchema = Yup.object({
46
80
otherwise : ( schema ) => schema ,
47
81
} ) ,
48
82
username : nameValidator ( Language . usernameLabel ) ,
83
+ login_type : Yup . string ( ) . oneOf ( Object . keys ( authMethodLanguage ) ) ,
49
84
} )
50
85
51
- const authMethodSelect = (
52
- title : string ,
53
- value : string ,
54
- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- future will use this
55
- description : string ,
56
- ) => {
57
- return (
58
- < MenuItem key = "value" id = { "item-" + value } value = { value } >
59
- { title }
60
- { /* TODO: Add description */ }
61
- </ MenuItem >
62
- )
63
- }
64
-
65
86
export const CreateUserForm : FC <
66
87
React . PropsWithChildren < CreateUserFormProps >
67
88
> = ( { onSubmit, onCancel, error, isLoading, myOrgId, authMethods } ) => {
@@ -73,7 +94,7 @@ export const CreateUserForm: FC<
73
94
username : "" ,
74
95
organization_id : myOrgId ,
75
96
disable_login : false ,
76
- login_type : "password " ,
97
+ login_type : "" ,
77
98
} ,
78
99
validationSchema,
79
100
onSubmit,
@@ -83,41 +104,14 @@ export const CreateUserForm: FC<
83
104
error ,
84
105
)
85
106
86
- const methods = [ ]
87
- if ( authMethods ?. password . enabled ) {
88
- methods . push (
89
- authMethodSelect (
90
- "Password" ,
91
- "password" ,
92
- "User can provide their email and password to login." ,
93
- ) ,
94
- )
95
- }
96
- if ( authMethods ?. oidc . enabled ) {
97
- methods . push (
98
- authMethodSelect (
99
- "OpenID Connect" ,
100
- "oidc" ,
101
- "Uses an OpenID connect provider to authenticate the user." ,
102
- ) ,
103
- )
104
- }
105
- if ( authMethods ?. github . enabled ) {
106
- methods . push (
107
- authMethodSelect (
108
- "Github" ,
109
- "github" ,
110
- "Uses github oauth to authenticate the user." ,
111
- ) ,
112
- )
113
- }
114
- methods . push (
115
- authMethodSelect (
116
- "None" ,
117
- "none" ,
118
- "User authentication is disabled. This user an only be used if an api token is created for them." ,
119
- ) ,
120
- )
107
+ const styles = useStyles ( )
108
+
109
+ const methods = [
110
+ authMethods ?. password . enabled && "password" ,
111
+ authMethods ?. oidc . enabled && "oidc" ,
112
+ authMethods ?. github . enabled && "github" ,
113
+ "none" ,
114
+ ] . filter ( Boolean ) as Array < keyof typeof authMethodLanguage >
121
115
122
116
return (
123
117
< FullPageForm title = "Create user" >
@@ -141,21 +135,6 @@ export const CreateUserForm: FC<
141
135
fullWidth
142
136
label = { Language . emailLabel }
143
137
/>
144
- < TextField
145
- { ...getFieldHelpers (
146
- "password" ,
147
- form . values . login_type === "password"
148
- ? ""
149
- : "No password required for this login type" ,
150
- ) }
151
- autoComplete = "current-password"
152
- fullWidth
153
- id = "password"
154
- data-testid = "password-input"
155
- disabled = { form . values . login_type !== "password" }
156
- label = { Language . passwordLabel }
157
- type = "password"
158
- />
159
138
< TextField
160
139
{ ...getFieldHelpers (
161
140
"login_type" ,
@@ -172,12 +151,53 @@ export const CreateUserForm: FC<
172
151
}
173
152
await form . setFieldValue ( "login_type" , e . target . value )
174
153
} }
154
+ SelectProps = { {
155
+ renderValue : ( selected : unknown ) =>
156
+ authMethodLanguage [ selected as keyof typeof authMethodLanguage ]
157
+ ?. displayName ?? "" ,
158
+ } }
175
159
>
176
- { methods }
160
+ { methods . map ( ( value ) => {
161
+ const language = authMethodLanguage [ value ]
162
+ return (
163
+ < MenuItem key = { value } id = { "item-" + value } value = { value } >
164
+ < Stack spacing = { 0 } maxWidth = { 400 } >
165
+ { language . displayName }
166
+ < span className = { styles . labelDescription } >
167
+ { language . description }
168
+ </ span >
169
+ </ Stack >
170
+ </ MenuItem >
171
+ )
172
+ } ) }
177
173
</ TextField >
174
+ < TextField
175
+ { ...getFieldHelpers (
176
+ "password" ,
177
+ form . values . login_type === "password"
178
+ ? ""
179
+ : "No password required for this login type" ,
180
+ ) }
181
+ autoComplete = "current-password"
182
+ fullWidth
183
+ id = "password"
184
+ data-testid = "password-input"
185
+ disabled = { form . values . login_type !== "password" }
186
+ label = { Language . passwordLabel }
187
+ type = "password"
188
+ />
178
189
</ Stack >
179
190
< FormFooter onCancel = { onCancel } isLoading = { isLoading } />
180
191
</ form >
181
192
</ FullPageForm >
182
193
)
183
194
}
195
+
196
+ const useStyles = makeStyles < Theme > ( ( theme ) => ( {
197
+ labelDescription : {
198
+ fontSize : 14 ,
199
+ color : theme . palette . text . secondary ,
200
+ wordWrap : "normal" ,
201
+ whiteSpace : "break-spaces" ,
202
+ } ,
203
+ } ) )
0 commit comments