auth: smart login/logout redirect back to original page
Some checks failed
CI / update (push) Failing after 0s

Login link now includes callbackUrl for the current page. Logout
redirects intelligently: stays on public pages, falls back to the
recipe detail for /edit/[name], to the recipe root for auth-only
sub-routes (add, favorites, to-try, admin), and to / for cospend.
This commit is contained in:
2026-02-26 19:25:43 +01:00
parent dd4680e946
commit 2f4c3ac1ae
3 changed files with 34 additions and 4 deletions

View File

@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte"; import { onMount } from "svelte";
import { page } from '$app/stores';
let { user, recipeLang = 'rezepte', lang = 'de' } = $props(); let { user, recipeLang = 'rezepte', lang = 'de' } = $props();
@@ -18,6 +19,29 @@
} }
}) })
}) })
function getLogoutCallbackUrl(pathname: string): string {
// Cospend has no public equivalent
if (pathname.startsWith('/cospend')) return '/';
// Match /rezepte or /recipes prefix
const m = pathname.match(/^\/(rezepte|recipes)(\/.*)?$/);
if (m) {
const base = `/${m[1]}`;
const rest = m[2] ?? '';
// /edit/[name] → the recipe detail page
const editMatch = rest.match(/^\/edit\/(.+)$/);
if (editMatch) return `${base}/${editMatch[1]}`;
// Auth-only sub-routes → recipe root
if (/^\/(add|favorites|to-try|admin|administration)(\/|$)/.test(rest))
return base;
}
// Public page: stay here
return pathname;
}
</script> </script>
<style> <style>
/* (A) SPEECH BOX */ /* (A) SPEECH BOX */
@@ -155,10 +179,10 @@ h2 + p{
<li><a href="/{recipeLang}/administration">Administration</a></li> <li><a href="/{recipeLang}/administration">Administration</a></li>
{/if} {/if}
<li><a href="https://sso.bocken.org/if/user/#/settings" >Einstellungen</a></li> <li><a href="https://sso.bocken.org/if/user/#/settings" >Einstellungen</a></li>
<li><a href="/logout" >Log Out</a></li> <li><a href="/logout?callbackUrl={encodeURIComponent(getLogoutCallbackUrl($page.url.pathname))}">Log Out</a></li>
</ul> </ul>
</div> </div>
</button> </button>
{:else} {:else}
<a class=entry href=/login>Login</a> <a class=entry href="/login?callbackUrl={encodeURIComponent($page.url.pathname + $page.url.search)}">Login</a>
{/if} {/if}

View File

@@ -6,7 +6,8 @@ export const load: PageServerLoad = async ({ fetch, locals, params }) => {
const session = await locals.auth(); const session = await locals.auth();
if (!session?.user?.nickname) { if (!session?.user?.nickname) {
throw redirect(302, `/${params.recipeLang}`); const callbackUrl = encodeURIComponent(`/${params.recipeLang}/favorites`);
throw redirect(302, `/login?callbackUrl=${callbackUrl}`);
} }
try { try {

View File

@@ -6,7 +6,12 @@ import { dbConnect } from '$utils/db';
export const load: PageServerLoad = async ({ locals, params }) => { export const load: PageServerLoad = async ({ locals, params }) => {
const session = await locals.auth(); const session = await locals.auth();
if (!session?.user?.groups?.includes('rezepte_users')) { if (!session?.user) {
const callbackUrl = encodeURIComponent(`/${params.recipeLang}/to-try`);
throw redirect(302, `/login?callbackUrl=${callbackUrl}`);
}
if (!session.user.groups?.includes('rezepte_users')) {
throw redirect(302, `/${params.recipeLang}`); throw redirect(302, `/${params.recipeLang}`);
} }