diff options
Diffstat (limited to 'code/app/src/routes')
4 files changed, 105 insertions, 82 deletions
diff --git a/code/app/src/routes/(api)/delete-cookie/+server.ts b/code/app/src/routes/(api)/delete-cookie/+server.ts new file mode 100644 index 0000000..ee5e1dc --- /dev/null +++ b/code/app/src/routes/(api)/delete-cookie/+server.ts @@ -0,0 +1,8 @@ +import type { RequestHandler } from './$types'; + +export const GET: RequestHandler = async ({ cookies, url }) => { + const cookieToDelete = url.searchParams.get("key"); + if (!cookieToDelete || cookies.get(cookieToDelete) === undefined) return; + cookies.delete(cookieToDelete) + return new Response(); +};
\ No newline at end of file diff --git a/code/app/src/routes/(main)/(public)/reset-password/+page.svelte b/code/app/src/routes/(main)/(public)/reset-password/+page.svelte index 4d0288f..8bda3dc 100644 --- a/code/app/src/routes/(main)/(public)/reset-password/+page.svelte +++ b/code/app/src/routes/(main)/(public)/reset-password/+page.svelte @@ -1,13 +1,12 @@ <script lang="ts"> import { Alert, Input, Button } from "$lib/components"; - import X from "$lib/components/icons/x.svelte"; import LL from "$lib/i18n/i18n-svelte"; import { PasswordResetService } from "$lib/services/password-reset-service"; const formData = { email: { value: "", - error: "", + errors: [], }, }; @@ -20,27 +19,31 @@ }, }; - const service = new PasswordResetService(); + const resetRequests = new PasswordResetService(); let loading = false; let showSuccessAlert = false; - $: showErrorAlert = formError.title || (formError.subtitle && !showSuccessAlert); + $: showErrorAlert = (formError.title !== "" || formError.subtitle !== "") && !showSuccessAlert; async function submitFormAsync() { formError.set(); showSuccessAlert = false; loading = true; - const response = await service.create_request_async(formData.email.value); + const response = await resetRequests.create_request_async(formData.email.value); loading = false; if (response.isCreated) { showSuccessAlert = true; - return; - } - if (response.knownProblem) { + } else if (response.knownProblem) { if (response.knownProblem.title) formError.title = response.knownProblem.title; if (response.knownProblem.subtitle) formError.subtitle = response.knownProblem.subtitle; - for (const error of response.knownProblem.errors) { + for (const error of Object.entries(response.knownProblem.errors)) { + if (error[0] === "email") { + error[1].forEach(formData.email.errors.push); + } } + } else { + formError.title = $LL.unexpectedError(); + formError.subtitle = $LL.tryAgainSoon(); } } </script> @@ -61,7 +64,7 @@ <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"> <form class="space-y-6" on:submit|preventDefault={submitFormAsync}> - <Alert title={errorData.title} message={errorData.text} type="error" visible={showErrorAlert} /> + <Alert title={formError.title} message={formError.subtitle} type="error" visible={showErrorAlert} /> <Alert type="success" @@ -75,8 +78,9 @@ name="email" type="email" autocomplete="email" + errors={formData.email.errors} required - bind:value={formData.email} + bind:value={formData.email.value} label={$LL.emailAddress()} /> <Button text={$LL.submit()} type="submit" {loading} fullWidth /> diff --git a/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.svelte b/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.svelte index 3710290..2026764 100644 --- a/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.svelte +++ b/code/app/src/routes/(main)/(public)/reset-password/[id]/+page.svelte @@ -1,26 +1,22 @@ <script lang="ts"> - import { check_forgot_password_request, fulfill_forgot_password_request } from "$lib/api/account"; import { onMount } from "svelte"; import LL from "$lib/i18n/i18n-svelte"; import { Alert, Input, Button } from "$lib/components"; import type { PageServerData } from "./$types"; - import type { ErrorResult } from "$lib/models/internal/ErrorResult"; import { goto } from "$app/navigation"; - import { Message, messageQueryKey } from "$routes/(main)/(public)/sign-in"; + import { SignInPageMessage, signInPageMessageQueryKey } from "$routes/(main)/(public)/sign-in"; + import { PasswordResetService } from "$lib/services/password-reset-service"; export let data: PageServerData; - + const service = new PasswordResetService(); const formData = { - newPassword: "", + newPassword: { + value: "", + errors: [], + }, }; - const errorData = { - text: "", - title: "", - } as ErrorResult; - let errorState: undefined | "expired" | "404" | "unknown"; - let finishedPreliminaryLoading = false; let loading = false; let canSubmit = true; @@ -28,18 +24,18 @@ async function submitFormAsync() { if (!canSubmit) return; loading = true; - const request = await fulfill_forgot_password_request(data.resetRequestId, formData.newPassword); - if (request.ok) { - goto("/sign-in?" + messageQueryKey + "=" + Message.AFTER_PASSWORD_RESET); + const request = await service.fulfill_request_async(data.resetRequestId, formData.newPassword.value); + if (request.isFulfilled) { + goto("/sign-in?" + signInPageMessageQueryKey + "=" + SignInPageMessage.AFTER_PASSWORD_RESET); + } else if (request.knownProblem) { } - loading = false; } onMount(async () => { errorState = undefined; - const isValidRequest = await check_forgot_password_request(data.resetRequestId); - if (!isValidRequest.ok && isValidRequest.status !== 404) { + const isValidRequest = await service.request_is_valid_async(data.resetRequestId); + if (!isValidRequest.isValid) { errorState = "unknown"; canSubmit = false; } 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 5e2cb56..01c65dd 100644 --- a/code/app/src/routes/(main)/(public)/sign-in/+page.svelte +++ b/code/app/src/routes/(main)/(public)/sign-in/+page.svelte @@ -1,26 +1,44 @@ <script lang="ts"> - import {goto} from "$app/navigation"; - import {http_account} from "$lib/api/account"; - import {Button, Checkbox, Input, Alert} from "$lib/components"; + import { goto } from "$app/navigation"; + import { http_account } from "$lib/api/account"; + import { Button, Checkbox, Input, Alert } from "$lib/components"; import LL from "$lib/i18n/i18n-svelte"; import pwKey from "$actions/pwKey"; - import {isOk} from "rustic"; - import {onMount} from "svelte"; - import {signInPageMessageQueryKey, signInPageTestKeys, type SignInPageMessage} from "."; + import { isOk } from "rustic"; + import { onMount } from "svelte"; + import { signInPageMessageQueryKey, signInPageTestKeys, type SignInPageMessage } from "."; + import { AccountService } from "$lib/services/account-service"; + import type { LoginPayload } from "$lib/services/abstractions/IAccountService"; let loading = false; let messageType: SignInPageMessage | undefined = undefined; - const data = { - username: "", - password: "", - persist: true, - } as LoginPayload; + const accountService = new AccountService(); - let errorData = { - text: "", + const formData = { + username: { + value: "", + errors: [], + }, + password: { + value: "", + errors: [], + }, + persist: { + value: false, + errors: [], + }, + }; + + const formError = { title: "", - } as ErrorResult; + subtitle: "", + set(title = "", subtitle = "") { + formError.title = title; + formError.subtitle = subtitle; + }, + }; + $: showErrorAlert = (errorData.text?.length ?? 0 + errorData.title?.length ?? 0) > 0; onMount(() => { @@ -33,7 +51,7 @@ }); async function submitFormAsync() { - errorData = {text: "", title: ""}; + errorData = { text: "", title: "" }; loading = true; data.persist = !data.persist; const loginResponse = await http_account.login_async(data); @@ -56,24 +74,24 @@ <div class="sm:max-w-md sm:mx-auto sm:w-full"> {#if messageType === "after-password-reset"} <Alert - title={$LL.signInPage.yourNewPasswordIsApplied()} - _pwKey={signInPageTestKeys.afterPasswordResetAlert} - message={$LL.signInPage.signInBelow()} - closeable + title={$LL.signInPage.yourNewPasswordIsApplied()} + _pwKey={signInPageTestKeys.afterPasswordResetAlert} + message={$LL.signInPage.signInBelow()} + closeable /> {:else if messageType === "user-disabled"} <Alert - title={$LL.signInPage.yourAccountIsDisabled()} - _pwKey={signInPageTestKeys.userDisabledAlert} - message={$LL.signInPage.contactYourAdminIfDisabled()} - closeable + title={$LL.signInPage.yourAccountIsDisabled()} + _pwKey={signInPageTestKeys.userDisabledAlert} + message={$LL.signInPage.contactYourAdminIfDisabled()} + closeable /> {:else if messageType === "user-inactivity"} <Alert - title={$LL.signInPage.youHaveReachedInactivityLimit()} - _pwKey={signInPageTestKeys.userInactivityAlert} - message={$LL.signInPage.feelFreeToSignInAgain()} - closeable + title={$LL.signInPage.youHaveReachedInactivityLimit()} + _pwKey={signInPageTestKeys.userInactivityAlert} + message={$LL.signInPage.feelFreeToSignInAgain()} + closeable /> {/if} </div> @@ -84,46 +102,43 @@ </h2> <p class="mt-2 text-sm text-gray-600"> {$LL.or().toLowerCase()} - <a href="/sign-up" use:pwKey={signInPageTestKeys.signUpAnchor} - class="link">{$LL.createANewAccount().toLowerCase()}</a> + <a href="/sign-up" use:pwKey={signInPageTestKeys.signUpAnchor} class="link">{$LL.createANewAccount().toLowerCase()}</a> </p> </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={errorData.title} message={errorData.text} type="error" - _pwKey={signInPageTestKeys.formErrorAlert}/> + <Alert title={errorData.title} message={errorData.text} type="error" _pwKey={signInPageTestKeys.formErrorAlert} /> {/if} - <form class="space-y-6 mt-2" use:pwKey={signInPageTestKeys.signInForm} - on:submit|preventDefault={submitFormAsync}> + <form class="space-y-6 mt-2" use:pwKey={signInPageTestKeys.signInForm} on:submit|preventDefault={submitFormAsync}> <Input - id="username" - _pwKey={signInPageTestKeys.usernameInput} - name="username" - type="email" - label={$LL.emailAddress()} - required - bind:value={data.username} + id="username" + _pwKey={signInPageTestKeys.usernameInput} + name="username" + type="email" + label={$LL.emailAddress()} + required + bind:value={data.username} /> <Input - id="password" - name="password" - type="password" - label={$LL.password()} - _pwKey={signInPageTestKeys.passwordInput} - autocomplete="current-password" - required - bind:value={data.password} + id="password" + name="password" + type="password" + label={$LL.password()} + _pwKey={signInPageTestKeys.passwordInput} + autocomplete="current-password" + required + bind:value={data.password} /> <div class="flex items-center justify-between"> <Checkbox - id="remember-me" - _pwKey={signInPageTestKeys.rememberMeCheckbox} - name="remember-me" - bind:checked={data.persist} - label={$LL.signInPage.notMyComputer()} + id="remember-me" + _pwKey={signInPageTestKeys.rememberMeCheckbox} + name="remember-me" + bind:checked={data.persist} + label={$LL.signInPage.notMyComputer()} /> <div class="text-sm"> <a href="/reset-password" class="link" use:pwKey={signInPageTestKeys.resetPasswordAnchor}> @@ -132,7 +147,7 @@ </div> </div> - <Button text={$LL.submit()} fullWidth type="submit" {loading}/> + <Button text={$LL.submit()} fullWidth type="submit" {loading} /> </form> </div> </div> |
