diff --git a/src/App.svelte b/src/App.svelte
index d2149d1..41a186a 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -3,6 +3,15 @@
let connectionState = 'OFFLINE';
let serverVersion = '—';
let activeView = 'Live dashboard';
+ let sessionToken = '';
+ let authenticated = false;
+ let mustReplaceCredentials = false;
+ let username = '';
+ let password = '';
+ let newUsername = '';
+ let newPassword = '';
+ let authError = '';
+ let authBusy = false;
async function checkServer() {
connectionState = 'CONNECTING';
@@ -16,6 +25,64 @@
connectionState = 'SERVER UNAVAILABLE';
}
}
+
+ async function login() {
+ authBusy = true;
+ authError = '';
+ try {
+ const response = await fetch(`${serverAddress}/api/v1/auth/login`, {
+ method: 'POST',
+ headers: { 'content-type': 'application/json' },
+ body: JSON.stringify({ username, password }),
+ });
+ if (!response.ok) throw new Error('Your username or password may be incorrect.');
+ const result: { session_token: string; must_replace_credentials: boolean } = await response.json();
+ sessionToken = result.session_token;
+ authenticated = true;
+ mustReplaceCredentials = result.must_replace_credentials;
+ connectionState = 'CONNECTED';
+ if (!mustReplaceCredentials) password = '';
+ if (mustReplaceCredentials) newUsername = username;
+ } catch (error) {
+ authError = error instanceof Error ? error.message : 'The server could not process the login.';
+ authenticated = false;
+ } finally {
+ authBusy = false;
+ }
+ }
+
+ async function replaceCredentials() {
+ authBusy = true;
+ authError = '';
+ try {
+ const response = await fetch(`${serverAddress}/api/v1/auth/credentials`, {
+ method: 'POST',
+ headers: { 'content-type': 'application/json', authorization: `Bearer ${sessionToken}` },
+ body: JSON.stringify({ current_password: password, username: newUsername, password: newPassword }),
+ });
+ if (!response.ok) throw new Error(response.status === 400 ? 'Use a username and a password of at least 10 characters.' : 'Credential replacement failed.');
+ sessionToken = '';
+ authenticated = false;
+ mustReplaceCredentials = false;
+ username = newUsername;
+ password = '';
+ newPassword = '';
+ authError = 'Credentials updated. Sign in again.';
+ } catch (error) {
+ authError = error instanceof Error ? error.message : 'Credential replacement failed.';
+ } finally {
+ authBusy = false;
+ }
+ }
+
+ async function logout() {
+ if (sessionToken) {
+ await fetch(`${serverAddress}/api/v1/auth/logout`, { method: 'POST', headers: { authorization: `Bearer ${sessionToken}` } }).catch(() => undefined);
+ }
+ sessionToken = '';
+ authenticated = false;
+ mustReplaceCredentials = false;
+ }