Login system
This commit is contained in:
13
src/routes/+layout.ts
Normal file
13
src/routes/+layout.ts
Normal 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
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
<div class="bg-black pointer-events-auto">
|
<div class="bg-black pointer-events-auto">
|
||||||
TEST CARD
|
START CARD
|
||||||
</div>
|
</div>
|
||||||
8
src/routes/[qrcode]/+page.ts
Normal file
8
src/routes/[qrcode]/+page.ts
Normal 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;
|
||||||
|
};
|
||||||
89
src/routes/[qrcode]/login/+page.svelte
Normal file
89
src/routes/[qrcode]/login/+page.svelte
Normal 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>
|
||||||
8
src/routes/[qrcode]/login/+page.ts
Normal file
8
src/routes/[qrcode]/login/+page.ts
Normal 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;
|
||||||
|
};
|
||||||
3
src/routes/[qrcode]/status/+page.svelte
Normal file
3
src/routes/[qrcode]/status/+page.svelte
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<div class="bg-black pointer-events-auto">
|
||||||
|
STATUS CARD
|
||||||
|
</div>
|
||||||
8
src/routes/[qrcode]/status/+page.ts
Normal file
8
src/routes/[qrcode]/status/+page.ts
Normal 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;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user