Compare commits
13 Commits
d3e7a3b4ae
...
a9e3d8264c
| Author | SHA1 | Date | |
|---|---|---|---|
| a9e3d8264c | |||
| 332a3e5c15 | |||
| 4fc6da850b | |||
| 36273fd426 | |||
| 793ddb17d6 | |||
| 349d2cea6a | |||
| 23f2feeefb | |||
| 48fe999b5b | |||
| c857041e21 | |||
| e26b36121a | |||
| 416118197b | |||
| 01afbea9a3 | |||
| 69422d1f92 |
@@ -21,7 +21,7 @@
|
|||||||
<h1 class="text-3xl text-slate-400 font-bold">Tatort</h1>
|
<h1 class="text-3xl text-slate-400 font-bold">Tatort</h1>
|
||||||
<div class="lg:flex lg:justify-end w-48">
|
<div class="lg:flex lg:justify-end w-48">
|
||||||
{#if data.user}
|
{#if data.user}
|
||||||
<form method="POST" action="{ROUTE_NAMES.ANMELDUNG_LOGOUT}">
|
<form method="POST" action="{ROUTE_NAMES.LOGOUT}">
|
||||||
<input type="hidden" />
|
<input type="hidden" />
|
||||||
<button type="submit" class="text-sm font-semibold leading-6 text-gray-900"
|
<button type="submit" class="text-sm font-semibold leading-6 text-gray-900"
|
||||||
><span
|
><span
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ export const loginUser = async ({ request, cookies }: { request: Request; cookie
|
|||||||
|
|
||||||
const token = authenticate(user, password);
|
const token = authenticate(user, password);
|
||||||
|
|
||||||
if (!token) return fail(400, { user, incorrect: true });
|
if (!token) return fail(400, { user, incorrect: true,
|
||||||
|
message: "Ungültige Zugangsdaten" });
|
||||||
|
|
||||||
cookies.set(COOKIE_NAME, token, {
|
cookies.set(COOKIE_NAME, token, {
|
||||||
path: ROUTE_NAMES.ROOT,
|
path: ROUTE_NAMES.ROOT,
|
||||||
@@ -26,5 +27,5 @@ export const loginUser = async ({ request, cookies }: { request: Request; cookie
|
|||||||
export const logoutUser = async (event: RequestEvent) => {
|
export const logoutUser = async (event: RequestEvent) => {
|
||||||
event.cookies.delete(COOKIE_NAME, { path: ROUTE_NAMES.ROOT });
|
event.cookies.delete(COOKIE_NAME, { path: ROUTE_NAMES.ROOT });
|
||||||
event.locals.user = null;
|
event.locals.user = null;
|
||||||
return { success: true };
|
return redirect(303, ROUTE_NAMES.ROOT);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { redirect, type ServerLoadEvent } from '@sveltejs/kit';
|
import { type ServerLoadEvent } from '@sveltejs/kit';
|
||||||
import type { PageServerLoad } from '../anmeldung/$types';
|
import type { PageServerLoad } from '../anmeldung/$types';
|
||||||
|
|
||||||
import { ROUTE_NAMES } from '..';
|
import { ROUTE_NAMES } from '..';
|
||||||
|
|
||||||
export const load: PageServerLoad = (event: ServerLoadEvent) => {
|
export const load: PageServerLoad = (event: ServerLoadEvent) => {
|
||||||
if (!event.locals.user && event.url.pathname !== ROUTE_NAMES.ANMELDUNG)
|
if (event.locals.user) {
|
||||||
throw redirect(303, ROUTE_NAMES.ANMELDUNG);
|
return {
|
||||||
return {
|
user: event.locals.user
|
||||||
user: event.locals.user
|
};
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
export let data;
|
export let data;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if data.user?.admin}
|
||||||
|
|
||||||
<div class="h-screen v-screen flex flex-col">
|
<div class="h-screen v-screen flex flex-col">
|
||||||
<div class="flex flex-col h-full">
|
<div class="flex flex-col h-full">
|
||||||
<Header {data}/>
|
<Header {data}/>
|
||||||
@@ -16,3 +18,10 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{:else}
|
||||||
|
|
||||||
|
<div class="h-screen bg-white"><slot /></div>
|
||||||
|
|
||||||
|
|
||||||
|
{/if}
|
||||||
6
src/routes/(angemeldet)/+page.server.ts
Normal file
6
src/routes/(angemeldet)/+page.server.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { loginUser, logoutUser } from '$lib/server/authService';
|
||||||
|
|
||||||
|
export const actions = {
|
||||||
|
login: ({ request, cookies }) => loginUser({ request, cookies }),
|
||||||
|
logout: (event) => logoutUser(event),
|
||||||
|
} as const;
|
||||||
@@ -2,18 +2,21 @@
|
|||||||
import AddProcess from '$lib/icons/Add-Process.svelte';
|
import AddProcess from '$lib/icons/Add-Process.svelte';
|
||||||
import FileRect from '$lib/icons/File-rect.svelte';
|
import FileRect from '$lib/icons/File-rect.svelte';
|
||||||
import ListIcon from '$lib/icons/List-icon.svelte';
|
import ListIcon from '$lib/icons/List-icon.svelte';
|
||||||
|
import Button from '$lib/components/Button.svelte';
|
||||||
|
import ArrowRight from '$lib/icons/Arrow-right.svelte';
|
||||||
|
|
||||||
import { ROUTE_NAMES } from '../index.js';
|
import { ROUTE_NAMES } from '../index.js';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
export let form;
|
||||||
export let outline = true;
|
export let outline = true;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if data.user?.admin}
|
||||||
<div
|
<div
|
||||||
class=" inset-x-0 top-0 -z-10 h-full flex items-center justify-center bg-white shadow-lg ring-1 ring-gray-900/5"
|
class=" inset-x-0 top-0 -z-10 h-full flex items-center justify-center bg-white shadow-lg ring-1 ring-gray-900/5"
|
||||||
>
|
>
|
||||||
<div class="mx-auto flex justify-center max-w-7xl py-10 px-8 w-full">
|
<div class="mx-auto flex justify-center max-w-7xl py-10 px-8 w-full">
|
||||||
{#if data.user.admin}
|
|
||||||
<div class="group relative rounded-lg p-6 text-sm leading-6 hover:bg-gray-50 w-1/4">
|
<div class="group relative rounded-lg p-6 text-sm leading-6 hover:bg-gray-50 w-1/4">
|
||||||
<div
|
<div
|
||||||
class="flex h-11 w-11 items-center justify-center rounded-lg bg-gray-50 group-hover:bg-white"
|
class="flex h-11 w-11 items-center justify-center rounded-lg bg-gray-50 group-hover:bg-white"
|
||||||
@@ -28,8 +31,6 @@
|
|||||||
Verschaffe Dir einen Überblick über alle gespeicherten Tatorte.
|
Verschaffe Dir einen Überblick über alle gespeicherten Tatorte.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
{#if data.user.admin}
|
|
||||||
<div class="group relative rounded-lg p-6 text-sm leading-6 hover:bg-gray-50 w-1/4">
|
<div class="group relative rounded-lg p-6 text-sm leading-6 hover:bg-gray-50 w-1/4">
|
||||||
<div
|
<div
|
||||||
class="flex h-11 w-11 items-center justify-center rounded-lg bg-gray-50 group-hover:bg-white"
|
class="flex h-11 w-11 items-center justify-center rounded-lg bg-gray-50 group-hover:bg-white"
|
||||||
@@ -42,7 +43,6 @@
|
|||||||
</a>
|
</a>
|
||||||
<p class="mt-1 text-gray-600">Fügen Sie einem Tatort Bilder hinzu.</p>
|
<p class="mt-1 text-gray-600">Fügen Sie einem Tatort Bilder hinzu.</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
<div class="group relative rounded-lg p-6 text-sm leading-6 hover:bg-gray-50 w-1/4">
|
<div class="group relative rounded-lg p-6 text-sm leading-6 hover:bg-gray-50 w-1/4">
|
||||||
<div
|
<div
|
||||||
class="flex h-11 w-11 items-center justify-center rounded-lg bg-gray-50 group-hover:bg-white"
|
class="flex h-11 w-11 items-center justify-center rounded-lg bg-gray-50 group-hover:bg-white"
|
||||||
@@ -58,5 +58,64 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{:else}
|
||||||
|
|
||||||
|
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
||||||
|
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||||
|
<img class="mx-auto h-10 w-auto" src="/Landeswappen_NI.svg" alt="Landeswappen Niedersachsen" />
|
||||||
|
|
||||||
|
<h2 class="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">
|
||||||
|
Willkommen beim 3D Tatort
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div class="w-full max-w-sm mx-auto">
|
||||||
|
<div class="relative mt-5 bg-gray-50 rounded-xl shadow-xl p-3 pt-1">
|
||||||
|
<div class="mt-10">
|
||||||
|
|
||||||
|
<form action="{ROUTE_NAMES.LOGIN}" method="POST">
|
||||||
|
<div>
|
||||||
|
<label for="user" class="text-sm font-medium leading-6 text-gray-900">Name</label>
|
||||||
|
<div class="mt-2">
|
||||||
|
<input
|
||||||
|
id="user"
|
||||||
|
name="user"
|
||||||
|
type="text"
|
||||||
|
autocomplete="email"
|
||||||
|
required
|
||||||
|
class="rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="password" class="block text-sm font-medium leading-6 text-gray-900"
|
||||||
|
>Passwort</label
|
||||||
|
>
|
||||||
|
<div class="mt-2">
|
||||||
|
<input
|
||||||
|
id="password"
|
||||||
|
name="password"
|
||||||
|
type="password"
|
||||||
|
autocomplete="current-password"
|
||||||
|
required
|
||||||
|
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{#if form?.incorrect}
|
||||||
|
<p class="block text-sm leading-6 text-red-900 mt-2">{form.message}</p>
|
||||||
|
{/if}
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<Button type="submit" class="mt-5">Anmelden</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { getVorgaenge } from '$lib/server/vorgangService';
|
import { getVorgaenge } from '$lib/server/vorgangService';
|
||||||
import type { PageServerLoad } from '../../(token-based)/view/$types';
|
import type { PageServerLoad } from '../../(token-based)/view/$types';
|
||||||
|
import { error } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async (event) => {
|
||||||
|
if (!event.locals.user) {
|
||||||
|
error(404, 'Not Found')
|
||||||
|
}
|
||||||
|
|
||||||
export const load: PageServerLoad = async () => {
|
|
||||||
const vorgangList = getVorgaenge();
|
const vorgangList = getVorgaenge();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
import { BUCKET, client } from '$lib/minio';
|
import { BUCKET, client } from '$lib/minio';
|
||||||
import { fail } from '@sveltejs/kit';
|
import { fail, error } from '@sveltejs/kit';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
import { db } from '$lib/server/dbService';
|
import { db } from '$lib/server/dbService';
|
||||||
@@ -123,3 +123,10 @@ export const actions = {
|
|||||||
return { etag, error };
|
return { etag, error };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async (event) => {
|
||||||
|
if (!event.locals.user) {
|
||||||
|
error(404, 'Not found')
|
||||||
|
}
|
||||||
|
};
|
||||||
8
src/routes/(angemeldet)/user-management/+page.server.ts
Normal file
8
src/routes/(angemeldet)/user-management/+page.server.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import type { PageServerLoad } from '../../(token-based)/view/$types';
|
||||||
|
import { error } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async (event) => {
|
||||||
|
if (!event.locals.user) {
|
||||||
|
error(404, 'Not Found')
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,19 +1,23 @@
|
|||||||
import { dev } from '$app/environment';
|
import { dev } from '$app/environment';
|
||||||
import { loginUser, logoutUser } from '$lib/server/authService';
|
import { error, fail, redirect } from '@sveltejs/kit';
|
||||||
import { redirect } from '@sveltejs/kit';
|
|
||||||
import { ROUTE_NAMES } from '../index.js';
|
import { ROUTE_NAMES } from '../index.js';
|
||||||
|
import { vorgangPINValidation } from '$lib/server/vorgangService.js';
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
login: ({ request, cookies }) => loginUser({ request, cookies }),
|
default: async ({ request, cookies }) => {
|
||||||
logout: (event) => logoutUser(event),
|
|
||||||
getVorgangByToken: async ({ request, cookies }) => {
|
|
||||||
const data = await request.formData();
|
const data = await request.formData();
|
||||||
const vorgangToken = data.get('vorgang-token');
|
const vorgangToken = data.get('vorgang-token');
|
||||||
const vorgangPIN = data.get('vorgang-pin');
|
const vorgangPIN = data.get('vorgang-pin') as string;
|
||||||
|
|
||||||
if (!vorgangToken || !vorgangPIN) return;
|
if (!vorgangPIN) {
|
||||||
|
return fail(400, { message: 'Bitte einen PIN eingeben.'});
|
||||||
|
}
|
||||||
|
|
||||||
const COOKIE_NAME = `token-${vorgangToken}`
|
if (!vorgangPINValidation(vorgangToken, vorgangPIN)) {
|
||||||
|
return fail(400, { message: 'Falsche Zugangsdaten.'});
|
||||||
|
}
|
||||||
|
|
||||||
|
const COOKIE_NAME = `token-${vorgangToken}`;
|
||||||
cookies.set(COOKIE_NAME, vorgangPIN, {
|
cookies.set(COOKIE_NAME, vorgangPIN, {
|
||||||
path: '/',
|
path: '/',
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
@@ -24,3 +28,8 @@ export const actions = {
|
|||||||
throw redirect(303, ROUTE_NAMES.VORGANG(vorgangToken));
|
throw redirect(303, ROUTE_NAMES.VORGANG(vorgangToken));
|
||||||
}
|
}
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const load: PageServerLoad = async ({ url }) => {
|
||||||
|
const vorgang = url.searchParams.get('vorgang');
|
||||||
|
if (!vorgang) error(404, "Not Found");
|
||||||
|
};
|
||||||
@@ -1,22 +1,15 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import BaseInputField from '$lib/components/BaseInputField.svelte';
|
import BaseInputField from '$lib/components/BaseInputField.svelte';
|
||||||
import Button from '$lib/components/Button.svelte';
|
import Button from '$lib/components/Button.svelte';
|
||||||
import Modal from '$lib/components/Modal/Modal.svelte';
|
|
||||||
import ModalContent from '$lib/components/Modal/ModalContent.svelte';
|
|
||||||
import ModalFooter from '$lib/components/Modal/ModalFooter.svelte';
|
|
||||||
import ModalTitle from '$lib/components/Modal/ModalTitle.svelte';
|
|
||||||
import ArrowRight from '$lib/icons/Arrow-right.svelte';
|
import ArrowRight from '$lib/icons/Arrow-right.svelte';
|
||||||
import Login from '$lib/icons/Login.svelte';
|
|
||||||
|
|
||||||
export let form;
|
export let form;
|
||||||
|
|
||||||
export let open = false;
|
|
||||||
|
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import { ROUTE_NAMES } from '../index.js';
|
import { ROUTE_NAMES } from '../index.js';
|
||||||
const vorgangToken = page.url.searchParams.get('vorgang');
|
const vorgangToken = page.url.searchParams.get('vorgang');
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if vorgangToken}
|
||||||
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
||||||
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
|
||||||
<img class="mx-auto h-10 w-auto" src="/Landeswappen_NI.svg" alt="Landeswappen Niedersachsen" />
|
<img class="mx-auto h-10 w-auto" src="/Landeswappen_NI.svg" alt="Landeswappen Niedersachsen" />
|
||||||
@@ -28,73 +21,30 @@
|
|||||||
<div class="w-full max-w-sm mx-auto">
|
<div class="w-full max-w-sm mx-auto">
|
||||||
<div class="relative mt-5 bg-gray-50 rounded-xl shadow-xl p-3 pt-1">
|
<div class="relative mt-5 bg-gray-50 rounded-xl shadow-xl p-3 pt-1">
|
||||||
<div class="mt-10">
|
<div class="mt-10">
|
||||||
<form action="{ROUTE_NAMES.ANMELDUNG_GET_VORGANG_BY_TOKEN}" method="POST">
|
|
||||||
<BaseInputField
|
<form method="POST">
|
||||||
id="vorgang-token"
|
<input type="hidden" name="vorgang-token" value={vorgangToken} />
|
||||||
name="vorgang-token"
|
<div class="mt-5">
|
||||||
label="Vorgangskennung"
|
<BaseInputField
|
||||||
type="text"
|
id="vorgang-pin"
|
||||||
value={vorgangToken}
|
name="vorgang-pin"
|
||||||
/>
|
label="Zugangs-PIN"
|
||||||
<div class="mt-5">
|
type="text"
|
||||||
<BaseInputField
|
value={form?.vorgangPIN}
|
||||||
id="vorgang-pin"
|
error={form?.error?.message}
|
||||||
name="vorgang-pin"
|
/>
|
||||||
label="Zugangs-PIN"
|
</div>
|
||||||
type="text"
|
{#if form?.message}
|
||||||
value={form?.vorgangPIN}
|
<p class="block text-sm leading-6 text-red-900 mt-2">{form.message}</p>
|
||||||
error={form?.error?.message}
|
{/if}
|
||||||
/>
|
|
||||||
</div>
|
<div class="flex justify-end pt-4">
|
||||||
<div class="flex justify-end pt-4">
|
<Button type="submit"><ArrowRight /></Button>
|
||||||
<Button type="submit"><ArrowRight /></Button>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end mt-10 px-3">
|
|
||||||
<Button on:click={() => (open = true)}><Login /></Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Modal {open}>
|
{/if}
|
||||||
<ModalTitle>Anmelden</ModalTitle>
|
|
||||||
<ModalContent class="flex justify-center">
|
|
||||||
<form action="{ROUTE_NAMES.ANMELDUNG_LOGIN}" method="POST">
|
|
||||||
<div>
|
|
||||||
<label for="user" class="text-sm font-medium leading-6 text-gray-900">Kennung</label>
|
|
||||||
<div class="mt-2">
|
|
||||||
<input
|
|
||||||
id="user"
|
|
||||||
name="user"
|
|
||||||
type="text"
|
|
||||||
autocomplete="email"
|
|
||||||
required
|
|
||||||
class="rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label for="password" class="block text-sm font-medium leading-6 text-gray-900"
|
|
||||||
>Passwort</label
|
|
||||||
>
|
|
||||||
<div class="mt-2">
|
|
||||||
<input
|
|
||||||
id="password"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
autocomplete="current-password"
|
|
||||||
required
|
|
||||||
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-end">
|
|
||||||
<Button type="submit" class="mt-5">Anmelden</Button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</ModalContent>
|
|
||||||
<ModalFooter><Button on:click={() => (open = false)}>Ok</Button></ModalFooter>
|
|
||||||
</Modal>
|
|
||||||
@@ -16,8 +16,8 @@ export const ROUTE_NAMES = {
|
|||||||
|
|
||||||
// Anmeldung: actions
|
// Anmeldung: actions
|
||||||
ANMELDUNG: '/anmeldung',
|
ANMELDUNG: '/anmeldung',
|
||||||
ANMELDUNG_LOGIN: '/anmeldung?/login',
|
LOGIN: '/?/login',
|
||||||
ANMELDUNG_LOGOUT: '/anmeldung?/logout',
|
LOGOUT: '/?/logout',
|
||||||
ANMELDUNG_GET_VORGANG_BY_TOKEN: '/anmeldung?/getVorgangByToken',
|
ANMELDUNG_GET_VORGANG_BY_TOKEN: '/anmeldung?/getVorgangByToken',
|
||||||
ANMELDUNG_VORGANG_PARAM: (vorgangToken: string) => `/anmeldung?vorgang=${vorgangToken}`
|
ANMELDUNG_VORGANG_PARAM: (vorgangToken: string) => `/anmeldung?vorgang=${vorgangToken}`
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,144 +1,143 @@
|
|||||||
import { describe, it, expect, vi } from 'vitest';
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
import { actions } from '$root/routes/anmeldung/+page.server';
|
// import { actions } from '$root/routes/anmeldung/+page.server';
|
||||||
import { load } from '$root/routes/(token-based)/+layout.server'
|
// import { load } from '$root/routes/(token-based)/+layout.server'
|
||||||
|
import { actions } from '../../src/routes/anmeldung/+page.server';
|
||||||
|
import { load } from '../../src/routes/(token-based)/+layout.server';
|
||||||
|
|
||||||
import { baseData } from '../fixtures';
|
import { baseData } from '../fixtures';
|
||||||
import { ROUTE_NAMES } from '../../src/routes';
|
import { ROUTE_NAMES } from '../../src/routes';
|
||||||
import { dev } from '$app/environment';
|
import { dev } from '$app/environment';
|
||||||
import { vorgangExists, vorgangPINValidation } from '$lib/server/vorgangService';
|
import { vorgangExists, vorgangPINValidation } from '$lib/server/vorgangService';
|
||||||
import { Redirect } from '@sveltejs/kit';
|
import type { Redirect } from '@sveltejs/kit';
|
||||||
|
|
||||||
vi.mock('$lib/server/vorgangService', () => ({
|
vi.mock('$lib/server/vorgangService', () => ({
|
||||||
vorgangExists: vi.fn(),
|
vorgangExists: vi.fn(),
|
||||||
vorgangPINValidation: vi.fn(),
|
vorgangPINValidation: vi.fn()
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('Vorgang Anzeige via Token', () => {
|
describe('Vorgang Anzeige via Token', () => {
|
||||||
it('Setze Cookie nach erfolgreicher Eingabe', async () => {
|
it('Setze Cookie nach erfolgreicher Eingabe', async () => {
|
||||||
// Mock formData
|
// Mock formData
|
||||||
const vorgObj = baseData.vorgang;
|
const vorgObj = baseData.vorgang;
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.set('vorgang-token', vorgObj.vorgangToken);
|
formData.set('vorgang-token', vorgObj.vorgangToken);
|
||||||
formData.set('vorgang-pin', vorgObj.vorgangPIN);
|
formData.set('vorgang-pin', vorgObj.vorgangPIN);
|
||||||
|
|
||||||
const mockRequest = {
|
const mockRequest = {
|
||||||
formData: vi.fn().mockResolvedValue(formData)
|
formData: vi.fn().mockResolvedValue(formData)
|
||||||
};
|
};
|
||||||
|
vi.mocked(vorgangPINValidation).mockReturnValueOnce(true);
|
||||||
|
|
||||||
const cookiesSet = vi.fn();
|
const cookiesSet = vi.fn();
|
||||||
|
|
||||||
const event = {
|
const event = {
|
||||||
request: mockRequest,
|
request: mockRequest,
|
||||||
cookies: {
|
cookies: {
|
||||||
set: cookiesSet
|
set: cookiesSet
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let thrownRedirect: Redirect | undefined;
|
let thrownRedirect: Redirect | undefined;
|
||||||
try {
|
try {
|
||||||
await actions.getVorgangByToken(event);
|
await actions.default(event);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
thrownRedirect = e as Redirect;
|
thrownRedirect = e as Redirect;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect bei erfolgreicher Eingabe
|
// Redirect bei erfolgreicher Eingabe
|
||||||
expect(thrownRedirect?.status).toBe(303);
|
expect(thrownRedirect?.status).toBe(303);
|
||||||
expect(thrownRedirect?.location).toBe(ROUTE_NAMES.VORGANG(vorgObj.vorgangToken));
|
expect(thrownRedirect?.location).toBe(ROUTE_NAMES.VORGANG(vorgObj.vorgangToken));
|
||||||
|
|
||||||
// Cookie wurde gesetzt
|
// Cookie wurde gesetzt
|
||||||
const COOKIE_NAME = `token-${vorgObj.vorgangToken}`
|
const COOKIE_NAME = `token-${vorgObj.vorgangToken}`;
|
||||||
expect(cookiesSet).toHaveBeenCalledWith(COOKIE_NAME, vorgObj.vorgangPIN, {
|
expect(cookiesSet).toHaveBeenCalledWith(COOKIE_NAME, vorgObj.vorgangPIN, {
|
||||||
path: '/',
|
path: '/',
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
sameSite: 'strict',
|
sameSite: 'strict',
|
||||||
secure: !dev
|
secure: !dev
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Schlägt fehl wenn keine Daten übergeben werden', async () => {
|
it('Schlägt fehl wenn keine Daten übergeben werden', async () => {
|
||||||
const formData = new FormData(); // no data
|
const formData = new FormData(); // no data
|
||||||
|
const mockRequest = {
|
||||||
const mockRequest = {
|
formData: vi.fn().mockResolvedValue(formData)
|
||||||
formData: vi.fn().mockResolvedValue(formData)
|
};
|
||||||
};
|
const cookiesSet = vi.fn();
|
||||||
|
const event = {
|
||||||
const cookiesSet = vi.fn();
|
request: mockRequest,
|
||||||
|
cookies: {
|
||||||
const event = {
|
set: cookiesSet
|
||||||
request: mockRequest,
|
}
|
||||||
cookies: {
|
};
|
||||||
set: cookiesSet
|
const result = await actions.default(event);
|
||||||
}
|
expect(result.status).toBe(400);
|
||||||
};
|
expect(result.data.message).toMatch(/PIN eingeben/i);
|
||||||
|
// Cookie wird nicht gesetzt
|
||||||
const result = await actions.getVorgangByToken(event);
|
expect(cookiesSet).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
expect(result).toBeUndefined();
|
it.todo('Überprüfe was passiert, wenn Eingabe falsch, bzw. nicht im System passend gefunden');
|
||||||
|
|
||||||
// Cookie wird nicht gesetzt
|
|
||||||
expect(cookiesSet).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Teste Guard', () => {
|
describe('Teste Guard', () => {
|
||||||
it('Lese Cookie aus', async () => {
|
it('Lese Cookie aus', async () => {
|
||||||
const vorgObj = baseData.vorgang;
|
const vorgObj = baseData.vorgang;
|
||||||
|
|
||||||
const COOKIE_NAME = `token-${vorgObj.vorgangToken}`
|
const COOKIE_NAME = `token-${vorgObj.vorgangToken}`;
|
||||||
const cookiesGet = vi.fn().mockImplementation((key: string) => {
|
const cookiesGet = vi.fn().mockImplementation((key: string) => {
|
||||||
if (key === COOKIE_NAME) return vorgObj.vorgangPIN;
|
if (key === COOKIE_NAME) return vorgObj.vorgangPIN;
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// mocked objects
|
||||||
|
const event = {
|
||||||
|
cookies: {
|
||||||
|
get: cookiesGet
|
||||||
|
},
|
||||||
|
locals: {},
|
||||||
|
params: { vorgang: vorgObj.vorgangToken }
|
||||||
|
};
|
||||||
|
vi.mocked(vorgangExists).mockReturnValueOnce(true);
|
||||||
|
vi.mocked(vorgangPINValidation).mockReturnValueOnce(true);
|
||||||
|
|
||||||
// mocked objects
|
await load(event);
|
||||||
const event = {
|
|
||||||
cookies: {
|
|
||||||
get: cookiesGet
|
|
||||||
},
|
|
||||||
locals: {},
|
|
||||||
params: {vorgang: vorgObj.vorgangToken}
|
|
||||||
};
|
|
||||||
vi.mocked(vorgangExists).mockReturnValueOnce(true);
|
|
||||||
vi.mocked(vorgangPINValidation).mockReturnValueOnce(true);
|
|
||||||
|
|
||||||
await load(event);
|
expect(cookiesGet).toHaveBeenCalledWith(COOKIE_NAME);
|
||||||
|
});
|
||||||
|
|
||||||
expect(cookiesGet).toHaveBeenCalledWith(COOKIE_NAME);
|
it('Kein Cookie gesetzt', async () => {
|
||||||
});
|
const vorgObj = baseData.vorgang;
|
||||||
|
|
||||||
it('Kein Cookie gesetzt', async () => {
|
const COOKIE_NAME = `token-${vorgObj.vorgangToken}`;
|
||||||
const vorgObj = baseData.vorgang;
|
const cookiesGet = vi.fn().mockImplementation((key: string) => {
|
||||||
|
if (key === COOKIE_NAME) return vorgObj.vorgangPIN;
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
|
||||||
const COOKIE_NAME = `token-${vorgObj.vorgangToken}`
|
// mocked objects
|
||||||
const cookiesGet = vi.fn().mockImplementation((key: string) => {
|
const event = {
|
||||||
if (key === COOKIE_NAME) return vorgObj.vorgangPIN;
|
cookies: {
|
||||||
return undefined;
|
get: cookiesGet
|
||||||
});
|
},
|
||||||
|
locals: {},
|
||||||
|
params: { vorgang: vorgObj.vorgangToken }
|
||||||
|
};
|
||||||
|
vi.mocked(vorgangExists).mockReturnValueOnce(true);
|
||||||
|
vi.mocked(vorgangPINValidation).mockReturnValueOnce(false);
|
||||||
|
|
||||||
|
let thrownRedirect;
|
||||||
|
try {
|
||||||
|
await load(event);
|
||||||
|
throw new Error('Function did not throw');
|
||||||
|
} catch (e) {
|
||||||
|
thrownRedirect = e;
|
||||||
|
}
|
||||||
|
expect(thrownRedirect?.status).toBe(303);
|
||||||
|
expect(thrownRedirect?.location).toBe(
|
||||||
|
ROUTE_NAMES.ANMELDUNG_VORGANG_PARAM(vorgObj.vorgangToken)
|
||||||
|
);
|
||||||
|
|
||||||
// mocked objects
|
expect(cookiesGet).toHaveBeenCalledWith(COOKIE_NAME);
|
||||||
const event = {
|
});
|
||||||
cookies: {
|
|
||||||
get: cookiesGet
|
|
||||||
},
|
|
||||||
locals: {},
|
|
||||||
params: {vorgang: vorgObj.vorgangToken}
|
|
||||||
};
|
|
||||||
vi.mocked(vorgangExists).mockReturnValueOnce(true);
|
|
||||||
vi.mocked(vorgangPINValidation).mockReturnValueOnce(false);
|
|
||||||
|
|
||||||
let thrownRedirect;
|
|
||||||
try {
|
|
||||||
await load(event);
|
|
||||||
throw new Error('Function did not throw')
|
|
||||||
} catch (e) {
|
|
||||||
thrownRedirect = e;
|
|
||||||
}
|
|
||||||
expect(thrownRedirect?.status).toBe(303);
|
|
||||||
expect(thrownRedirect?.location).toBe(ROUTE_NAMES.ANMELDUNG_VORGANG_PARAM(vorgObj.vorgangToken));
|
|
||||||
|
|
||||||
expect(cookiesGet).toHaveBeenCalledWith(COOKIE_NAME);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,20 +4,15 @@ import { ROUTE_NAMES } from '../../src/routes';
|
|||||||
import { baseData, mockEvent } from '../fixtures';
|
import { baseData, mockEvent } from '../fixtures';
|
||||||
|
|
||||||
describe('+layout.server load(): Teste korrekte URL', () => {
|
describe('+layout.server load(): Teste korrekte URL', () => {
|
||||||
test('Werfe redirect zu /anmeldung wenn User nicht eingeloggt', async () => {
|
test('Werfe keinen Redirect und gebe nichts zurück', async () => {
|
||||||
const mockEvent = {
|
const mockEvent = {
|
||||||
locals: {
|
locals: {
|
||||||
user: null
|
user: null
|
||||||
},
|
},
|
||||||
url: new URL(`https://example.com/not-anmeldung`)
|
url: new URL(`https://example.com/not-anmeldung`)
|
||||||
};
|
};
|
||||||
try {
|
const res = load(mockEvent);
|
||||||
load(mockEvent);
|
expect(res).toBe(undefined);
|
||||||
throw new Error('Expected load() to throw');
|
|
||||||
} catch (err) {
|
|
||||||
expect(err.status).toBe(303);
|
|
||||||
expect(err.location).toBe(ROUTE_NAMES.ANMELDUNG);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user