Compare commits
18 Commits
e45b0e34c9
...
cbea96f892
| Author | SHA1 | Date | |
|---|---|---|---|
| cbea96f892 | |||
| 7e87a01c59 | |||
| 4f0526c71f | |||
| dd06c93b1c | |||
| 26b94938a9 | |||
| b5ff4a72fb | |||
| eea1621339 | |||
| c53400d7b7 | |||
| ef1ddb58a0 | |||
| 8c4f95d52e | |||
| 5b408b096e | |||
| aae8237aae | |||
| 54e3a64dac | |||
| 5927f1dacd | |||
| f39debd0b8 | |||
| 7d265341cc | |||
| d6f2956bcb | |||
| e1cf6dc16f |
54
src/lib/server/userService.ts
Normal file
54
src/lib/server/userService.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { db } from '$lib/server/dbService';
|
||||
|
||||
export const getUsers = (): { userId: string; userName: string }[] => {
|
||||
const getUsersSQLStmt = `SELECT id, name
|
||||
FROM users;`;
|
||||
const statement = db.prepare(getUsersSQLStmt);
|
||||
const result = statement.all() as { id: string; name: string }[];
|
||||
const userList: { userId: string; userName: string }[] = [];
|
||||
|
||||
for (const resultItem of result) {
|
||||
const user = { userId: resultItem.id, userName: resultItem.name };
|
||||
userList.push(user);
|
||||
}
|
||||
|
||||
return userList;
|
||||
};
|
||||
|
||||
export const addUser = (userName: string, userPassword: string): number => {
|
||||
const addUserSQLStmt = `INSERT into users(name, pw)
|
||||
values (?, ?)`;
|
||||
const statement = db.prepare(addUserSQLStmt);
|
||||
|
||||
let rowCount;
|
||||
try {
|
||||
const info = statement.run(userName, userPassword);
|
||||
rowCount = info.changes;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
rowCount = 0;
|
||||
}
|
||||
|
||||
return rowCount;
|
||||
};
|
||||
|
||||
export const deleteUser = (userId: string) => {
|
||||
// make sure to not delete the last entry
|
||||
const deleteUserSQLStmt = `DELETE
|
||||
FROM users
|
||||
WHERE id = ?
|
||||
AND (SELECT COUNT(*) FROM users) > 1;`;
|
||||
|
||||
const statement = db.prepare(deleteUserSQLStmt);
|
||||
|
||||
let rowCount;
|
||||
try {
|
||||
const info = statement.run(userId);
|
||||
rowCount = info.changes;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
rowCount = 0;
|
||||
}
|
||||
|
||||
return rowCount;
|
||||
};
|
||||
@@ -48,11 +48,11 @@
|
||||
>
|
||||
<FileRect class=" group-hover:text-indigo-600" {outline} />
|
||||
</div>
|
||||
<a href="/view" class="mt-6 block font-semibold text-gray-900">
|
||||
Ansicht
|
||||
<a href="/user-management" class="mt-6 block font-semibold text-gray-900">
|
||||
Benutzerverwaltung
|
||||
<span class="absolute inset-0"></span>
|
||||
</a>
|
||||
<p class="mt-1 text-gray-600">Schau Dir einen Tatort in der 3D Ansicht an.</p>
|
||||
<p class="mt-1 text-gray-600">Füge neue Benutzer hinzu oder entferne welche.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { getVorgaenge } from '$lib/server/vorgangService';
|
||||
import type { PageServerLoad } from '../../(token-based)/view/$types';
|
||||
|
||||
export const load: PageServerLoad = async () => {
|
||||
const vorgangList = await getVorgaenge();
|
||||
const vorgangList = getVorgaenge();
|
||||
|
||||
return {
|
||||
vorgangList
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import { client } from '$lib/minio';
|
||||
import { fail } from '@sveltejs/kit';
|
||||
|
||||
import vorgangNumberOccupied from '$lib/helper/vorgangNumberOccupied.js';
|
||||
|
||||
/** @type {import('./$types').Actions} */
|
||||
export const actions = {
|
||||
default: async ({ request }: {request: Request}) => {
|
||||
const data = await request.formData();
|
||||
const vorgangNumber = data.get('vorgangNumber');
|
||||
const description = data.get('description');
|
||||
|
||||
if (!vorgangNumber) {
|
||||
return fail(400, {
|
||||
vorgangNumber,
|
||||
description,
|
||||
error: { vorgangNumber: 'Es muss eine Vorgangsnummer vorhanden sein.' }
|
||||
});
|
||||
}
|
||||
|
||||
if (await vorgangNumberOccupied(`${vorgangNumber}`)) {
|
||||
return fail(400, {
|
||||
vorgangNumber,
|
||||
description,
|
||||
error: { vorgangNumber: 'Die Vorgangsnummer wurde im System bereits angelegt.' }
|
||||
});
|
||||
}
|
||||
|
||||
const config = `${JSON.stringify({ vorgangNumber, description, version: 1 })}\n`;
|
||||
|
||||
await client.putObject('tatort', `${vorgangNumber}/config.json`, config, undefined, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
};
|
||||
@@ -1,115 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Alert from '$lib/components/Alert.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import Modal from '$lib/components/Modal/Modal.svelte';
|
||||
import ModalTitle from '$lib/components/Modal/ModalTitle.svelte';
|
||||
import ModalContent from '$lib/components/Modal/ModalContent.svelte';
|
||||
import ModalFooter from '$lib/components/Modal/ModalFooter.svelte';
|
||||
import Exclamation from '$lib/icons/Exclamation.svelte';
|
||||
|
||||
export let form;
|
||||
|
||||
let open = false;
|
||||
$: open = form?.success ?? false;
|
||||
</script>
|
||||
|
||||
<div class="mx-auto max-w-2xl">
|
||||
<div class="flex flex-col items-center justify-center w-full">
|
||||
<h1 class="text-xl">Neuer Vorgang</h1>
|
||||
</div>
|
||||
|
||||
<form method="POST">
|
||||
<div class="space-y-12">
|
||||
<div class="border-b border-gray-900/10 pb-12">
|
||||
<p class="mt-8 text-sm leading-6 text-gray-600">
|
||||
This information will be displayed publicly so be careful what you share.
|
||||
</p>
|
||||
|
||||
<div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8">
|
||||
<div>
|
||||
<label for="vorgangNumber" class="block text-sm font-medium leading-6 text-gray-900"
|
||||
><span class="flex"
|
||||
>{#if form?.error?.vorgangNumber}
|
||||
<span class="inline-block mr-1"><Exclamation /></span>
|
||||
{/if} Vorgangs-Nr.</span
|
||||
></label
|
||||
>
|
||||
<div class="mt-2">
|
||||
<div
|
||||
class="flex rounded-md shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-inset focus-within:ring-indigo-600"
|
||||
>
|
||||
<input
|
||||
value={form?.vorgangNumber ?? ''}
|
||||
type="text"
|
||||
name="vorgangNumber"
|
||||
id="vorgangNumber"
|
||||
class="block flex-1 border-0 bg-transparent py-1.5 pl-1 text-gray-900 placeholder:text-gray-400 focus:ring-0 text-sm leading-6"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{#if form?.error?.vorgangNumber}
|
||||
<p class="block text-sm leading-6 text-red-900 mt-2">{form.error.vorgangNumber}</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="description" class="block text-sm font-medium leading-6 text-gray-900"
|
||||
><span class="flex"
|
||||
>{#if form?.description}
|
||||
<span class="inline-block mr-1"><Exclamation /></span>
|
||||
{/if} Beschreibung</span
|
||||
></label
|
||||
>
|
||||
<div class="mt-2">
|
||||
<textarea
|
||||
value={form?.description?.toString() ?? ''}
|
||||
id="description"
|
||||
name="description"
|
||||
rows="3"
|
||||
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"
|
||||
></textarea>
|
||||
</div>
|
||||
{#if form?.error}
|
||||
<p class="block text-sm leading-6 text-red-900 mt-2">{form.description}</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<label for="vorgang-token">
|
||||
<span >Zugangstoken (optional) </span>
|
||||
</label>
|
||||
|
||||
<div class="mt-2">
|
||||
<div
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
id="vorgang-token"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex items-center justify-end gap-x-6">
|
||||
<button type="button" class="text-sm font-semibold leading-6 text-gray-900">Cancel</button>
|
||||
<Button
|
||||
type="submit"
|
||||
class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
|
||||
>Save</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<Modal {open}
|
||||
><ModalTitle>vorgang anlegen</ModalTitle><ModalContent>
|
||||
{#if form?.success}
|
||||
<Alert class="w-full">Vorgang erfolgreich angelegt</Alert>
|
||||
{:else}
|
||||
<Alert class="w-full" type="error">Fehler beim Upload</Alert>
|
||||
{/if}
|
||||
</ModalContent>
|
||||
<ModalFooter><Button on:click={() => (open = false)}>Ok</Button></ModalFooter>
|
||||
</Modal>
|
||||
</div>
|
||||
@@ -17,11 +17,11 @@ const isRequiredFieldValid = (value: unknown) => {
|
||||
export const actions = {
|
||||
url: async ({ request }: { request: Request }) => {
|
||||
const data = await request.formData();
|
||||
const vorgangName = data.get('vorgang');
|
||||
const crimeName = data.get('name');
|
||||
const type = data.get('type');
|
||||
const vorgangPIN = data.get('vorgangPIN');
|
||||
const fileName = data.get('fileName');
|
||||
const vorgangName: string | null = data.get('vorgang') as string;
|
||||
const crimeName: string | null = data.get('name') as string;
|
||||
const type: string | null = data.get('type') as string;
|
||||
const vorgangPIN: string | null = data.get('vorgangPIN') as string;
|
||||
const fileName: string | null = data.get('fileName') as string;
|
||||
|
||||
const vorgangExists = vorgangNameExists(vorgangName);
|
||||
let vorgangToken;
|
||||
|
||||
193
src/routes/(angemeldet)/user-management/+page.svelte
Normal file
193
src/routes/(angemeldet)/user-management/+page.svelte
Normal file
@@ -0,0 +1,193 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from 'svelte';
|
||||
import Button from "$lib/components/Button.svelte";
|
||||
|
||||
import jsSHA from 'jssha'
|
||||
|
||||
const {data} = $props();
|
||||
|
||||
let userName = $state('')
|
||||
let userPassword = $state('')
|
||||
let userList = $state([])
|
||||
let addUserError = $state(false);
|
||||
let addUserSuccess = $state(false);
|
||||
const currentUser: string = data.user.id;
|
||||
|
||||
onMount(async () => {
|
||||
userList = await getUsers();
|
||||
})
|
||||
|
||||
async function getUsers() {
|
||||
const URL = "/api/users"
|
||||
const response = await fetch(URL);
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
async function addUser() {
|
||||
if (userName == "") {
|
||||
alert("Der Benutzername darf nicht leer sein.")
|
||||
return;
|
||||
}
|
||||
|
||||
if (userPassword == "") {
|
||||
alert("Das Passwort darf nicht leer sein.")
|
||||
return;
|
||||
}
|
||||
|
||||
const URL = "/api/users";
|
||||
const hashedUserPassword = new jsSHA('SHA-512', 'TEXT').update(userPassword).getHash('HEX');
|
||||
const userData = {userName: userName, userPassword: hashedUserPassword}
|
||||
|
||||
const response = await fetch(URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(userData)
|
||||
})
|
||||
|
||||
if (response.ok) {
|
||||
userList = await getUsers();
|
||||
addUserSuccess = true;
|
||||
resetInput();
|
||||
} else {
|
||||
addUserError = true;
|
||||
}
|
||||
}
|
||||
|
||||
function resetInput() {
|
||||
userName = "";
|
||||
userPassword = "";
|
||||
addUserError = false;
|
||||
setInterval(() => {
|
||||
addUserSuccess = false;
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
async function deleteUser(userId: number) {
|
||||
const URL = `/api/users/${userId}`;
|
||||
|
||||
const response = await fetch(URL, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
if (response.status == 204) {
|
||||
userList = await getUsers();
|
||||
} else {
|
||||
alert("Nutzer konnte nicht gelöscht werden")
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<h1 class="flex justify-center text-3xl md:text-4xl font-bold text-gray-800 dark:text-white tracking-tight mb-4">
|
||||
Benutzerverwaltung
|
||||
</h1>
|
||||
|
||||
<h1 class="flex justify-center text-lg md:text-xl font-medium text-gray-800 dark:text-white tracking-tight mb-2">
|
||||
Benutzerliste
|
||||
</h1>
|
||||
|
||||
<div class="w-1/4 mx-auto">
|
||||
<table class="min-w-full border border-gray-300 rounded overflow-hidden">
|
||||
<thead class="bg-gray-100 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th class="text-left px-4 py-2">Benutzername</th>
|
||||
<th class="text-center px-4 py-2">Entfernen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each userList as userItem}
|
||||
<tr class="border-t border-gray-200 dark:border-gray-600">
|
||||
<td class="px-4 py-2 text-gray-800 dark:text-white">{userItem.userName}</td>
|
||||
<td class="px-4 py-2 text-center">
|
||||
<button
|
||||
class="text-red-600 hover:text-red-800 focus:outline-none focus:ring-2 focus:ring-red-500 rounded-full p-1 transition"
|
||||
on:click={() => deleteUser(userItem.userId)}
|
||||
aria-label="Delete user"
|
||||
>
|
||||
{#if (userItem.userName != currentUser)}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
{/if}
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h1 style="margin-top: 50px;"
|
||||
class="flex justify-center text-lg md:text-xl font-medium text-gray-800 dark:text-white tracking-tight mb-2">
|
||||
Neuer Nutzer
|
||||
</h1>
|
||||
|
||||
<div class="mx-auto flex justify-center">
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="username">Benutzername</label>
|
||||
<input bind:value={userName} type="text" id="username" placeholder="Namen eingeben"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password">Passwort</label>
|
||||
<input bind:value={userPassword} type="password" id="password" placeholder="Passwort vergeben"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="mx-auto flex flex-col items-center space-y-4" style="margin-top: 20px;">
|
||||
{#if addUserError}
|
||||
<div class="flex items-center bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4 rounded shadow-sm"
|
||||
role="alert">
|
||||
<svg class="h-5 w-5 mr-3 text-yellow-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 9v2m0 4h.01M12 5a7 7 0 100 14 7 7 0 000-14z"/>
|
||||
</svg>
|
||||
<span class="text-sm font-medium">Der Benutzer konnte nicht hinzugefügt werden.</span>
|
||||
</div>
|
||||
{/if}
|
||||
{#if addUserSuccess}
|
||||
<div class="flex items-center bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4 rounded shadow-sm"
|
||||
role="alert">
|
||||
<svg class="h-5 w-5 mr-3 text-yellow-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 9v2m0 4h.01M12 5a7 7 0 100 14 7 7 0 000-14z"/>
|
||||
</svg>
|
||||
<span class="text-sm font-medium">Der Benutzer wurde hinzugefügt.</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<Button on:click={addUser}>Benutzer hinzufügen</Button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"] {
|
||||
padding: 8px;
|
||||
font-size: 16px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
@@ -59,8 +59,8 @@
|
||||
return;
|
||||
}
|
||||
|
||||
async function handle_input(ev: KeyboardEvent, i: number) {
|
||||
let item = crimesList[i];
|
||||
async function handleEditFieldInput(ev: KeyboardEvent, listItemIndex: number) {
|
||||
let item = crimesList[listItemIndex];
|
||||
if (ev.key == 'Escape') {
|
||||
let text_field_id = `label__${item.name}`;
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
ev.preventDefault();
|
||||
|
||||
// construct PUT URL
|
||||
const url = $page.url;
|
||||
const url = $page.url.pathname.split('?')[0];
|
||||
|
||||
let data_obj: { new_name: string; old_name: string } = { new_name: '', old_name: '' };
|
||||
data_obj['new_name'] = new_name;
|
||||
@@ -129,13 +129,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function setClipboard(text) {
|
||||
const type = "text/plain";
|
||||
const clipboardItemData = {
|
||||
[type]: text,
|
||||
};
|
||||
const clipboardItem = new ClipboardItem(clipboardItemData);
|
||||
await navigator.clipboard.write([clipboardItem]);
|
||||
function constructMailToLink() {
|
||||
const subject = "Link zum Tatvorgang";
|
||||
const link = $page.url.toString().split('?')[0];
|
||||
const body = `Hallo,
|
||||
|
||||
hier ist der Link zum Tatvorgang:
|
||||
${link}
|
||||
|
||||
Der Zugangs-PIN wird zur Sicherheit über einen zweiten Kommunikationskanal übermittelt.
|
||||
|
||||
Mit freundlichen Grüßen,
|
||||
`;
|
||||
|
||||
const mailtoLink = `mailto:?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
||||
|
||||
return mailtoLink;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -144,12 +153,12 @@
|
||||
<h1 class="text-xl">Vorgang {vorgang.name}</h1>
|
||||
{#if data?.user?.admin}
|
||||
Zugangs-PIN: {vorgang.pin}
|
||||
<Button on:click={() => setClipboard($page.url.toString().split('?')[0])}>Copy Link</Button>
|
||||
<a href="{constructMailToLink()}"><Button>Share Link</Button></a>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="mx-auto flex justify-center max-w-7xl h-full">
|
||||
<ul class="divide-y divide-gray-100">
|
||||
{#each crimesList as item, i}
|
||||
{#each crimesList as item, crimeListItemIndex}
|
||||
<li>
|
||||
<a
|
||||
href="/view/{$page.params.vorgang}/{item.name}?pin={vorgangPIN}"
|
||||
@@ -168,12 +177,12 @@
|
||||
tabindex="0"
|
||||
aria-label="Dateiname bearbeiten"
|
||||
on:focusout={() => {
|
||||
defocus_element(i);
|
||||
defocus_element(crimeListItemIndex);
|
||||
}}
|
||||
on:keydown|stopPropagation={// event needed to identify ID
|
||||
// TO-DO: check if event is needed or if index is sufficient
|
||||
async (ev) => {
|
||||
handle_input(ev, i);
|
||||
handleEditFieldInput(ev, crimeListItemIndex);
|
||||
}}>{item.name}</span
|
||||
>
|
||||
|
||||
|
||||
@@ -2,21 +2,20 @@ import { client } from '$lib/minio';
|
||||
import { json } from '@sveltejs/kit';
|
||||
|
||||
|
||||
// rename operation
|
||||
// rename operation for crimes
|
||||
export async function PUT({ request }: {request: Request}) {
|
||||
const data = await request.json();
|
||||
|
||||
|
||||
// Vorgang
|
||||
const vorgang = request.url.split('/').at(-1);
|
||||
const vorgangToken = request.url.split('/').at(-1);
|
||||
|
||||
// prepare copy, incl. check if new name exists already
|
||||
const old_name = data["old_name"];
|
||||
const src_full_path = `/tatort/${vorgang}/${old_name}`;
|
||||
const new_name = `${vorgang}/${data["new_name"]}`;
|
||||
const crimeOldName = data["old_name"];
|
||||
const crimeS3FullBucketPathOld = `/tatort/${vorgangToken}/${crimeOldName}`;
|
||||
const crimeNewName = `${vorgangToken}/${data["new_name"]}`;
|
||||
|
||||
try {
|
||||
await client.statObject('tatort', new_name);
|
||||
await client.statObject('tatort', crimeNewName);
|
||||
return json({ msg: 'Die Datei existiert bereits.' }, { status: 400 });
|
||||
} catch (error) {
|
||||
// continue operation
|
||||
@@ -24,10 +23,10 @@ export async function PUT({ request }: {request: Request}) {
|
||||
}
|
||||
|
||||
// actual copy operation
|
||||
await client.copyObject('tatort', new_name, src_full_path)
|
||||
await client.copyObject('tatort', crimeNewName, crimeS3FullBucketPathOld)
|
||||
|
||||
// delete
|
||||
await client.removeObject('tatort', `${vorgang}/${old_name}`)
|
||||
await client.removeObject('tatort', `${vorgangToken}/${crimeOldName}`)
|
||||
|
||||
// return success or failure
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
|
||||
export const actions = {
|
||||
default: async ({request}: {request: Request}) => {
|
||||
const data = await request.formData();
|
||||
const vorgangId = data.get('vorgang-id');
|
||||
const vorgangToken = data.get('vorgang-token');
|
||||
|
||||
if( vorgangId && vorgangToken) throw redirect(303, `/list/${vorgangId}?token=${vorgangToken}`);
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<script lang="ts">
|
||||
import BaseInputField from '$lib/components/BaseInputField.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import ArrowRight from '$lib/icons/Arrow-right.svelte';
|
||||
|
||||
export let form;
|
||||
</script>
|
||||
|
||||
<div class="mx-auto max-w-2xl">
|
||||
<div class="flex flex-col items-center justify-center w-full">
|
||||
<h1 class="text-xl">Vorgang ansehen</h1>
|
||||
</div>
|
||||
<p class="mt-8 mb-8 text-sm leading-6 text-gray-600">
|
||||
Anhand der Vorgangsnummer werden Sie zu den Dateien des Vorgangs weitergeleitet und können sich
|
||||
den Vorgang dann ansehen.
|
||||
</p>
|
||||
<form method="POST">
|
||||
<BaseInputField
|
||||
id="vorgang-id"
|
||||
name="vorgang-id"
|
||||
label="Vorgangskennung"
|
||||
type="text"
|
||||
value={form?.vorgangId}
|
||||
/>
|
||||
<div class="mt-5">
|
||||
<BaseInputField
|
||||
id="vorgang-token"
|
||||
name="vorgang-token"
|
||||
label="Zugangstoken"
|
||||
type="text"
|
||||
value={form?.vorgangToken}
|
||||
error={form?.error?.message}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex justify-end pt-4">
|
||||
<Button type="submit"><ArrowRight /></Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
25
src/routes/api/users/+server.ts
Normal file
25
src/routes/api/users/+server.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { addUser, getUsers } from '$lib/server/userService';
|
||||
|
||||
export function GET({ locals }) {
|
||||
if (!locals.user) {
|
||||
return json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const userList = getUsers();
|
||||
|
||||
return new Response(JSON.stringify(userList));
|
||||
}
|
||||
|
||||
export async function POST({ request, locals }) {
|
||||
if (!locals.user) {
|
||||
return json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const data = await request.json();
|
||||
const userName = data.userName;
|
||||
const userPassword = data.userPassword;
|
||||
const rowCount = addUser(userName, userPassword);
|
||||
|
||||
return new Response(null, { status: rowCount == 1 ? 200 : 400 });
|
||||
}
|
||||
13
src/routes/api/users/[user]/+server.ts
Normal file
13
src/routes/api/users/[user]/+server.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { deleteUser } from '$lib/server/userService';
|
||||
|
||||
export async function DELETE({ params, locals }) {
|
||||
if (!locals.user) {
|
||||
return json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const userId = params.user;
|
||||
const rowCount = deleteUser(userId);
|
||||
|
||||
return new Response(null, { status: rowCount == 1 ? 204 : 400 });
|
||||
}
|
||||
Reference in New Issue
Block a user