Login system

This commit is contained in:
2025-03-25 13:28:18 +01:00
parent ae04d2b7b3
commit a33c1d8f5b
9 changed files with 173 additions and 6 deletions

13
src/routes/+layout.ts Normal file
View File

@@ -0,0 +1,13 @@
import type { LayoutLoad } from './$types';
export const load: LayoutLoad = async ({ fetch }) => {
const user = await fetch('/api/public/1/auth/myself/', {
method: 'GET',
headers: {
'Accept': 'application/json',
}
});
return {
user: user.ok ? await user.json() : null
};
};

View File

@@ -3,10 +3,32 @@
import type { LayoutProps } from './$types'; import type { LayoutProps } from './$types';
import ConnType2 from "$lib/icons/ConnType2.svelte"; import ConnType2 from "$lib/icons/ConnType2.svelte";
import Icon from "@iconify/svelte"; import Icon from "@iconify/svelte";
import { goto, invalidateAll } from "$app/navigation";
let { data, children }: LayoutProps = $props(); let { data, children }: LayoutProps = $props();
const cc = $derived(data.chargecontroller); const cc = $derived(data.chargecontroller);
const user = $derived(data.user);
const qrcode = $derived(page.params.qrcode); const qrcode = $derived(page.params.qrcode);
let logouting = $state(false);
async function logout() {
logouting = true;
try {
const response = await fetch("/api/public/1/auth/logout/", {
method: 'GET',
headers: {
'Accept': 'application/json',
}
});
if (response.ok) {
await invalidateAll();
await goto(`/${qrcode}`);
}
} finally {
logouting = false;
}
}
</script> </script>
<div class="flex flex-col h-screen"> <div class="flex flex-col h-screen">
@@ -17,16 +39,29 @@
</div> </div>
<div class="flex-none"> <div class="flex-none">
<ul class="menu menu-horizontal px-1"> <ul class="menu menu-horizontal px-1">
<li><p>QRCODE: {qrcode}</p></li> <li><p>
{#if user}
{user['username']}
{:else}
No User
{/if}
</p></li>
<li> <li>
<details> <details>
<summary>PARK: {cc['park']}</summary> <summary>
EN
</summary>
<ul class="bg-base-100 rounded-t-none p-2"> <ul class="bg-base-100 rounded-t-none p-2">
<li><p>EN</p></li> <li><p>EN</p></li>
<li><p>IT</p></li> <li><p>IT</p></li>
</ul> </ul>
</details> </details>
</li> </li>
<li>
<button class={["h-full w-full", logouting && "bg-gray-300"]} onclick={logout}>
<Icon class="h-5 w-5" icon="mdi:logout"/>
</button>
</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@@ -4,16 +4,19 @@ import { type } from "arktype";
const QrcodeType = type("string.integer.parse"); const QrcodeType = type("string.integer.parse");
export const load: LayoutLoad = async ({ params, fetch }) => { export const load: LayoutLoad = async ({ params, fetch, parent }) => {
const qrcode = QrcodeType(params.qrcode); const qrcode = QrcodeType(params.qrcode);
if (qrcode instanceof type.errors) error(400, 'invalid qrcode'); if (qrcode instanceof type.errors) error(400, 'invalid qrcode');
const data = await fetch(`/api/v2/chargecontroller/${qrcode}/`, { const cc = await fetch(`/api/v2/chargecontroller/${qrcode}/`, {
method: 'GET', method: 'GET',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
} }
}); });
const parentData = await parent();
return { return {
chargecontroller: await data.json(), ...parentData,
qrcode: qrcode,
chargecontroller: await cc.json(),
}; };
}; };

View File

@@ -1,3 +1,3 @@
<div class="bg-black pointer-events-auto"> <div class="bg-black pointer-events-auto">
TEST CARD START CARD
</div> </div>

View File

@@ -0,0 +1,8 @@
import type { PageLoad } from './$types';
import { redirect } from "@sveltejs/kit";
export const load: PageLoad = async ({ parent }) => {
const parentData = await parent();
if (parentData.user === null) return redirect(303, `${parentData.qrcode}/login`);
return parentData;
};

View File

@@ -0,0 +1,89 @@
<script>
import { superForm, defaults, setMessage } from 'sveltekit-superforms';
import { type } from "arktype";
import { arktypeClient } from 'sveltekit-superforms/adapters';
import FormInput from "$lib/FormInput.svelte";
import PwdFormInput from "$lib/PwdFormInput.svelte";
import { goto, invalidateAll } from "$app/navigation";
let { data } = $props();
const schema = type({
username: 'string > 3',
password: 'string > 3',
});
const schemaDefaults = {
username: '',
password: '',
};
const form = superForm(defaults(schemaDefaults, arktypeClient(schema)), {
SPA: true,
validators: arktypeClient(schema),
resetForm: false,
async onUpdate({ form }) {
// Equivalent to onSubmit for this context. We can validate and then execute things.
if (form.valid) {
// Call an external API with form.data, await the result and update form
const response = await fetch("/api/public/1/auth/login/", {
method: 'POST',
body: JSON.stringify(form.data),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
});
console.log(response.status);
if (response.status !== 200) {
setMessage(form, {
status: 'error',
text: `HTTP Code ${response.status}:\n${JSON.stringify(await response.json(), null, 2)}`,
});
} else {
setMessage(form, {
status: 'success',
text: 'Login succeded, redirecting...',
});
await invalidateAll();
await goto(`/${data.qrcode}`);
}
}
},
});
const { message, enhance, submitting } = form;
</script>
<div class="pointer-events-auto bg-gray-300/50 h-full w-full flex justify-center items-center">
<div class="card bg-base-100 w-fit shadow-md">
<form class="card-body" method="POST" use:enhance>
<h2 class="card-title">Accesso Utente</h2>
<div class="flex flex-col gap-2 my-2">
<FormInput {form} type="text" label="Username" name="username"/>
<PwdFormInput {form} label="Password" name="password"/>
</div>
<div class="card-actions justify-center">
<button class="btn btn-primary" type="submit">
{#if $submitting}
<span class="loading"></span>
{/if}
Login
</button>
</div>
{#if $message}
<div class="card bg-base-200 mt-4 card-border max-w-[80vw]">
<div class="card-body">
<h2 class="card-title" class:text-error={$message['status'] === 'error'}>
{$message['status'] === 'success' ? 'Success!' : 'Error'}
</h2>
<div>
{$message['text']}
</div>
</div>
</div>
{/if}
</form>
</div>
</div>

View File

@@ -0,0 +1,8 @@
import type { PageLoad } from './$types';
import { redirect } from "@sveltejs/kit";
export const load: PageLoad = async ({ parent }) => {
const parentData = await parent();
if (parentData.user !== null) return redirect(303, `/${parentData.qrcode}`);
return parentData;
};

View File

@@ -0,0 +1,3 @@
<div class="bg-black pointer-events-auto">
STATUS CARD
</div>

View File

@@ -0,0 +1,8 @@
import type { PageLoad } from './$types';
import { redirect } from "@sveltejs/kit";
export const load: PageLoad = async ({ parent }) => {
const parentData = await parent();
if (parentData.user === null) return redirect(303, `${parentData.qrcode}/login`);
return parentData;
};