feat: display passkey setup page for users coming from the login page

This commit is contained in:
Elias Schneider
2026-10-02 20:56:04 +02:00
parent c9681234dd
commit 4d2a5e423e
7 changed files with 86 additions and 24 deletions
+17 -4
View File
@@ -1,16 +1,21 @@
import StorageService from '#lib/services/storage-service.ts';
import VersionService from '#lib/services/version-service.ts';
import WebAuthnService from '#lib/services/webauthn-service.ts';
import type { AppVersionInformation } from '#lib/types/application-configuration.type.ts';
import { redirect } from '@sveltejs/kit';
import type { LayoutLoad } from './$types';
export const load: LayoutLoad = async () => {
export const load: LayoutLoad = async ({ url }) => {
const versionService = new VersionService();
const storageService = new StorageService();
const webauthnService = new WebAuthnService();
const currentVersion = versionService.getCurrentVersion();
const [newestVersion, sqliteStorageWarning] = await Promise.all([
const [newestVersion, sqliteStorageWarning, passkeys] = await Promise.all([
versionService.getNewestVersion().catch(() => null),
storageService.getSqliteStorageWarning().catch(() => false)
storageService.getSqliteStorageWarning().catch(() => false),
webauthnService.listCredentials()
]);
// If newestVersion is empty, it means the check is disabled or failed.
@@ -24,8 +29,16 @@ export const load: LayoutLoad = async () => {
isUpToDate
};
const skipPasskeySetup =
parseInt(localStorage.getItem('skip-passkey-setup-until') ?? '0') > Date.now();
if (!skipPasskeySetup && passkeys.length === 0 && url.pathname !== '/signup/add-passkey') {
redirect(303, '/signup/add-passkey');
}
return {
versionInformation,
sqliteStorageWarning
sqliteStorageWarning,
passkeys
};
};
@@ -1,18 +1,11 @@
import UserService from '#lib/services/user-service.ts';
import WebAuthnService from '#lib/services/webauthn-service.ts';
import type { PageLoad } from './$types';
export const load: PageLoad = async () => {
const webauthnService = new WebAuthnService();
const userService = new UserService();
const [account, passkeys] = await Promise.all([
userService.getCurrent(),
webauthnService.listCredentials()
]);
const account = await userService.getCurrent();
return {
account,
passkeys
account
};
};
+2 -2
View File
@@ -1,5 +1,4 @@
<script lang="ts">
import { goto } from '$app/navigation';
import SignInWrapper from '#lib/components/login-wrapper.svelte';
import SignupForm from '#lib/components/signup/signup-form.svelte';
import { Button } from '#lib/components/ui/button/index.ts';
@@ -10,6 +9,7 @@
import type { UserSignUp } from '#lib/types/user.type.ts';
import { getAxiosErrorMessage } from '#lib/utils/error-util.ts';
import { tryCatch } from '#lib/utils/try-catch-util.ts';
import { goto } from '$app/navigation';
import { LucideChevronLeft } from '@lucide/svelte';
import { onMount } from 'svelte';
import { fade } from 'svelte/transition';
@@ -30,7 +30,7 @@
await userStore.setUser(result.data);
goto('/signup/add-passkey');
goto('/');
return true;
}
@@ -1,5 +1,4 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { openConfirmDialog } from '#lib/components/confirm-dialog/index.ts';
import SignInWrapper from '#lib/components/login-wrapper.svelte';
import { Button } from '#lib/components/ui/button/index.ts';
@@ -7,6 +6,7 @@
import WebAuthnService from '#lib/services/webauthn-service.ts';
import { getWebauthnErrorMessage } from '#lib/utils/error-util.ts';
import { tryCatch } from '#lib/utils/try-catch-util.ts';
import { goto } from '$app/navigation';
import { startRegistration } from '@simplewebauthn/browser';
import { fade } from 'svelte/transition';
import LoginLogoErrorSuccessIndicator from '../../login/components/login-logo-error-success-indicator.svelte';
@@ -41,6 +41,7 @@
return;
}
dismiss();
goto('/settings/account');
isLoading = false;
}
@@ -53,11 +54,17 @@
label: m.skip_for_now(),
destructive: true,
action: () => {
dismiss();
goto('/settings/account');
}
}
});
}
function dismiss() {
const inOneDay = Date.now() + 24 * 60 * 60 * 1000;
localStorage.setItem('skip-passkey-setup-until', inOneDay.toString());
}
</script>
<svelte:head>
@@ -1,5 +1,4 @@
<script lang="ts">
import { goto } from '$app/navigation';
import SignInWrapper from '#lib/components/login-wrapper.svelte';
import SignupForm from '#lib/components/signup/signup-form.svelte';
import { Button } from '#lib/components/ui/button/index.ts';
@@ -10,6 +9,7 @@
import type { UserSignUp } from '#lib/types/user.type.ts';
import { getAxiosErrorMessage } from '#lib/utils/error-util.ts';
import { tryCatch } from '#lib/utils/try-catch-util.ts';
import { goto } from '$app/navigation';
import { fade } from 'svelte/transition';
import LoginLogoErrorSuccessIndicator from '../../login/components/login-logo-error-success-indicator.svelte';
@@ -27,7 +27,7 @@
await userStore.setUser(result.data);
goto('/signup/add-passkey');
goto('/');
return true;
}
</script>