added 2FA

This commit is contained in:
2024-04-26 22:16:21 +03:00
parent 53cadc289a
commit f17a002ac6
38 changed files with 1036 additions and 414 deletions

View File

@@ -5,14 +5,7 @@ import { useState, useTransition } from 'react'
import { useForm } from 'react-hook-form'
import { useSearchParams } from 'next/navigation'
import { zodResolver } from '@hookform/resolvers/zod'
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
import { Input } from '@/components/ui/input'
import { CardWrapper } from '@/components/auth/card-wrapper'
import { useI18n } from '@/locales/client'
@@ -28,10 +21,9 @@ export const LoginForm = () => {
const t = useI18n()
const searchParams = useSearchParams()
const urlError = searchParams.get('error') === 'OAuthAccountNotLinked'
? t('auth.form.error.email_in_use')
: ''
const urlError = searchParams.get('error') === 'OAuthAccountNotLinked' ? t('auth.form.error.email_in_use') : ''
const [showTwoFactor, setShowTwoFactor] = useState<boolean>(false)
const [error, setError] = useState<string | undefined>('')
const [success, setSuccess] = useState<string | undefined>('')
const [isPending, startTransition] = useTransition()
@@ -48,10 +40,26 @@ export const LoginForm = () => {
startTransition(() => {
login(values).then((data) => {
// @ts-ignore
setError(t(data?.error))
// @ts-ignore
setSuccess(t(data?.success))
//@ts-ignore
if (data?.error) {
form.reset() //@ts-ignore
setError(t(data?.error))
}
//@ts-ignore
if (data?.success) {
form.reset() //@ts-ignore
setSuccess(t(data?.success))
}
//@ts-ignore
if (data?.twoFactor) { //@ts-ignore
setShowTwoFactor(data?.twoFactor)
}
}).catch((err) => {
setError('auth.common.something_went_wrong')
//TODO: do logging
console.log(err)
})
})
}
@@ -67,48 +75,62 @@ export const LoginForm = () => {
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-0"
className={showTwoFactor ? 'space-y-6' : 'space-y-2'}
>
<div className="space-y-4">
<FormField control={form.control} name="email"
render={({ field }) => (<FormItem>
<FormLabel>{t('form.label.email')}</FormLabel>
<FormControl>
<Input
{...field}
disabled={isPending}
placeholder={t('form.placeholder.email')}
type="email"
autoComplete="email"
/>
</FormControl>
<FormMessage className="text-xs"/>
</FormItem>)}/>
{/*Password*/}
<FormField control={form.control} name="password"
render={({ field }) => (<FormItem>
<FormLabel>{t('form.label.password')}</FormLabel>
<FormControl>
<Input
{...field}
disabled={isPending}
placeholder="******"
type="password"
autoComplete="current-password"
/>
</FormControl>
<Button variant="link" size="sm" asChild
className="mt-0 p-0 items-start font-light text-sky-900">
<Link href={AUTH_RESET_PASSWORD_URL}>{t('auth.form.login.reset_password_link_text')}</Link>
</Button>
<FormMessage className="text-xs"/>
</FormItem>)}/>
{showTwoFactor && (
<FormField control={form.control} name="code"
render={({ field }) => (<FormItem>
<FormLabel>{t('form.label.two_factor')}</FormLabel>
<FormControl>
<Input
{...field}
disabled={isPending}
placeholder="¹₂³₄⁵₆"
/>
</FormControl>
<FormMessage className="text-xs"/>
</FormItem>)}/>
)}
{!showTwoFactor && (<>
<FormField control={form.control} name="email"
render={({ field }) => (<FormItem>
<FormLabel>{t('form.label.email')}</FormLabel>
<FormControl>
<Input
{...field}
disabled={isPending}
placeholder={t('form.placeholder.email')}
type="email"
autoComplete="email"
/>
</FormControl>
<FormMessage className="text-xs"/>
</FormItem>)}/>
<FormField control={form.control} name="password"
render={({ field }) => (<FormItem>
<FormLabel>{t('form.label.password')}</FormLabel>
<FormControl>
<Input
{...field}
disabled={isPending}
placeholder="******"
type="password"
autoComplete="current-password"
/>
</FormControl>
<Button variant="link" size="sm" asChild
className="mt-0 p-0 items-start font-light text-sky-900">
<Link href={AUTH_RESET_PASSWORD_URL}>{t('auth.form.login.reset_password_link_text')}</Link>
</Button>
<FormMessage className="text-xs"/>
</FormItem>)}/>
</>)}
</div>
<FormSuccess message={success}/>
<FormError message={error || urlError}/>
<Button type="submit" className="w-full" disabled={isPending}>
{t('form.label.login')}
{showTwoFactor ? t('form.button.two_factor') : t('form.button.login')}
</Button>
</form>
</Form>