Add user login logout
This commit is contained in:
Vendored
+13
-1
@@ -3,7 +3,19 @@
|
|||||||
declare global {
|
declare global {
|
||||||
namespace App {
|
namespace App {
|
||||||
// interface Error {}
|
// interface Error {}
|
||||||
// interface Locals {}
|
interface Locals {
|
||||||
|
user: {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
avatar_url: string;
|
||||||
|
is_active: boolean;
|
||||||
|
is_admin: boolean;
|
||||||
|
last_login: string;
|
||||||
|
created_at: string;
|
||||||
|
modified_at: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
// interface PageData {}
|
// interface PageData {}
|
||||||
// interface PageState {}
|
// interface PageState {}
|
||||||
// interface Platform {}
|
// interface Platform {}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { authenticateUser } from '$lib/server/auth';
|
||||||
|
import type { Handle } from '@sveltejs/kit';
|
||||||
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
export const handle: Handle = async ({ event, resolve }) => {
|
||||||
|
if (event.url.pathname.startsWith('/gameroom')) {
|
||||||
|
const current_user = await authenticateUser(event);
|
||||||
|
if (!current_user) {
|
||||||
|
throw redirect(302, '/login');
|
||||||
|
}
|
||||||
|
event.locals.user = current_user;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await resolve(event);
|
||||||
|
return response;
|
||||||
|
};
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
|
let { user } = $props();
|
||||||
|
let room_link: string = $state('/');
|
||||||
|
if (user) {
|
||||||
|
room_link = '/gameroom/';
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<header
|
<header
|
||||||
class="header bg-primary-FestiveRed-dark mb-10 flex w-full items-center justify-between p-6 drop-shadow-lg"
|
class="header mb-10 flex w-full items-center justify-between bg-primary-FestiveRed-dark p-6 drop-shadow-lg"
|
||||||
>
|
>
|
||||||
<a href="/" aria-label="Paska joululeffa 2024"
|
<a href="/" aria-label="Paska joululeffa 2024"
|
||||||
><enhanced:img
|
><enhanced:img
|
||||||
@@ -11,11 +16,15 @@
|
|||||||
alt="Paska joululeffa 2024"
|
alt="Paska joululeffa 2024"
|
||||||
/></a
|
/></a
|
||||||
>
|
>
|
||||||
<a href="/" aria-label="Shitty Christmas Movie"
|
<a href={room_link} aria-label="Shitty Christmas Movie"
|
||||||
><h1 class="text-primarySnowyWhite-dark text-2xl font-extrabold">Paska Joululeffa 2024</h1>
|
><h1 class="text-primarySnowyWhite-dark text-2xl font-extrabold">Paska Joululeffa 2024</h1>
|
||||||
</a>
|
</a>
|
||||||
<span>
|
<span>
|
||||||
<a href="/login">Sisään</a>
|
{#if user}
|
||||||
<!-- <button>Ulos</button> -->
|
{user.username}
|
||||||
|
<a href="/logout" data-sveltekit-preload-data="tap">Ulos</a>
|
||||||
|
{:else}
|
||||||
|
<a href="/login">Sisään</a>
|
||||||
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { enhance } from '$app/forms';
|
import { enhance } from '$app/forms';
|
||||||
const backend = import.meta.env.VITE_API_URL;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="black border-primary-FestiveRed-dark bg-primary-FestiveRed-dark mx-auto flex max-w-sm flex-col gap-8 rounded-xl border-2 p-6 text-center drop-shadow-lg backdrop-blur-md"
|
class="black mx-auto flex max-w-sm flex-col gap-8 rounded-xl border-2 border-primary-FestiveRed-dark bg-primary-FestiveRed-dark p-6 text-center drop-shadow-lg backdrop-blur-md"
|
||||||
>
|
>
|
||||||
<h1 class="text-2xl">Kirjaudu sisään</h1>
|
<h1 class="text-2xl">Kirjaudu sisään</h1>
|
||||||
<form method="POST" action="?/login" class="flex flex-col gap-6" use:enhance>
|
<form method="POST" action="?/login" class="flex flex-col gap-6" use:enhance>
|
||||||
<label for="username">Käyttäjä</label>
|
<label for="username">Käyttäjä</label>
|
||||||
<input type="text" name="username" id="username" class="input-text" required minlength="3" />
|
<input
|
||||||
|
type="text"
|
||||||
|
name="username"
|
||||||
|
id="username"
|
||||||
|
class="input-text"
|
||||||
|
required
|
||||||
|
minlength="3"
|
||||||
|
value="admin"
|
||||||
|
/>
|
||||||
<label for="password">Salasana</label>
|
<label for="password">Salasana</label>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
@@ -17,6 +24,7 @@
|
|||||||
id="password"
|
id="password"
|
||||||
class="input-text"
|
class="input-text"
|
||||||
required
|
required
|
||||||
|
value="password"
|
||||||
minlength="5"
|
minlength="5"
|
||||||
/>
|
/>
|
||||||
<hr class="my-4 border-0" />
|
<hr class="my-4 border-0" />
|
||||||
|
|||||||
@@ -1 +1,9 @@
|
|||||||
// place files you want to import through the `$lib` alias in this folder.
|
// place files you want to import through the `$lib` alias in this folder.
|
||||||
|
|
||||||
|
export const api_url = "http://localhost:8000";
|
||||||
|
|
||||||
|
export function decodeUSerCookie(userCookie: string) {
|
||||||
|
const decodedCookie = decodeURIComponent(userCookie);
|
||||||
|
const parsedCookie = JSON.parse(decodedCookie);
|
||||||
|
return parsedCookie;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { redirect, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
|
||||||
|
export const authenticateUser = (event: RequestEvent) => {
|
||||||
|
const {cookies} = event;
|
||||||
|
const userCookie = cookies.get('user');
|
||||||
|
if (!userCookie) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const decodedCookie = decodeURIComponent(userCookie);
|
||||||
|
const parsedCookie = JSON.parse(decodedCookie);
|
||||||
|
|
||||||
|
if (!parsedCookie) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return parsedCookie
|
||||||
|
}
|
||||||
|
|
||||||
|
export const logoutUser = (event: RequestEvent) => {
|
||||||
|
const {cookies} = event;
|
||||||
|
cookies.delete('user', {
|
||||||
|
path: '/',
|
||||||
|
sameSite: 'strict',
|
||||||
|
secure: false,
|
||||||
|
});
|
||||||
|
throw redirect(302, '/login');
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import type { LayoutServerLoad } from './$types';
|
||||||
|
import { authenticateUser } from '$lib/server/auth';
|
||||||
|
|
||||||
|
export const load: LayoutServerLoad = async (event) => {
|
||||||
|
const user = await authenticateUser(event);
|
||||||
|
return {
|
||||||
|
user: user
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
import '../app.css';
|
import '../app.css';
|
||||||
import Header from '$lib/components/Header.svelte';
|
import Header from '$lib/components/Header.svelte';
|
||||||
import Footer from '$lib/components/Footer.svelte';
|
import Footer from '$lib/components/Footer.svelte';
|
||||||
let { children } = $props();
|
import type { LayoutData } from './$types';
|
||||||
|
let { data, children }: { data: LayoutData; children: () => any } = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@@ -10,7 +11,7 @@
|
|||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div class="flex min-h-[100dvh] flex-col">
|
<div class="flex min-h-[100dvh] flex-col">
|
||||||
<Header />
|
<Header user={data.user} />
|
||||||
<main class="container mx-auto max-w-4xl flex-grow overflow-hidden">
|
<main class="container mx-auto max-w-4xl flex-grow overflow-hidden">
|
||||||
{@render children()}
|
{@render children()}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import type { PageServerLoad } from "./$types";
|
||||||
|
import { api_url } from "$lib";
|
||||||
|
|
||||||
|
type movie = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
imdb_id: string;
|
||||||
|
actors: Array<string>;
|
||||||
|
plot: string;
|
||||||
|
poster_url: string;
|
||||||
|
release_date: string;
|
||||||
|
showtime: string;
|
||||||
|
is_watched: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async (event) => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const get_next_movie_url = `${api_url}/movie/next`;
|
||||||
|
const response = await fetch(get_next_movie_url);
|
||||||
|
const data: movie = await response.json();
|
||||||
|
|
||||||
|
|
||||||
|
const year = new Date(data.release_date).getFullYear();
|
||||||
|
data.release_date = `${year}`;
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
movie: data,
|
||||||
|
user: event.locals.user
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import MovieDetails from '$lib/components/MovieDetails.svelte';
|
||||||
|
let data = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<MovieDetails {...data} />
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import type { PageServerLoad } from "./$types";
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async (event) => {
|
||||||
|
return {
|
||||||
|
user: event.locals.user
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { PageData } from './$types';
|
||||||
|
let { data }: { data: PageData } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>gameroom</h1>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
import type { Actions } from './$types';
|
||||||
|
|
||||||
|
|
||||||
|
const api_url = import.meta.env.VITE_API_URL
|
||||||
|
|
||||||
|
|
||||||
|
export const actions: Actions = {
|
||||||
|
login: async ({ request, cookies }) => {
|
||||||
|
const formData = await request.formData();
|
||||||
|
const login_data = Object.fromEntries(formData);
|
||||||
|
const response = await fetch(`${api_url}/user/login`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(login_data)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const user_data = await response.json()
|
||||||
|
const encodedUserData = encodeURIComponent(JSON.stringify(user_data));
|
||||||
|
cookies.set('user', encodedUserData, {
|
||||||
|
path: '/',
|
||||||
|
sameSite: 'strict',
|
||||||
|
secure: false,
|
||||||
|
maxAge: 60 * 60 * 24
|
||||||
|
});
|
||||||
|
throw redirect(302, '/gameroom');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
@@ -1,5 +1,22 @@
|
|||||||
<script>
|
<script lang="ts">
|
||||||
import Login from '$lib/components/Login.svelte';
|
import Login from '$lib/components/Login.svelte';
|
||||||
|
|
||||||
|
const { form } = $props();
|
||||||
|
|
||||||
|
if (form) {
|
||||||
|
console.log('asda', form);
|
||||||
|
}
|
||||||
|
|
||||||
|
const api_url = import.meta.env.VITE_API_URL;
|
||||||
|
|
||||||
|
type User = {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
avatar_url: string;
|
||||||
|
is_admin: boolean;
|
||||||
|
last_login: string;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Login />
|
<Login />
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import type { PageServerLoad } from "./$types";
|
||||||
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
export const load: PageServerLoad = async (event) => {
|
||||||
|
event.cookies.delete('user', {
|
||||||
|
path: '/',
|
||||||
|
sameSite: 'strict',
|
||||||
|
secure: false,
|
||||||
|
});
|
||||||
|
throw redirect(302, '/login');
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user