mirror of
https://github.com/open-reception/appointment-booking-software.git
synced 2026-08-17 21:25:52 +02:00
Make logout a front-end only fetch to fix race conditions and make sure access_token is gone
This commit is contained in:
@@ -125,9 +125,16 @@
|
||||
"errorGettingPrfOutput": "Fehler beim Abrufen der Sicherheitsdaten vom Passkey. Bitte verwenden Sie einen modernen Authentifikator, der die PRF-Erweiterung unterstützt."
|
||||
},
|
||||
"logout": {
|
||||
"title": "Erfolgreich abgemeldet",
|
||||
"description": "Du wurdest abgemeldet.",
|
||||
"success": "Erfolgreich abgemeldet",
|
||||
"title": "Abmelden",
|
||||
"success": {
|
||||
"title": "Du wurdest abgemeldet.",
|
||||
"description": "Du wurdest abgemeldet."
|
||||
},
|
||||
"error": {
|
||||
"title": "Abmelden fehlgeschlagen",
|
||||
"description": "Du konntest nicht abgemeldet werden."
|
||||
},
|
||||
"retry": "Erneut versuchen",
|
||||
"action": "Zur Anmeldung"
|
||||
},
|
||||
"passkey": {
|
||||
|
||||
@@ -133,9 +133,16 @@
|
||||
}
|
||||
},
|
||||
"logout": {
|
||||
"title": "Logout complete",
|
||||
"description": "You are logged-out.",
|
||||
"success": "Logout successful",
|
||||
"title": "Logout",
|
||||
"success": {
|
||||
"title": "You are logged out.",
|
||||
"description": "You are logged-out."
|
||||
},
|
||||
"error": {
|
||||
"title": "Logout failed",
|
||||
"description": "You could not be logged out."
|
||||
},
|
||||
"retry": "Retry",
|
||||
"action": "Go to Login"
|
||||
},
|
||||
"passkey": {
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { removeAuthCookies } from "$lib/server/utils/cookies";
|
||||
import { auth } from "$lib/stores/auth";
|
||||
import type { PageServerLoad } from "./$types";
|
||||
|
||||
export const load: PageServerLoad = async (event) => {
|
||||
const success: Promise<boolean> = event
|
||||
.fetch("/api/auth/logout", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "same-origin",
|
||||
})
|
||||
.then(async (resp) => {
|
||||
return resp.status < 400;
|
||||
})
|
||||
.finally(() => {
|
||||
removeAuthCookies(event);
|
||||
auth.reset();
|
||||
});
|
||||
|
||||
return { streaming: { success } };
|
||||
};
|
||||
@@ -8,15 +8,41 @@
|
||||
import { ROUTES } from "$lib/const/routes.js";
|
||||
import { auth } from "$lib/stores/auth.js";
|
||||
import { staffCrypto } from "$lib/stores/staff-crypto.js";
|
||||
import { TriangleAlert } from "@lucide/svelte";
|
||||
import Check from "@lucide/svelte/icons/check";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
const { data } = $props();
|
||||
let success: boolean | undefined = $state();
|
||||
|
||||
onMount(() => {
|
||||
auth.reset();
|
||||
staffCrypto.clear();
|
||||
logout();
|
||||
});
|
||||
|
||||
const logout = async () => {
|
||||
success = undefined;
|
||||
fetch("/api/auth/logout", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "same-origin",
|
||||
})
|
||||
.then(async (resp) => {
|
||||
if (resp.status === 200 || resp.status === 401) {
|
||||
success = true;
|
||||
} else {
|
||||
throw new Error(resp.statusText);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("Logout failed:", error);
|
||||
success = false;
|
||||
})
|
||||
.finally(() => {
|
||||
auth.reset();
|
||||
staffCrypto.clear();
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -29,24 +55,42 @@
|
||||
{/snippet}
|
||||
<CenteredCard.Root>
|
||||
<CenteredCard.Main>
|
||||
{#await data.streaming.success}
|
||||
{#if success === undefined}
|
||||
<CenterLoadingState />
|
||||
{:then}
|
||||
{:else if success === true}
|
||||
<CenterState
|
||||
Icon={Check}
|
||||
headline={m["logout.title"]()}
|
||||
description={m["logout.description"]()}
|
||||
headline={m["logout.success.title"]()}
|
||||
description={m["logout.success.description"]()}
|
||||
/>
|
||||
{/await}
|
||||
{:else}
|
||||
<CenterState
|
||||
Icon={TriangleAlert}
|
||||
headline={m["logout.error.title"]()}
|
||||
description={m["logout.error.description"]()}
|
||||
/>
|
||||
{/if}
|
||||
</CenteredCard.Main>
|
||||
<CenteredCard.Action>
|
||||
{#await data.streaming.success}
|
||||
{#if success === undefined}
|
||||
<Skeleton class="h-10 w-full" />
|
||||
{:then}
|
||||
{:else}
|
||||
{#if success === false}
|
||||
<Button
|
||||
size="lg"
|
||||
class="w-full"
|
||||
variant="outline"
|
||||
onclick={logout}
|
||||
isLoading={success === undefined}
|
||||
disabled={success === undefined}
|
||||
>
|
||||
{m["logout.retry"]()}
|
||||
</Button>
|
||||
{/if}
|
||||
<Button size="lg" class="w-full" href={ROUTES.LOGIN}>
|
||||
{m["logout.action"]()}
|
||||
</Button>
|
||||
{/await}
|
||||
{/if}
|
||||
</CenteredCard.Action>
|
||||
</CenteredCard.Root>
|
||||
</PageWithClaim>
|
||||
|
||||
Reference in New Issue
Block a user