Skip to content

Commit 616d8ab

Browse files
committed
feat(site): add descriptions for each auth method to the selection menu
1 parent 306615c commit 616d8ab

File tree

1 file changed

+88
-58
lines changed

1 file changed

+88
-58
lines changed

site/src/components/CreateUserForm/CreateUserForm.tsx

Lines changed: 88 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ import { Stack } from "../Stack/Stack"
1414
import { ErrorAlert } from "components/Alert/ErrorAlert"
1515
import { hasApiFieldErrors, isApiError } from "api/errors"
1616
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"
20+
import { Link as RouterLink } from "react-router-dom"
1721

1822
export const Language = {
1923
emailLabel: "Email",
@@ -26,6 +30,38 @@ export const Language = {
2630
cancel: "Cancel",
2731
}
2832

33+
export const authMethodLanguage = {
34+
password: {
35+
displayName: "Password",
36+
description: "Use an email address and password to login",
37+
},
38+
oidc: {
39+
displayName: "OpenID Connect",
40+
description: "Use an OpenID Connect provider for authentication",
41+
},
42+
github: {
43+
displayName: "Github",
44+
description: "Use Github OAuth for authentication",
45+
},
46+
none: {
47+
displayName: "None",
48+
description: (
49+
<>
50+
Disable authentication for this user (See the{" "}
51+
<Link
52+
component={RouterLink}
53+
target="_blank"
54+
rel="noopener"
55+
to="https://coder.com/docs/v2/latest/admin/auth#disable-built-in-authentication"
56+
>
57+
documentation
58+
</Link>{" "}
59+
for more details)
60+
</>
61+
),
62+
},
63+
}
64+
2965
export interface CreateUserFormProps {
3066
onSubmit: (user: TypesGen.CreateUserRequest) => void
3167
onCancel: () => void
@@ -46,22 +82,9 @@ const validationSchema = Yup.object({
4682
otherwise: (schema) => schema,
4783
}),
4884
username: nameValidator(Language.usernameLabel),
85+
login_type: Yup.string().oneOf(Object.keys(authMethodLanguage)),
4986
})
5087

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-
6588
export const CreateUserForm: FC<
6689
React.PropsWithChildren<CreateUserFormProps>
6790
> = ({ onSubmit, onCancel, error, isLoading, myOrgId, authMethods }) => {
@@ -73,7 +96,7 @@ export const CreateUserForm: FC<
7396
username: "",
7497
organization_id: myOrgId,
7598
disable_login: false,
76-
login_type: "password",
99+
login_type: "",
77100
},
78101
validationSchema,
79102
onSubmit,
@@ -83,41 +106,34 @@ export const CreateUserForm: FC<
83106
error,
84107
)
85108

109+
const styles = useStyles()
110+
// This, unfortunately, cannot be an actual component because mui requires
111+
// that all `MenuItem`s but be direct children of the `Select` the belong to
112+
const authMethodSelect = (value: keyof typeof authMethodLanguage) => {
113+
const language = authMethodLanguage[value]
114+
return (
115+
<MenuItem key={value} id={"item-" + value} value={value}>
116+
<Stack spacing={0} maxWidth={400}>
117+
{language.displayName}
118+
<span className={styles.labelDescription}>
119+
{language.description}
120+
</span>
121+
</Stack>
122+
</MenuItem>
123+
)
124+
}
125+
86126
const methods = []
87127
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-
)
128+
methods.push(authMethodSelect("password"))
95129
}
96130
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-
)
131+
methods.push(authMethodSelect("oidc"))
104132
}
105133
if (authMethods?.github.enabled) {
106-
methods.push(
107-
authMethodSelect(
108-
"Github",
109-
"github",
110-
"Uses github oauth to authenticate the user.",
111-
),
112-
)
134+
methods.push(authMethodSelect("github"))
113135
}
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-
)
136+
methods.push(authMethodSelect("none"))
121137

122138
return (
123139
<FullPageForm title="Create user">
@@ -141,21 +157,6 @@ export const CreateUserForm: FC<
141157
fullWidth
142158
label={Language.emailLabel}
143159
/>
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-
/>
159160
<TextField
160161
{...getFieldHelpers(
161162
"login_type",
@@ -172,12 +173,41 @@ export const CreateUserForm: FC<
172173
}
173174
await form.setFieldValue("login_type", e.target.value)
174175
}}
176+
SelectProps={{
177+
renderValue: (selected: unknown) =>
178+
authMethodLanguage[selected as keyof typeof authMethodLanguage]
179+
?.displayName ?? "",
180+
}}
175181
>
176182
{methods}
177183
</TextField>
184+
<TextField
185+
{...getFieldHelpers(
186+
"password",
187+
form.values.login_type === "password"
188+
? ""
189+
: "No password required for this login type",
190+
)}
191+
autoComplete="current-password"
192+
fullWidth
193+
id="password"
194+
data-testid="password-input"
195+
disabled={form.values.login_type !== "password"}
196+
label={Language.passwordLabel}
197+
type="password"
198+
/>
178199
</Stack>
179200
<FormFooter onCancel={onCancel} isLoading={isLoading} />
180201
</form>
181202
</FullPageForm>
182203
)
183204
}
205+
206+
const useStyles = makeStyles<Theme>((theme) => ({
207+
labelDescription: {
208+
fontSize: 14,
209+
color: theme.palette.text.secondary,
210+
wordWrap: "normal",
211+
whiteSpace: "break-spaces",
212+
},
213+
}))

0 commit comments

Comments
 (0)