From a8219611cbebbd27501d9f30c804979048b98107 Mon Sep 17 00:00:00 2001
From: ivarlovlie <git@ivarlovlie.no>
Date: Tue, 13 Dec 2022 14:48:11 +0100
Subject: feat: A whole slew of things

- Use a md5 hash of the session cookie value as key for session validity check
- Introduce global state
- Introduce a common interface for form logic, and implement it on the sign-in form
- Introduce static resolve() on all services instead of new-upping all over.
- Implement /portal on the frontend to support giving the frontend a inital context from server or anywhere.
- Show a notification when users sign in for the first time after validating their email
---
 .../routes/(main)/(public)/sign-in/+page.svelte    | 106 +++++++++++----------
 1 file changed, 54 insertions(+), 52 deletions(-)

(limited to 'code/app/src/routes/(main)/(public)/sign-in/+page.svelte')

diff --git a/code/app/src/routes/(main)/(public)/sign-in/+page.svelte b/code/app/src/routes/(main)/(public)/sign-in/+page.svelte
index c4ecb1a..66d4575 100644
--- a/code/app/src/routes/(main)/(public)/sign-in/+page.svelte
+++ b/code/app/src/routes/(main)/(public)/sign-in/+page.svelte
@@ -8,62 +8,62 @@
     import { AccountService } from "$services/account-service";
     import type { LoginPayload } from "$services/abstractions/IAccountService";
     import { FormError } from "$models/internal/FormError";
+    import type { IForm } from "$models/internal/IForm";
 
-    let loading = false;
-    let showErrorAlert = false;
     let messageType: SignInPageMessage | undefined = undefined;
 
-    const accountService = new AccountService();
-
-    const formData = {
-        username: {
-            value: "",
-            errors: [],
-        },
-        password: {
-            value: "",
-            errors: [],
+    const accountService = AccountService.resolve();
+    const form = {
+        fields: {
+            username: {
+                value: "",
+                errors: [],
+            },
+            password: {
+                value: "",
+                errors: [],
+            },
+            persist: {
+                value: false,
+                errors: [],
+            },
         },
-        persist: {
-            value: false,
-            errors: [],
-        },
-        as_payload(): LoginPayload {
+        error: new FormError(),
+        isLoading: false,
+        showError: false,
+        get_payload(): LoginPayload {
             return {
-                password: formData.password.value,
-                username: formData.username.value,
-                persist: !formData.persist.value,
+                password: form.fields.password.value,
+                username: form.fields.username.value,
+                persist: !form.fields.persist.value,
             };
         },
-    };
-
-    const formError = new FormError();
+        async submit_async() {
+            console.log("sadf");
+            form.error.set();
+            form.showError = form.error.has_error();
+            form.isLoading = true;
+            const loginResponse = await accountService.login_async(form.get_payload());
+            if (loginResponse.isLoggedIn) {
+                await goto("/home");
+            } else if (loginResponse.knownProblem) {
+                form.error.set_from_known_problem(loginResponse.knownProblem);
+            } else {
+                form.error.set($LL.unexpectedError(), $LL.tryAgainSoon());
+            }
+            form.isLoading = false;
+            form.showError = form.error.has_error();
+        },
+    } as IForm;
 
     onMount(() => {
-        const searcher = new URLSearchParams(window.location.search);
-        if (searcher.get(signInPageMessageQueryKey)) {
-            messageType = searcher.get(signInPageMessageQueryKey) as SignInPageMessage;
-            searcher.delete(signInPageMessageQueryKey);
-            history.replaceState(null, "", window.location.origin + window.location.pathname);
+        const queryParams = new URLSearchParams(window.location.search);
+        if (queryParams.get(signInPageMessageQueryKey)) {
+            messageType = queryParams.get(signInPageMessageQueryKey) as SignInPageMessage;
+            queryParams.delete(signInPageMessageQueryKey);
+            window.history.replaceState(null, "", window.location.origin + window.location.pathname);
         }
     });
-
-    async function submit_form_async() {
-        formError.set();
-        showErrorAlert = formError.has_error();
-        loading = true;
-        const loginResponse = await accountService.login_async(formData.as_payload());
-        if (loginResponse.isLoggedIn) {
-            await goto("/home");
-        } else if (loginResponse.knownProblem) {
-            formError.set_from_known_problem(loginResponse.knownProblem);
-        } else {
-            formError.title = $LL.unexpectedError();
-            formError.subtitle = $LL.tryAgainSoon();
-        }
-        loading = false;
-        showErrorAlert = formError.has_error();
-    }
 </script>
 
 <div class="min-h-full flex flex-col justify-center py-12 sm:px-6 lg:px-8">
@@ -106,10 +106,10 @@
     </div>
     <div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
         <div class="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
-            {#if showErrorAlert}
-                <Alert title={formError.title} message={formError.subtitle} type="error" _pwKey={signInPageTestKeys.formErrorAlert} />
+            {#if form.showError}
+                <Alert title={form.error.title} message={form.error.subtitle} type="error" _pwKey={signInPageTestKeys.formErrorAlert} />
             {/if}
-            <form class="space-y-6 mt-2" use:pwKey={signInPageTestKeys.signInForm} on:submit|preventDefault={submit_form_async}>
+            <form class="space-y-6 mt-2" use:pwKey={signInPageTestKeys.signInForm} on:submit|preventDefault={() => form.submit_async()}>
                 <Input
                     id="username"
                     _pwKey={signInPageTestKeys.usernameInput}
@@ -117,7 +117,8 @@
                     type="email"
                     label={$LL.emailAddress()}
                     required
-                    bind:value={formData.username.value}
+                    errors={form.fields.username.errors}
+                    bind:value={form.fields.username.value}
                 />
 
                 <Input
@@ -128,7 +129,8 @@
                     _pwKey={signInPageTestKeys.passwordInput}
                     autocomplete="current-password"
                     required
-                    bind:value={formData.password.value}
+                    errors={form.fields.password.errors}
+                    bind:value={form.fields.password.value}
                 />
 
                 <div class="flex items-center justify-between">
@@ -136,7 +138,7 @@
                         id="remember-me"
                         _pwKey={signInPageTestKeys.rememberMeCheckbox}
                         name="remember-me"
-                        bind:checked={formData.persist.value}
+                        bind:checked={form.fields.persist.value}
                         label={$LL.signInPage.notMyComputer()}
                     />
                     <div class="text-sm">
@@ -146,7 +148,7 @@
                     </div>
                 </div>
 
-                <Button text={$LL.submit()} fullWidth type="submit" {loading} />
+                <Button text={$LL.submit()} fullWidth type="submit" loading={form.isLoading} />
             </form>
         </div>
     </div>
-- 
cgit v1.3

