feat(web): improve /auth pages (#1969)

* feat(web): improve /auth pages

* invalidate load functions after login

* handle login server errors more graceful

* add loading state to oauth button
This commit is contained in:
Michel Heusschen
2023-03-15 22:38:29 +01:00
committed by GitHub
parent 04955a4123
commit 87d84b922f
10 changed files with 299 additions and 276 deletions

View File

@@ -1,23 +1,18 @@
export const prerender = false;
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { api } }) => {
try {
const { data: userInfo } = await api.userApi.getMyUserInfo();
if (userInfo.shouldChangePassword) {
return {
user: userInfo,
meta: {
title: 'Change Password'
}
};
} else {
throw redirect(302, '/photos');
}
} catch (e) {
throw redirect(302, '/auth/login');
export const load = (async ({ locals: { user } }) => {
if (!user) {
throw redirect(302, AppRoute.AUTH_LOGIN);
} else if (!user.shouldChangePassword) {
throw redirect(302, AppRoute.PHOTOS);
}
return {
user,
meta: {
title: 'Change Password'
}
};
}) satisfies PageServerLoad;

View File

@@ -1,21 +1,28 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { fade } from 'svelte/transition';
import ChangePasswordForm from '$lib/components/forms/change-password-form.svelte';
import FullscreenContainer from '$lib/components/shared-components/fullscreen-container.svelte';
import { AppRoute } from '$lib/constants';
import type { PageData } from './$types';
export let data: PageData;
const onSuccessHandler = async () => {
await fetch('auth/logout', { method: 'POST' });
await fetch(AppRoute.AUTH_LOGOUT, { method: 'POST' });
goto('/auth/login');
goto(AppRoute.AUTH_LOGIN);
};
</script>
<section class="h-screen w-screen flex place-items-center place-content-center">
<div in:fade={{ duration: 100 }} out:fade={{ duration: 100 }}>
<ChangePasswordForm user={data.user} on:success={onSuccessHandler} />
</div>
</section>
<FullscreenContainer title={data.meta.title}>
<p slot="message">
Hi {data.user.firstName}
{data.user.lastName} ({data.user.email}),
<br />
<br />
This is either the first time you are signing into the system or a request has been made to change
your password. Please enter the new password below.
</p>
<ChangePasswordForm user={data.user} on:success={onSuccessHandler} />
</FullscreenContainer>

View File

@@ -1,14 +1,32 @@
import { AppRoute } from '$lib/constants';
import { redirect } from '@sveltejs/kit';
import type { OAuthConfigResponseDto } from '@api';
import type { PageServerLoad } from './$types';
export const load = (async ({ locals: { api } }) => {
const { data } = await api.userApi.getUserCount(true);
if (data.userCount === 0) {
// Admin not registered
throw redirect(302, '/auth/register');
throw redirect(302, AppRoute.AUTH_REGISTER);
}
let authConfig: OAuthConfigResponseDto = {
passwordLoginEnabled: true,
enabled: false
};
try {
// TODO: Figure out how to get correct redirect URI server-side.
const { data } = await api.oauthApi.generateConfig({ redirectUri: '/' });
data.url = undefined;
authConfig = data;
} catch (err) {
console.error('[ERROR] login/+page.server.ts:', err);
}
return {
authConfig,
meta: {
title: 'Login'
}

View File

@@ -1,16 +1,22 @@
<script lang="ts">
import { goto } from '$app/navigation';
import { fade } from 'svelte/transition';
import LoginForm from '$lib/components/forms/login-form.svelte';
import FullscreenContainer from '$lib/components/shared-components/fullscreen-container.svelte';
import { AppRoute } from '$lib/constants';
import { loginPageMessage } from '$lib/constants';
import type { PageData } from './$types';
export let data: PageData;
</script>
<section
class="min-h-screen w-screen flex place-items-center place-content-center p-4"
transition:fade={{ duration: 100 }}
>
<FullscreenContainer title={data.meta.title} showMessage={!!loginPageMessage}>
<p slot="message">
{@html loginPageMessage}
</p>
<LoginForm
on:success={() => goto('/photos')}
on:first-login={() => goto('/auth/change-password')}
authConfig={data.authConfig}
on:success={() => goto(AppRoute.PHOTOS, { invalidateAll: true })}
on:first-login={() => goto(AppRoute.AUTH_CHANGE_PASSWORD)}
/>
</section>
</FullscreenContainer>

View File

@@ -1,7 +1,16 @@
<script lang="ts">
import AdminRegistrationForm from '$lib/components/forms/admin-registration-form.svelte';
import FullscreenContainer from '$lib/components/shared-components/fullscreen-container.svelte';
import type { PageData } from './$types';
export let data: PageData;
</script>
<section class="h-screen w-screen flex place-items-center place-content-center">
<FullscreenContainer title={data.meta.title}>
<p slot="message">
Since you are the first user on the system, you will be assigned as the Admin and are
responsible for administrative tasks, and additional users will be created by you.
</p>
<AdminRegistrationForm />
</section>
</FullscreenContainer>