mirror of
https://github.com/BradNut/sveltekit-auth-cookies
synced 2025-09-08 17:40:33 +00:00
Fix login page endpoint, implement session passing, redirect on protected routes and login.
This commit is contained in:
parent
4672da6f4a
commit
f9aae20f91
7 changed files with 170 additions and 93 deletions
8
src/app.d.ts
vendored
8
src/app.d.ts
vendored
|
|
@ -3,8 +3,12 @@
|
||||||
// See https://kit.svelte.dev/docs/types#app
|
// See https://kit.svelte.dev/docs/types#app
|
||||||
// for information about these interfaces
|
// for information about these interfaces
|
||||||
declare namespace App {
|
declare namespace App {
|
||||||
// interface Locals {}
|
interface Locals {
|
||||||
|
user?: { username: string }
|
||||||
|
}
|
||||||
// interface Platform {}
|
// interface Platform {}
|
||||||
// interface Session {}
|
interface Session {
|
||||||
|
user?: { username: string }
|
||||||
|
}
|
||||||
// interface Stuff {}
|
// interface Stuff {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
src/hooks.ts
Normal file
33
src/hooks.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
import type { GetSession, Handle } from "@sveltejs/kit"
|
||||||
|
import * as cookie from 'cookie'
|
||||||
|
|
||||||
|
import { db } from '$lib/database'
|
||||||
|
|
||||||
|
export const handle: Handle = async ({ event, resolve }) => {
|
||||||
|
const cookieHeader = event.request.headers.get('cookie')
|
||||||
|
const cookies = cookie.parse(cookieHeader ?? '')
|
||||||
|
|
||||||
|
if (!cookies.session) {
|
||||||
|
return await resolve(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
const session = await db.user.findUnique({
|
||||||
|
where: { id: cookies.session },
|
||||||
|
})
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
event.locals.user = { username: session.username }
|
||||||
|
}
|
||||||
|
|
||||||
|
return await resolve(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getSession: GetSession = ({ locals }) => {
|
||||||
|
if (!locals.user) return {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
user: {
|
||||||
|
username: locals.user.username
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,8 +8,7 @@ export async function send(form: HTMLFormElement): Send {
|
||||||
const response = await fetch(form.action, {
|
const response = await fetch(form.action, {
|
||||||
method: form.method,
|
method: form.method,
|
||||||
body: new FormData(form),
|
body: new FormData(form),
|
||||||
headers: { accept: 'application/json' }
|
headers: { accept: 'application/json' },
|
||||||
})
|
})
|
||||||
|
|
||||||
return await response.json()
|
return await response.json()
|
||||||
}
|
}
|
||||||
|
|
@ -1,57 +1,57 @@
|
||||||
<script lang="ts">
|
<script context="module" lang="ts">
|
||||||
import { session } from '$app/stores'
|
export const load: Load = ({ session, props }) => {
|
||||||
import { send } from '$lib/api'
|
if (session.user) {
|
||||||
|
return {
|
||||||
|
status: 302,
|
||||||
|
redirect: '/'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export let error: string
|
return { props };
|
||||||
|
};
|
||||||
async function login(event: SubmitEvent) {
|
|
||||||
const formEl = event.target as HTMLFormElement
|
|
||||||
const response = await send(formEl)
|
|
||||||
|
|
||||||
if (response.error) {
|
|
||||||
error = response.error
|
|
||||||
}
|
|
||||||
|
|
||||||
$session.user = response.user
|
|
||||||
|
|
||||||
formEl.reset()
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form
|
<script lang="ts">
|
||||||
on:submit|preventDefault={login}
|
import { session } from '$app/stores';
|
||||||
method="post"
|
import { send } from '$lib/api';
|
||||||
autocomplete="off"
|
import type { Load } from '@sveltejs/kit';
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<label for="username">Username</label>
|
|
||||||
<input
|
|
||||||
id="username"
|
|
||||||
name="username"
|
|
||||||
type="username"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
export let error: string;
|
||||||
<label for="password">Password</label>
|
|
||||||
<input
|
|
||||||
id="password"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if error}
|
async function login(event: SubmitEvent) {
|
||||||
<p class="error">{error}</p>
|
const formEl = event.target as HTMLFormElement;
|
||||||
{/if}
|
const response = await send(formEl);
|
||||||
|
|
||||||
<button type="submit">Sign In</button>
|
if (response.error) {
|
||||||
|
error = response.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
$session.user = response.user;
|
||||||
|
|
||||||
|
formEl.reset();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<form on:submit|preventDefault={login} method="post" autocomplete="off">
|
||||||
|
<div>
|
||||||
|
<label for="username">Username</label>
|
||||||
|
<input id="username" name="username" type="username" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input id="password" name="password" type="password" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if error}
|
||||||
|
<p class="error">{error}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<button type="submit">Sign In</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.error {
|
.error {
|
||||||
color: tomato;
|
color: tomato;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,7 @@ import { db } from '$lib/database'
|
||||||
export const post: RequestHandler = async ({ request }) => {
|
export const post: RequestHandler = async ({ request }) => {
|
||||||
const form = await request.formData()
|
const form = await request.formData()
|
||||||
const username = form.get('username')
|
const username = form.get('username')
|
||||||
console.log('username', username);
|
|
||||||
const password = form.get('password')
|
const password = form.get('password')
|
||||||
console.log('password', password);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
typeof username !== 'string' ||
|
typeof username !== 'string' ||
|
||||||
|
|
@ -1,55 +1,71 @@
|
||||||
|
<script context="module" lang="ts">
|
||||||
|
export const load: Load = ({ session, props }) => {
|
||||||
|
if (session.user) {
|
||||||
|
return {
|
||||||
|
status: 302,
|
||||||
|
redirect: '/'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { props };
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<script type="ts">
|
<script type="ts">
|
||||||
import {send} from '$lib/api';
|
import { send } from '$lib/api';
|
||||||
|
import type { Load } from '@sveltejs/kit';
|
||||||
|
|
||||||
export let error: string;
|
export let error: string;
|
||||||
export let success: string;
|
export let success: string;
|
||||||
|
|
||||||
async function register(event: SubmitEvent) {
|
async function register(event: SubmitEvent) {
|
||||||
error = ''
|
error = '';
|
||||||
|
|
||||||
const formEl = event.target as HTMLFormElement
|
const formEl = event.target as HTMLFormElement;
|
||||||
const response = await send(formEl)
|
const response = await send(formEl);
|
||||||
|
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
error = response.error
|
error = response.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
success = response.success
|
success = response.success;
|
||||||
}
|
}
|
||||||
|
|
||||||
formEl.reset()
|
formEl.reset();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form on:submit|preventDefault={register} method="post" autocomplete="off">
|
<form on:submit|preventDefault={register} method="post" autocomplete="off">
|
||||||
<div>
|
<div>
|
||||||
<label for="username">Username
|
<label for="username"
|
||||||
<input id="username" name="username" type="text" required />
|
>Username
|
||||||
</label>
|
<input id="username" name="username" type="text" required />
|
||||||
</div>
|
</label>
|
||||||
<div>
|
</div>
|
||||||
<label for="password">Password
|
<div>
|
||||||
<input id="password" name="password" type="password" required />
|
<label for="password"
|
||||||
</label>
|
>Password
|
||||||
</div>
|
<input id="password" name="password" type="password" required />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
{#if error}
|
{#if error}
|
||||||
<p class="error">{error}</p>
|
<p class="error">{error}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if success}
|
{#if success}
|
||||||
<div>
|
<div>
|
||||||
<p>Thank you for signing up!</p>
|
<p>Thank you for signing up!</p>
|
||||||
<p><a href="/auth/login">You can log in.</a></p>
|
<p><a href="/auth/login">You can log in.</a></p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button type="submit">Sign Up</button>
|
<button type="submit">Sign Up</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.error {
|
.error {
|
||||||
color: tomato;
|
color: tomato;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
27
src/routes/protected/index.svelte
Normal file
27
src/routes/protected/index.svelte
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
<script context="module" lang="ts">
|
||||||
|
import type { Load } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
export const load: Load = ({ session }) => {
|
||||||
|
if (!session.user) {
|
||||||
|
return {
|
||||||
|
status: 302,
|
||||||
|
redirect: '/auth/login'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
props: {
|
||||||
|
user: session.user.username
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export let user: string;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>Protected</h1>
|
||||||
|
|
||||||
|
<p>Weclome {user}</p>
|
||||||
Loading…
Reference in a new issue