mirror of
https://github.com/BradNut/AdelieStack
synced 2025-09-08 17:40:20 +00:00
Fixing the login page
This commit is contained in:
parent
2c6a22d686
commit
42d7627783
9 changed files with 63 additions and 50 deletions
|
|
@ -22,7 +22,7 @@ const apiClient: Handle = async ({ event, resolve }) => {
|
|||
/* ----------------------------- Auth functions ----------------------------- */
|
||||
async function getAuthedUser() {
|
||||
const { data } = await api.users.me.$get().then(parseApiResponse);
|
||||
return { user: data?.user, session: data?.session };
|
||||
return data?.user;
|
||||
}
|
||||
|
||||
async function getAuthedUserOrThrow() {
|
||||
|
|
|
|||
12
src/lib/dtos/signin.dto.ts
Normal file
12
src/lib/dtos/signin.dto.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import {z} from "zod";
|
||||
|
||||
export const signinDto = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(3, { message: 'Must be at least 3 characters' })
|
||||
.max(50, { message: 'Must be less than 50 characters' }),
|
||||
password: z.string({ required_error: 'Password is required' }).trim(),
|
||||
});
|
||||
|
||||
export type signinDto = z.infer<typeof signinDto>;
|
||||
12
src/lib/server/api/dtos/signin.dto.ts
Normal file
12
src/lib/server/api/dtos/signin.dto.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import {z} from "zod";
|
||||
|
||||
export const signinDto = z.object({
|
||||
username: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(3, { message: 'Must be at least 3 characters' })
|
||||
.max(50, { message: 'Must be less than 50 characters' }),
|
||||
password: z.string({ required_error: 'Password is required' }).trim(),
|
||||
});
|
||||
|
||||
export type signinDto = z.infer<typeof signinDto>;
|
||||
|
|
@ -25,6 +25,7 @@ export class UsersController extends Controller {
|
|||
.get('/me', async (c) => {
|
||||
const session = c.var.session;
|
||||
const user = session ? await this.usersRepository.findOneByIdOrThrow(session.userId) : null;
|
||||
c.var.logger.info(`Get user: ${JSON.stringify(user)}`);
|
||||
return c.json(user);
|
||||
})
|
||||
.patch('/me', authState('session'), zValidator('form', updateUserDto), async (c) => {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
import HouseIcon from 'lucide-svelte/icons/house';
|
||||
import { page } from '$app/state';
|
||||
import { enhance } from '$app/forms';
|
||||
import ThemeDropdown from '@/components/theme-dropdown.svelte';
|
||||
|
||||
const { children, data } = $props();
|
||||
|
||||
|
|
@ -86,10 +87,11 @@
|
|||
/>
|
||||
</div>
|
||||
</form>
|
||||
<ThemeDropdown />
|
||||
{#if data.authedUser}
|
||||
{@render userDropdown()}
|
||||
{:else}
|
||||
<Button href="/register">Login</Button>
|
||||
<Button href="/login">Login</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@ import { StatusCodes } from "$lib/constants/status-codes";
|
|||
import { redirect } from "@sveltejs/kit";
|
||||
|
||||
export const load = async ({ locals }) => {
|
||||
const user = await locals.getAuthedUser();
|
||||
return { user: user };
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
logout: async ({ locals }) => {
|
||||
await locals.api.iam.logout.$post()
|
||||
redirect(StatusCodes.SEE_OTHER, '/register')
|
||||
redirect(StatusCodes.SEE_OTHER, '/')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@
|
|||
let { data } = $props();
|
||||
</script>
|
||||
|
||||
<h1>Welcome {data?.user?.email}</h1>
|
||||
<h1>Welcome {data?.authedUser?.username}</h1>
|
||||
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,22 @@
|
|||
import { signinUsernameDto } from '$lib/dtos/signin-username.dto';
|
||||
import { StatusCodes } from '$lib/utils/status-codes';
|
||||
import { type Actions, fail } from '@sveltejs/kit';
|
||||
import { redirect } from 'sveltekit-flash-message/server';
|
||||
import { zod } from 'sveltekit-superforms/adapters';
|
||||
import { setError, superValidate } from 'sveltekit-superforms/server';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { signinDto } from '@/server/api/dtos/signin.dto';
|
||||
|
||||
export const load: PageServerLoad = async (event) => {
|
||||
const { locals } = event;
|
||||
const { locals, parent } = event;
|
||||
const { authedUser } = await parent();
|
||||
|
||||
const { user } = await locals.getAuthedUser();
|
||||
|
||||
if (user) {
|
||||
if (authedUser) {
|
||||
console.log('user already signed in');
|
||||
const message = { type: 'success', message: 'You are already signed in' } as const;
|
||||
throw redirect('/', message, event);
|
||||
// redirect(302, '/', message, event)
|
||||
}
|
||||
const form = await superValidate(event, zod(signinUsernameDto));
|
||||
const form = await superValidate(event, zod(signinDto));
|
||||
|
||||
return {
|
||||
form,
|
||||
|
|
@ -35,7 +34,7 @@ export const actions: Actions = {
|
|||
throw redirect('/', message, event);
|
||||
}
|
||||
|
||||
const form = await superValidate(event, zod(signinUsernameDto));
|
||||
const form = await superValidate(event, zod(signinDto));
|
||||
|
||||
const { error } = await locals.api.login.$post({ json: form.data }).then(locals.parseApiResponse);
|
||||
console.log('Login error', error);
|
||||
|
|
|
|||
|
|
@ -1,40 +1,25 @@
|
|||
<script lang="ts">
|
||||
import { Button } from "$components/ui/button";
|
||||
import * as Card from "$components/ui/card";
|
||||
import * as Form from "$components/ui/form";
|
||||
import { Input } from "$components/ui/input";
|
||||
import { boredState } from "$lib/stores/boredState.js";
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import * as Card from '$lib/components/ui/card';
|
||||
import { Input } from '$lib/components/ui/input';
|
||||
import * as Form from '$lib/components/ui/form';
|
||||
import { receive, send } from "$lib/utils/pageCrossfade";
|
||||
import * as flashModule from "sveltekit-flash-message/client";
|
||||
import { zodClient } from "sveltekit-superforms/adapters";
|
||||
import { superForm } from "sveltekit-superforms/client";
|
||||
import { signinDto } from '@/dtos/signin.dto.js';
|
||||
|
||||
let { data } = $props();
|
||||
|
||||
const superLoginForm = superForm(data.form, {
|
||||
onSubmit: () => boredState.update((n) => ({ ...n, loading: true })),
|
||||
onResult: () => boredState.update((n) => ({ ...n, loading: false })),
|
||||
flashMessage: {
|
||||
module: flashModule,
|
||||
onError: ({ result, flashMessage }) => {
|
||||
// Error handling for the flash message:
|
||||
// - result is the ActionResult
|
||||
// - message is the flash store (not the status message store)
|
||||
const errorMessage = result.error.message;
|
||||
flashMessage.set({ type: "error", message: errorMessage });
|
||||
},
|
||||
},
|
||||
syncFlashMessage: false,
|
||||
taintedMessage: null,
|
||||
// validators: zodClient(signInSchema),
|
||||
// validationMethod: 'oninput',
|
||||
delayMs: 0,
|
||||
const sf_login_password = superForm(data.form, {
|
||||
validators: zodClient(signinDto),
|
||||
resetForm: false
|
||||
});
|
||||
|
||||
const { form: loginForm, enhance } = superLoginForm;
|
||||
const { form: loginForm, enhance: loginEnhance, errors: loginErrors } = sf_login_password;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Bored Game | Login</title>
|
||||
<title>Acme | Login</title>
|
||||
</svelte:head>
|
||||
|
||||
<div in:receive={{ key: "auth-card" }} out:send={{ key: "auth-card" }}>
|
||||
|
|
@ -44,8 +29,8 @@
|
|||
</Card.Header>
|
||||
<Card.Content class="grid gap-4">
|
||||
{@render usernamePasswordForm()}
|
||||
<span class="text-center text-sm text-muted-foreground">or sign in with</span>
|
||||
{@render oAuthButtons()}
|
||||
<!-- <span class="text-center text-sm text-muted-foreground">or sign in with</span> -->
|
||||
<!-- {@render oAuthButtons()} -->
|
||||
<p class="px-8 py-4 text-center text-sm text-muted-foreground">
|
||||
By clicking continue, you agree to our
|
||||
<a href="/terms" class="underline underline-offset-4 hover:text-primary"> Terms of Use </a>
|
||||
|
|
@ -57,18 +42,22 @@
|
|||
</div>
|
||||
|
||||
{#snippet usernamePasswordForm()}
|
||||
<form method="POST" use:enhance>
|
||||
<Form.Field form={superLoginForm} name="username">
|
||||
<Form.Control let:attrs>
|
||||
<Form.Label for="username">Username</Form.Label>
|
||||
<Input {...attrs} autocomplete="username" bind:value={$loginForm.username} />
|
||||
<form method="POST" use:loginEnhance>
|
||||
<Form.Field form={sf_login_password} name="username">
|
||||
<Form.Control>
|
||||
{#snippet children({ props })}
|
||||
<Form.Label for="username">Username / Email</Form.Label>
|
||||
<Input {...props} autocomplete="username" placeholder="john.doe@example.com" bind:value={$loginForm.username} />
|
||||
{/snippet}
|
||||
</Form.Control>
|
||||
<Form.FieldErrors />
|
||||
</Form.Field>
|
||||
<Form.Field form={superLoginForm} name="password">
|
||||
<Form.Control let:attrs>
|
||||
<Form.Label for="password">Password</Form.Label>
|
||||
<Input {...attrs} autocomplete="current-password" type="password" bind:value={$loginForm.password} />
|
||||
<Form.Field form={sf_login_password} name="password">
|
||||
<Form.Control>
|
||||
{#snippet children({ props })}
|
||||
<Form.Label for="password">Password</Form.Label>
|
||||
<Input {...props} autocomplete="current-password" placeholder={"••••••••"} type="password" bind:value={$loginForm.password} />
|
||||
{/snippet}
|
||||
</Form.Control>
|
||||
<Form.FieldErrors />
|
||||
</Form.Field>
|
||||
|
|
|
|||
Loading…
Reference in a new issue