mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
This allows for a complete sign-up flow: 1. coder login https://dev.coder.com 2. Navigates to /cli-auth 3. Redirects to /login?redirect=%2Fcli-auth 4. User signs in with GitHub 5. User is redirected back to /cli-auth
128 lines
3.9 KiB
TypeScript
128 lines
3.9 KiB
TypeScript
import Button from "@material-ui/core/Button"
|
|
import FormHelperText from "@material-ui/core/FormHelperText"
|
|
import Link from "@material-ui/core/Link"
|
|
import { makeStyles } from "@material-ui/core/styles"
|
|
import TextField from "@material-ui/core/TextField"
|
|
import { FormikContextType, useFormik } from "formik"
|
|
import React from "react"
|
|
import * as Yup from "yup"
|
|
import { AuthMethods } from "../../api/typesGenerated"
|
|
import { getFormHelpers, onChangeTrimmed } from "../../util/formUtils"
|
|
import { Welcome } from "../Welcome/Welcome"
|
|
import { LoadingButton } from "./../LoadingButton/LoadingButton"
|
|
|
|
/**
|
|
* BuiltInAuthFormValues describes a form using built-in (email/password)
|
|
* authentication. This form may not always be present depending on external
|
|
* auth providers available and administrative configurations
|
|
*/
|
|
interface BuiltInAuthFormValues {
|
|
email: string
|
|
password: string
|
|
}
|
|
|
|
export const Language = {
|
|
emailLabel: "Email",
|
|
passwordLabel: "Password",
|
|
emailInvalid: "Please enter a valid email address.",
|
|
emailRequired: "Please enter an email address.",
|
|
authErrorMessage: "Incorrect email or password.",
|
|
methodsErrorMessage: "Unable to fetch auth methods.",
|
|
passwordSignIn: "Sign In",
|
|
githubSignIn: "GitHub",
|
|
}
|
|
|
|
const validationSchema = Yup.object({
|
|
email: Yup.string().trim().email(Language.emailInvalid).required(Language.emailRequired),
|
|
password: Yup.string(),
|
|
})
|
|
|
|
const useStyles = makeStyles((theme) => ({
|
|
loginBtnWrapper: {
|
|
marginTop: theme.spacing(6),
|
|
borderTop: `1px solid ${theme.palette.action.disabled}`,
|
|
paddingTop: theme.spacing(3),
|
|
},
|
|
loginTextField: {
|
|
marginTop: theme.spacing(2),
|
|
},
|
|
submitBtn: {
|
|
marginTop: theme.spacing(2),
|
|
},
|
|
}))
|
|
|
|
export interface SignInFormProps {
|
|
isLoading: boolean
|
|
redirectTo: string
|
|
authErrorMessage?: string
|
|
methodsErrorMessage?: string
|
|
authMethods?: AuthMethods
|
|
onSubmit: ({ email, password }: { email: string; password: string }) => Promise<void>
|
|
}
|
|
|
|
export const SignInForm: React.FC<SignInFormProps> = ({
|
|
authMethods,
|
|
redirectTo,
|
|
isLoading,
|
|
authErrorMessage,
|
|
methodsErrorMessage,
|
|
onSubmit,
|
|
}) => {
|
|
const styles = useStyles()
|
|
|
|
const form: FormikContextType<BuiltInAuthFormValues> = useFormik<BuiltInAuthFormValues>({
|
|
initialValues: {
|
|
email: "",
|
|
password: "",
|
|
},
|
|
validationSchema,
|
|
onSubmit,
|
|
})
|
|
const getFieldHelpers = getFormHelpers<BuiltInAuthFormValues>(form)
|
|
|
|
return (
|
|
<>
|
|
<Welcome />
|
|
<form onSubmit={form.handleSubmit}>
|
|
<TextField
|
|
{...getFieldHelpers("email")}
|
|
onChange={onChangeTrimmed(form)}
|
|
autoFocus
|
|
autoComplete="email"
|
|
className={styles.loginTextField}
|
|
fullWidth
|
|
label={Language.emailLabel}
|
|
type="email"
|
|
variant="outlined"
|
|
/>
|
|
<TextField
|
|
{...getFieldHelpers("password")}
|
|
autoComplete="current-password"
|
|
className={styles.loginTextField}
|
|
fullWidth
|
|
id="password"
|
|
label={Language.passwordLabel}
|
|
type="password"
|
|
variant="outlined"
|
|
/>
|
|
{authErrorMessage && <FormHelperText error>{Language.authErrorMessage}</FormHelperText>}
|
|
{methodsErrorMessage && <FormHelperText error>{Language.methodsErrorMessage}</FormHelperText>}
|
|
<div className={styles.submitBtn}>
|
|
<LoadingButton color="primary" loading={isLoading} fullWidth type="submit" variant="contained">
|
|
{isLoading ? "" : Language.passwordSignIn}
|
|
</LoadingButton>
|
|
</div>
|
|
</form>
|
|
{authMethods?.github && (
|
|
<div className={styles.submitBtn}>
|
|
<Link href={`/api/v2/users/oauth2/github/callback?redirect=${encodeURIComponent(redirectTo)}`}>
|
|
<Button color="primary" disabled={isLoading} fullWidth type="submit" variant="contained">
|
|
{Language.githubSignIn}
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
)}
|
|
</>
|
|
)
|
|
}
|