Phase 7: Auth & Security upgrade (JWT, 2FA, Login UI)

This commit is contained in:
Gan, Jimmy
2026-02-19 03:47:48 +08:00
parent f3db7d3654
commit 651bc0580e
12 changed files with 495 additions and 38 deletions
+73 -19
View File
@@ -5,31 +5,85 @@
import Gitea from "./routes/Gitea.svelte";
import Files from "./routes/Files.svelte";
import Terminal from "./routes/Terminal.svelte";
import Login from "./routes/Login.svelte";
import { onMount } from "svelte";
import { getToken, checkAuth, setToken } from "./lib/api.js";
let page = $state("dashboard");
let dark = $state(false);
let authorized = $state(false);
let loading = $state(true);
onMount(async () => {
// Theme init
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
dark = true;
document.documentElement.classList.add('dark');
} else {
dark = false;
document.documentElement.classList.remove('dark');
}
// Auth check
const token = getToken();
if (!token) {
loading = false;
authorized = false;
return;
}
try {
await checkAuth();
authorized = true;
} catch (e) {
console.error("Auth check failed:", e);
setToken("");
authorized = false;
} finally {
loading = false;
}
});
function toggleTheme() {
dark = !dark;
document.documentElement.classList.toggle("dark", dark);
if (dark) {
document.documentElement.classList.add("dark");
localStorage.theme = 'dark';
} else {
document.documentElement.classList.remove("dark");
localStorage.theme = 'light';
}
}
function logout() {
setToken("");
window.location.reload();
}
</script>
<div class="flex h-screen overflow-hidden bg-surface-50 {dark ? 'dark bg-surface-900' : ''}">
<Sidebar bind:page {dark} {toggleTheme} />
<main class="flex-1 overflow-auto">
<div class="max-w-[1400px] mx-auto p-6 lg:p-8">
{#if page === "dashboard"}
<Dashboard />
{:else if page === "docker"}
<Docker />
{:else if page === "gitea"}
<Gitea />
{:else if page === "files"}
<Files />
{:else if page === "terminal"}
<Terminal />
{/if}
</div>
</main>
</div>
{#if loading}
<div class="flex h-screen items-center justify-center bg-surface-50 dark:bg-surface-950">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary-600"></div>
</div>
{:else if !authorized}
<Login />
{:else}
<div class="flex h-screen overflow-hidden bg-surface-50 {dark ? 'dark bg-surface-900' : ''}">
<Sidebar bind:page {dark} {toggleTheme} {logout} />
<main class="flex-1 overflow-auto">
<div class="max-w-[1400px] mx-auto p-6 lg:p-8">
{#if page === "dashboard"}
<Dashboard />
{:else if page === "docker"}
<Docker />
{:else if page === "gitea"}
<Gitea />
{:else if page === "files"}
<Files />
{:else if page === "terminal"}
<Terminal />
{/if}
</div>
</main>
</div>
{/if}