add option to add user manually (#22)
All checks were successful
delpoy / build-and-deploy (push) Successful in 1m25s
All checks were successful
delpoy / build-and-deploy (push) Successful in 1m25s
This commit is contained in:
parent
7878fef301
commit
b92e494ecb
@ -363,6 +363,7 @@
|
||||
if (!e.detail.draft) $reportCount += 1;
|
||||
currentPageReports = [e.detail, ...currentPageReports];
|
||||
activeReport = currentPageReports[0];
|
||||
newReportModal.close();
|
||||
}}
|
||||
/>
|
||||
</dialog>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { Check, NoSymbol, PencilSquare, Trash } from 'svelte-heros-v2';
|
||||
import { Check, NoSymbol, PencilSquare, Plus, Trash } from 'svelte-heros-v2';
|
||||
import Input from '$lib/components/Input/Input.svelte';
|
||||
import Select from '$lib/components/Input/Select.svelte';
|
||||
import { env } from '$env/dynamic/public';
|
||||
@ -10,6 +10,7 @@
|
||||
import HeaderBar from './HeaderBar.svelte';
|
||||
import SortableTr from '$lib/components/Table/SortableTr.svelte';
|
||||
import SortableTh from '$lib/components/Table/SortableTh.svelte';
|
||||
import NewUserModal from './NewUserModal.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
@ -19,6 +20,7 @@
|
||||
let userPage = 0;
|
||||
let userFilter = { name: null, playertype: null };
|
||||
let userTableContainerElement: HTMLDivElement;
|
||||
let newUserModal: HTMLDialogElement;
|
||||
|
||||
function fetchPageUsers(page: number) {
|
||||
if (!browser) return;
|
||||
@ -208,6 +210,16 @@
|
||||
</tr>
|
||||
{/each}
|
||||
{/await}
|
||||
<tr>
|
||||
<td colspan="100">
|
||||
<div class="flex justify-center items-center">
|
||||
<button class="btn btn-sm" on:click={() => newUserModal.show()}>
|
||||
<Plus />
|
||||
<span>Neuer Spieler</span>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/key}
|
||||
</tbody>
|
||||
</table>
|
||||
@ -227,3 +239,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<dialog class="modal" bind:this={newUserModal}>
|
||||
<NewUserModal
|
||||
on:submit={(e) => {
|
||||
currentPageUsers = [...currentPageUsers, e.detail];
|
||||
newUserModal.close();
|
||||
}}
|
||||
/>
|
||||
</dialog>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { getSession } from '$lib/server/session';
|
||||
import { Permissions } from '$lib/permissions';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import { error, type RequestHandler } from '@sveltejs/kit';
|
||||
import { User } from '$lib/server/database';
|
||||
import { type Attributes, Op } from 'sequelize';
|
||||
import { ApiError, getJavaUuid, getNoAuthUuid, UserNotFoundError } from '$lib/server/minecraft';
|
||||
|
||||
export const POST = (async ({ request, cookies }) => {
|
||||
if (getSession(cookies, { permissions: [Permissions.UserRead] }) == null) {
|
||||
@ -88,6 +89,90 @@ export const PATCH = (async ({ request, cookies }) => {
|
||||
return new Response();
|
||||
}) satisfies RequestHandler;
|
||||
|
||||
export const PUT = (async ({ request, cookies }) => {
|
||||
if (getSession(cookies, { permissions: [Permissions.UserWrite] }) == null) {
|
||||
return new Response(null, {
|
||||
status: 401
|
||||
});
|
||||
}
|
||||
|
||||
const data: {
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
|
||||
birthday: string;
|
||||
telephone: string;
|
||||
|
||||
username: string;
|
||||
playertype: string;
|
||||
} = await request.json();
|
||||
|
||||
if (
|
||||
data.firstname == null ||
|
||||
data.lastname == null ||
|
||||
data.birthday == null ||
|
||||
data.username == null ||
|
||||
data.playertype == null
|
||||
) {
|
||||
return new Response(null, { status: 400 });
|
||||
}
|
||||
|
||||
let uuid: string | null;
|
||||
try {
|
||||
switch (data.playertype) {
|
||||
case 'java':
|
||||
uuid = await getJavaUuid(data.username);
|
||||
break;
|
||||
case 'bedrock':
|
||||
uuid = null;
|
||||
// uuid = await getBedrockUuid(username);
|
||||
break;
|
||||
case 'noauth':
|
||||
uuid = getNoAuthUuid(data.username);
|
||||
break;
|
||||
default:
|
||||
throw new Error(`invalid player type (${data.playertype})`);
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof UserNotFoundError) {
|
||||
throw error(400, `Der Spielername ${data.username} existiert nicht`);
|
||||
} else if (e instanceof ApiError) {
|
||||
console.error((e as Error).message);
|
||||
uuid = null;
|
||||
} else {
|
||||
console.error((e as Error).message);
|
||||
throw error(500);
|
||||
}
|
||||
}
|
||||
|
||||
if (uuid && (await User.findOne({ where: { uuid: uuid } }))) {
|
||||
throw error(400, 'Dieser Minecraft-Account wurde bereits registriert');
|
||||
} else if (
|
||||
await User.findOne({
|
||||
where: {
|
||||
firstname: data.firstname,
|
||||
lastname: data.lastname,
|
||||
birthday: new Date(data.birthday).toUTCString()
|
||||
}
|
||||
})
|
||||
) {
|
||||
throw error(400, 'Ein Nutzer mit demselben Namen und Geburtstag wurde bereits registriert');
|
||||
}
|
||||
|
||||
await User.create({
|
||||
firstname: data.firstname,
|
||||
lastname: data.lastname,
|
||||
birthday: new Date(data.birthday).toUTCString(),
|
||||
telephone: data.telephone,
|
||||
username: data.username,
|
||||
playertype: data.playertype,
|
||||
password: null,
|
||||
uuid: uuid
|
||||
});
|
||||
|
||||
return new Response();
|
||||
}) satisfies RequestHandler;
|
||||
|
||||
export const DELETE = (async ({ request, cookies }) => {
|
||||
if (getSession(cookies, { permissions: [Permissions.UserWrite] }) == null) {
|
||||
return new Response(null, {
|
||||
|
114
src/routes/admin/users/NewUserModal.svelte
Normal file
114
src/routes/admin/users/NewUserModal.svelte
Normal file
@ -0,0 +1,114 @@
|
||||
<script lang="ts">
|
||||
import Input from '$lib/components/Input/Input.svelte';
|
||||
import { env } from '$env/dynamic/public';
|
||||
import Select from '$lib/components/Input/Select.svelte';
|
||||
import { errorMessage } from '$lib/stores';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let firstname: string;
|
||||
let lastname: string;
|
||||
let birthday: string;
|
||||
let phone: string;
|
||||
let username: string;
|
||||
let playertype = 'java';
|
||||
|
||||
async function newUser() {
|
||||
const response = await fetch(`${env.PUBLIC_BASE_PATH}/admin/users`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({
|
||||
firstname: firstname,
|
||||
lastname: lastname,
|
||||
birthday: birthday,
|
||||
telephone: phone,
|
||||
username: username,
|
||||
playertype: playertype
|
||||
})
|
||||
});
|
||||
if (response.ok) {
|
||||
dispatch('submit', {
|
||||
firstname: firstname,
|
||||
lastname: lastname,
|
||||
birthday: birthday,
|
||||
telephone: phone,
|
||||
username: username,
|
||||
playertype: playertype
|
||||
});
|
||||
globalCloseForm.submit();
|
||||
} else {
|
||||
$errorMessage = (await response.json()).message;
|
||||
}
|
||||
}
|
||||
|
||||
let globalCloseForm: HTMLFormElement;
|
||||
|
||||
let reportForm: HTMLFormElement;
|
||||
let confirmDialog: HTMLDialogElement;
|
||||
</script>
|
||||
|
||||
<form method="dialog" class="modal-box" bind:this={reportForm}>
|
||||
<button
|
||||
class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
|
||||
on:click|preventDefault={() => globalCloseForm.submit()}>✕</button
|
||||
>
|
||||
<h3 class="font-roboto text-xl">Neuer Spieler</h3>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<Input type="text" required bind:value={firstname}>
|
||||
<span slot="label">Vorname</span>
|
||||
</Input>
|
||||
<Input type="text" required bind:value={lastname}>
|
||||
<span slot="label">Nachname</span>
|
||||
</Input>
|
||||
<Input type="date" required bind:value={birthday}>
|
||||
<span slot="label">Geburtstag</span>
|
||||
</Input>
|
||||
<Input type="tel" bind:value={phone}>
|
||||
<span slot="label">Telefonnummer</span>
|
||||
</Input>
|
||||
<Input type="text" required bind:value={username}>
|
||||
<span slot="label">Minecraft-Spielername</span>
|
||||
</Input>
|
||||
<Select required label="Edition" bind:value={playertype}>
|
||||
<option value="java">Java Edition</option>
|
||||
<option value="bedrock">Bedrock Edition</option>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="flex flex-row space-x-2 mt-6">
|
||||
<Input
|
||||
type="submit"
|
||||
value="Hinzufügen"
|
||||
on:click={(e) => {
|
||||
if (reportForm.checkValidity()) {
|
||||
e.detail.preventDefault();
|
||||
confirmDialog.show();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
type="submit"
|
||||
value="Abbrechen"
|
||||
on:click={(e) => {
|
||||
e.detail.preventDefault();
|
||||
globalCloseForm.submit();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
<form method="dialog" class="modal-backdrop bg-[rgba(0,0,0,.3)]" bind:this={globalCloseForm}>
|
||||
<button>close</button>
|
||||
</form>
|
||||
|
||||
<dialog class="modal" bind:this={confirmDialog}>
|
||||
<form method="dialog" class="modal-box">
|
||||
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
|
||||
<h3 class="font-roboto text-xl mb-2">Spieler hinzufügen?</h3>
|
||||
<div class="flex flex-row space-x-2 mt-6">
|
||||
<Input type="submit" value="Hinzufügen" on:click={newUser} />
|
||||
<Input type="submit" value="Abbrechen" />
|
||||
</div>
|
||||
</form>
|
||||
<form method="dialog" class="modal-backdrop bg-[rgba(0,0,0,.3)]">
|
||||
<button>close</button>
|
||||
</form>
|
||||
</dialog>
|
Loading…
x
Reference in New Issue
Block a user