Skip to content

Commit 7ddf8aa

Browse files
QOL: make login page redirect to previous page on success
1 parent 8191780 commit 7ddf8aa

File tree

5 files changed

+88
-33
lines changed

5 files changed

+88
-33
lines changed

src/components/navbar/Navbar.svelte

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<script lang="ts">
2-
import { dev } from '$app/environment';
3-
import { goto } from '$app/navigation';
4-
import api from '$endpoints';
5-
import type { ConfigJson } from '$lib/server/data/config';
6-
import Separator from '$components/Separator.svelte';
2+
import { dev } from "$app/environment";
3+
import { goto } from "$app/navigation";
4+
import api from "$endpoints";
5+
import type { ConfigJson } from "$lib/server/data/config";
6+
import Separator from "$components/Separator.svelte";
77
8-
export let path: { url: string, txt: string }[];
8+
export let path: { url: string; txt: string }[];
99
export let config: ConfigJson;
1010
/** Whether the user is logged in. Set to undefined if auth is disabled */
1111
export let loggedIn: boolean | undefined;
@@ -16,16 +16,26 @@
1616
location.reload();
1717
}
1818
19+
/**
20+
* Go to the login page, with the from parameter determining the origin page.
21+
*/
22+
async function gotoLogin() {
23+
await goto(`/admin/login?from=${window.location.pathname}`);
24+
}
25+
1926
/** Clear all data, and take the user to the firstrun page */
2027
async function clear() {
2128
await api().debug.clear();
22-
await goto('/admin/firstrun');
29+
await goto("/admin/firstrun");
2330
}
2431
2532
// This function needs to accept `path` as an input, otherwise the links
2633
// stop being reactive due to cacheing or something
27-
function pathTo(path: { url: string, txt: string }[], i: number) {
28-
return path.slice(0, i + 1).map(p => p.url).join('/');
34+
function pathTo(path: { url: string; txt: string }[], i: number) {
35+
return path
36+
.slice(0, i + 1)
37+
.map((p) => p.url)
38+
.join("/");
2939
}
3040
</script>
3141

@@ -38,7 +48,7 @@
3848
<a href="/">{config.siteShortName}</a> /
3949
{#each path.slice(0, -1) as p, i}
4050
<a href="/{pathTo(path, i)}">{p.txt}</a>
41-
{'/ '}
51+
{"/ "}
4252
{/each}
4353
{path[path.length - 1].txt}
4454
</h1>
@@ -48,14 +58,14 @@
4858
<!-- Control buttons -->
4959
<span id="control-buttons">
5060
{#if loggedIn}
51-
<button on:click={() => goto('/admin')}> Admin </button>
61+
<button on:click={() => goto("/admin")}> Admin </button>
5262
<button on:click={logOut}> Log out </button>
5363
{:else if loggedIn !== undefined}
5464
<!-- Only include a login button if logging in is enabled -->
55-
<button on:click={() => goto('/admin/login')}> Log in </button>
65+
<button on:click={gotoLogin}> Log in </button>
5666
{/if}
5767
<!-- About button navigates to about page -->
58-
<button on:click={() => goto('/about')}> About </button>
68+
<button on:click={() => goto("/about")}> About </button>
5969
<!-- In dev mode, add a quick shortcut to delete everything -->
6070
{#if dev}
6171
<Separator />

src/routes/admin/+page.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import GitSettings from "./GitSettings.svelte";
77
import ChangePassword from "./ChangePassword.svelte";
88
import ReloadData from "./ReloadData.svelte";
9+
import LogOutAll from "./LogOutAll.svelte";
910
1011
export let data: import("./$types").PageData;
1112
</script>
@@ -32,6 +33,7 @@
3233
<div id="contents">
3334
<GitSettings {data} />
3435
<ChangePassword username={"admin"} />
36+
<LogOutAll />
3537
<ReloadData />
3638
</div>
3739
</Paper>

src/routes/admin/LogOutAll.svelte

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<script lang="ts">
2+
import { goto } from "$app/navigation";
3+
import api from "$endpoints";
4+
5+
async function logOut() {
6+
await api().admin.auth.revoke();
7+
goto("/admin/login");
8+
}
9+
</script>
10+
11+
<div>
12+
<h2>Log out of all sessions</h2>
13+
<p>This will sign you out on all of your devices (including this one).</p>
14+
<button on:click={logOut}>Log out of all sessions</button>
15+
</div>

src/routes/admin/login/+page.server.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ export async function load(req) {
1212
loggedIn = true;
1313
} catch { /* empty */ }
1414
if (loggedIn) {
15-
redirect(303, '/admin');
15+
// If they are logged in, redirect them to the `from` URL if it exists.
16+
redirect(303, req.url.searchParams.get("from") || '/');
1617
}
1718
const globals = await getPortfolioGlobals();
1819
return { globals };

src/routes/admin/login/+page.svelte

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,41 @@
11
<script lang="ts">
2-
import api from '$endpoints';
3-
import Background from '$components/Background.svelte';
4-
import Navbar from '$components/navbar/Navbar.svelte';
5-
import Paper from '$components/Paper.svelte';
6-
import { goto } from '$app/navigation';
7-
import consts from '$lib/consts';
2+
import api from "$endpoints";
3+
import Background from "$components/Background.svelte";
4+
import Navbar from "$components/navbar/Navbar.svelte";
5+
import Paper from "$components/Paper.svelte";
6+
import { goto } from "$app/navigation";
7+
import consts from "$lib/consts";
8+
import { onMount } from "svelte";
89
9-
export let data: import('./$types').PageData;
10+
export let data: import("./$types").PageData;
1011
11-
let username = '';
12-
let password = '';
12+
let previousPage: string;
13+
14+
let username = "";
15+
let password = "";
16+
17+
onMount(() => {
18+
previousPage =
19+
new URLSearchParams(window.location.search).get("from") || "/";
20+
// Avoid circular redirects
21+
if (previousPage.endsWith("/admin/login")) {
22+
previousPage = "/";
23+
}
24+
});
1325
1426
async function doLogin() {
1527
await api().admin.auth.login(username, password);
1628
// TODO: Cleanly handle and display errors
17-
await goto('/admin');
29+
await goto(previousPage);
1830
}
1931
</script>
2032

2133
<svelte:head>
2234
<title>login - {data.globals.config.siteName}</title>
23-
<meta name="generator" content="{consts.APP_NAME}">
24-
<meta name="theme-color" content="{data.globals.config.color}">
35+
<meta name="generator" content={consts.APP_NAME} />
36+
<meta name="theme-color" content={data.globals.config.color} />
2537
<!-- Prevent web crawlers from indexing the admin page -->
26-
<meta name="robots" content="noindex">
38+
<meta name="robots" content="noindex" />
2739
</svelte:head>
2840

2941
<Background color={data.globals.config.color}></Background>
@@ -32,26 +44,41 @@
3244
config={data.globals.config}
3345
loggedIn={false}
3446
path={[
35-
{ txt: 'Admin', url: 'admin' },
36-
{ txt: 'Login', url: 'login' },
47+
{ txt: "Admin", url: "admin" },
48+
{ txt: "Login", url: "login" },
3749
]}
3850
/>
3951

4052
<div class="center">
4153
<Paper>
4254
<main>
4355
<div class="center">
44-
<h1 style="font-size: 3rem"> Login </h1>
56+
<h1 style="font-size: 3rem">Login</h1>
4557
</div>
4658

4759
<form>
4860
<h3>Username</h3>
49-
<input type="text" id="username" bind:value={username} placeholder="Username" />
61+
<input
62+
type="text"
63+
id="username"
64+
bind:value={username}
65+
placeholder="Username"
66+
/>
5067

5168
<h3>Password</h3>
52-
<input type="password" id="password" bind:value={password} placeholder="Your complex and secure password" />
69+
<input
70+
type="password"
71+
id="password"
72+
bind:value={password}
73+
placeholder="Your complex and secure password"
74+
/>
5375
<p></p>
54-
<input type="submit" id="submit-main" value="Log in" on:click={doLogin} />
76+
<input
77+
type="submit"
78+
id="submit-main"
79+
value="Log in"
80+
on:click={doLogin}
81+
/>
5582
</form>
5683
</main>
5784
</Paper>

0 commit comments

Comments
 (0)