update auth guard and sign-in forms, add guidelines for custom auth to handle login and logout,
This commit is contained in:
@@ -29,6 +29,7 @@ export function AuthGuard({ children }: AuthGuardProps): React.JSX.Element | nul
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: here state that if user = null, eject user to login page
|
||||
if (!user) {
|
||||
logger.debug('[AuthGuard]: User is not logged in, redirecting to sign in');
|
||||
|
||||
|
10
002_source/cms/src/components/auth/custom/_GUIDELINES.md
Normal file
10
002_source/cms/src/components/auth/custom/_GUIDELINES.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# GUIDELINES
|
||||
|
||||
This folder contains login pages
|
||||
|
||||
the `@` sign refer to `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src`
|
||||
|
||||
## Assumption and Requirements
|
||||
|
||||
- assume `pb` is located in `@/lib/pb`
|
||||
- no need to handle error in this function, i'll handle it in the caller
|
@@ -1,4 +1,6 @@
|
||||
'use client';
|
||||
// RULES:
|
||||
// refer to ticket REQ0016 for login flow
|
||||
|
||||
import * as React from 'react';
|
||||
import RouterLink from 'next/link';
|
||||
@@ -25,6 +27,7 @@ import { authClient } from '@/lib/auth/custom/client';
|
||||
import { useUser } from '@/hooks/use-user';
|
||||
import { DynamicLogo } from '@/components/core/logo';
|
||||
import { toast } from '@/components/core/toaster';
|
||||
import { pb } from '@/lib/pb';
|
||||
|
||||
interface OAuthProvider {
|
||||
id: 'google' | 'discord';
|
||||
@@ -44,7 +47,7 @@ const schema = zod.object({
|
||||
|
||||
type Values = zod.infer<typeof schema>;
|
||||
|
||||
const defaultValues = { email: '', password: '' } satisfies Values;
|
||||
const defaultValues = { email: 'admin@123.com', password: 'admin@123.com' } satisfies Values;
|
||||
|
||||
export function SignInForm(): React.JSX.Element {
|
||||
const router = useRouter();
|
||||
@@ -103,15 +106,31 @@ export function SignInForm(): React.JSX.Element {
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<div>
|
||||
<Box component={RouterLink} href={paths.home} sx={{ display: 'inline-block', fontSize: 0 }}>
|
||||
<DynamicLogo colorDark="light" colorLight="dark" height={32} width={122} />
|
||||
<Box
|
||||
component={RouterLink}
|
||||
href={paths.home}
|
||||
sx={{ display: 'inline-block', fontSize: 0 }}
|
||||
>
|
||||
<DynamicLogo
|
||||
colorDark="light"
|
||||
colorLight="dark"
|
||||
height={32}
|
||||
width={122}
|
||||
/>
|
||||
</Box>
|
||||
</div>
|
||||
<Stack spacing={1}>
|
||||
<Typography variant="h5">Sign in</Typography>
|
||||
<Typography color="text.secondary" variant="body2">
|
||||
<Typography
|
||||
color="text.secondary"
|
||||
variant="body2"
|
||||
>
|
||||
Don't have an account?{' '}
|
||||
<Link component={RouterLink} href={paths.auth.custom.signUp} variant="subtitle2">
|
||||
<Link
|
||||
component={RouterLink}
|
||||
href={paths.auth.custom.signUp}
|
||||
variant="subtitle2"
|
||||
>
|
||||
Sign up
|
||||
</Link>
|
||||
</Typography>
|
||||
@@ -123,7 +142,15 @@ export function SignInForm(): React.JSX.Element {
|
||||
<Button
|
||||
color="secondary"
|
||||
disabled={isPending}
|
||||
endIcon={<Box alt="" component="img" height={24} src={provider.logo} width={24} />}
|
||||
endIcon={
|
||||
<Box
|
||||
alt=""
|
||||
component="img"
|
||||
height={24}
|
||||
src={provider.logo}
|
||||
width={24}
|
||||
/>
|
||||
}
|
||||
key={provider.id}
|
||||
onClick={(): void => {
|
||||
onAuth(provider.id).catch(() => {
|
||||
@@ -147,7 +174,10 @@ export function SignInForm(): React.JSX.Element {
|
||||
render={({ field }) => (
|
||||
<FormControl error={Boolean(errors.email)}>
|
||||
<InputLabel>Email address</InputLabel>
|
||||
<OutlinedInput {...field} type="email" />
|
||||
<OutlinedInput
|
||||
{...field}
|
||||
type="email"
|
||||
/>
|
||||
{errors.email ? <FormHelperText>{errors.email.message}</FormHelperText> : null}
|
||||
</FormControl>
|
||||
)}
|
||||
@@ -187,27 +217,65 @@ export function SignInForm(): React.JSX.Element {
|
||||
)}
|
||||
/>
|
||||
{errors.root ? <Alert color="error">{errors.root.message}</Alert> : null}
|
||||
<Button disabled={isPending} type="submit" variant="contained">
|
||||
<Button
|
||||
disabled={isPending}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
>
|
||||
Sign in
|
||||
</Button>
|
||||
</Stack>
|
||||
</form>
|
||||
<div>
|
||||
<Link component={RouterLink} href={paths.auth.custom.resetPassword} variant="subtitle2">
|
||||
<Link
|
||||
component={RouterLink}
|
||||
href={paths.auth.custom.resetPassword}
|
||||
variant="subtitle2"
|
||||
>
|
||||
Forgot password?
|
||||
</Link>
|
||||
</div>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Alert color="warning">
|
||||
Use{' '}
|
||||
<Typography component="span" sx={{ fontWeight: 700 }} variant="inherit">
|
||||
sofia@devias.io
|
||||
</Typography>{' '}
|
||||
with password{' '}
|
||||
<Typography component="span" sx={{ fontWeight: 700 }} variant="inherit">
|
||||
Secret1
|
||||
</Typography>
|
||||
<Stack>
|
||||
<Box>
|
||||
user:{' '}
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{ fontWeight: 700 }}
|
||||
variant="inherit"
|
||||
>
|
||||
admin@123.com
|
||||
</Typography>{' '}
|
||||
password{' '}
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{ fontWeight: 700 }}
|
||||
variant="inherit"
|
||||
>
|
||||
admin@123.com
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box>
|
||||
user{' '}
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{ fontWeight: 700 }}
|
||||
variant="inherit"
|
||||
>
|
||||
sofia@devias.io
|
||||
</Typography>{' '}
|
||||
password{' '}
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{ fontWeight: 700 }}
|
||||
variant="inherit"
|
||||
>
|
||||
Secret1
|
||||
</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Alert>
|
||||
</Stack>
|
||||
);
|
||||
|
@@ -115,15 +115,31 @@ export function SignInForm(): React.JSX.Element {
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<div>
|
||||
<Box component={RouterLink} href={paths.home} sx={{ display: 'inline-block', fontSize: 0 }}>
|
||||
<DynamicLogo colorDark="light" colorLight="dark" height={32} width={122} />
|
||||
<Box
|
||||
component={RouterLink}
|
||||
href={paths.home}
|
||||
sx={{ display: 'inline-block', fontSize: 0 }}
|
||||
>
|
||||
<DynamicLogo
|
||||
colorDark="light"
|
||||
colorLight="dark"
|
||||
height={32}
|
||||
width={122}
|
||||
/>
|
||||
</Box>
|
||||
</div>
|
||||
<Stack spacing={1}>
|
||||
<Typography variant="h5">Sign in</Typography>
|
||||
<Typography color="text.secondary" variant="body2">
|
||||
<Typography
|
||||
color="text.secondary"
|
||||
variant="body2"
|
||||
>
|
||||
Don't have an account?{' '}
|
||||
<Link component={RouterLink} href={paths.auth.supabase.signUp} variant="subtitle2">
|
||||
<Link
|
||||
component={RouterLink}
|
||||
href={paths.auth.supabase.signUp}
|
||||
variant="subtitle2"
|
||||
>
|
||||
Sign up
|
||||
</Link>
|
||||
</Typography>
|
||||
@@ -135,7 +151,15 @@ export function SignInForm(): React.JSX.Element {
|
||||
<Button
|
||||
color="secondary"
|
||||
disabled={isPending}
|
||||
endIcon={<Box alt="" component="img" height={24} src={provider.logo} width={24} />}
|
||||
endIcon={
|
||||
<Box
|
||||
alt=""
|
||||
component="img"
|
||||
height={24}
|
||||
src={provider.logo}
|
||||
width={24}
|
||||
/>
|
||||
}
|
||||
key={provider.id}
|
||||
onClick={(): void => {
|
||||
onAuth(provider.id).catch(() => {
|
||||
@@ -159,7 +183,10 @@ export function SignInForm(): React.JSX.Element {
|
||||
render={({ field }) => (
|
||||
<FormControl error={Boolean(errors.email)}>
|
||||
<InputLabel>Email address</InputLabel>
|
||||
<OutlinedInput {...field} type="email" />
|
||||
<OutlinedInput
|
||||
{...field}
|
||||
type="email"
|
||||
/>
|
||||
{errors.email ? <FormHelperText>{errors.email.message}</FormHelperText> : null}
|
||||
</FormControl>
|
||||
)}
|
||||
@@ -199,13 +226,21 @@ export function SignInForm(): React.JSX.Element {
|
||||
)}
|
||||
/>
|
||||
{errors.root ? <Alert color="error">{errors.root.message}</Alert> : null}
|
||||
<Button disabled={isPending} type="submit" variant="contained">
|
||||
<Button
|
||||
disabled={isPending}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
>
|
||||
Sign in
|
||||
</Button>
|
||||
</Stack>
|
||||
</form>
|
||||
<div>
|
||||
<Link component={RouterLink} href={paths.auth.supabase.resetPassword} variant="subtitle2">
|
||||
<Link
|
||||
component={RouterLink}
|
||||
href={paths.auth.supabase.resetPassword}
|
||||
variant="subtitle2"
|
||||
>
|
||||
Forgot password?
|
||||
</Link>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user