im getting lazy but now i can disable the register page

This commit is contained in:
2026-07-05 12:54:09 +01:00
parent ec56e3794e
commit f93f407d66
9 changed files with 178 additions and 38 deletions

View File

@@ -3,6 +3,21 @@ import { sql, eq, and, desc, inArray } from 'drizzle-orm';
import * as schema from '$lib/server/db/schema';
import { globalEmitter } from './globalEmitter';
export async function getSetting(key: string): Promise<string | null> {
const [row] = await db
.select({ value: schema.settings.value })
.from(schema.settings)
.where(eq(schema.settings.key, key));
return row?.value ?? null;
}
export async function setSetting(key: string, value: string): Promise<void> {
await db
.insert(schema.settings)
.values({ key, value })
.onConflictDoUpdate({ target: schema.settings.key, set: { value } });
}
// Initial data for page load
export async function getAllInitialInfo() {
return {

View File

@@ -156,6 +156,11 @@ export const registeredEventsView = sqliteView('registeredEventsView').as((qb) =
.innerJoin(divisions, eq(registeredEvents.division, divisions.id));
});
export const settings = sqliteTable('settings', {
key: text('key').primaryKey(),
value: text('value').notNull()
});
export const registeredEventPlayersView = sqliteView('registeredEventPlayersView').as((qb) => {
return qb
.select({

View File

@@ -22,6 +22,11 @@
border-solid border-red-500 px-2"
href="/ledger">ledger</a
>
<a
class="align-text-middle justify-right mx-3 my-1 h-auto content-center rounded-sm border-2
border-solid border-red-500 px-2"
href="/settings">settings</a
>
{/if}
{#if data.user}
<a

View File

@@ -1,7 +1,13 @@
import { getAllInitialInfo } from '$lib/server/databaseManager';
import { redirect } from '@sveltejs/kit';
import { getAllInitialInfo, getSetting } from '$lib/server/databaseManager';
// Provide initial data for the home page
export const load = async () => {
export const load = async ({ locals }) => {
const requireLogin = (await getSetting('requireLoginForLeaderboard')) === 'true';
if (requireLogin && !locals.user) {
throw redirect(303, '/login');
}
return await getAllInitialInfo();
};

View File

@@ -4,10 +4,21 @@ import { eq } from 'drizzle-orm';
import { db } from '$lib/server/db';
import { scorers } from '$lib/server/db/schema';
import { generateSessionToken, createSession, setSessionTokenCookie } from '$lib/server/auth';
import type { Actions } from '../signup/$types';
import { getSetting } from '$lib/server/databaseManager';
import type { PageServerLoad, Actions } from '../signup/$types';
export const load: PageServerLoad = async () => {
const disabled = (await getSetting('disableRegistration')) === 'true';
return { disabled };
};
export const actions: Actions = {
default: async (event) => {
const disabled = (await getSetting('disableRegistration')) === 'true';
if (disabled) {
return fail(403, { message: 'Registration is currently disabled by an administrator.' });
}
const data = await event.request.formData();
const username = data.get('username') as string;
const password = data.get('password') as string;

View File

@@ -1,38 +1,43 @@
<script lang="ts">
import type { ActionData } from './$types';
import type { PageData, ActionData } from './$types';
export let data: PageData;
export let form: ActionData;
</script>
<div class="auth-card">
<h1>Sign up</h1>
<form method="POST">
<label>
Username
<input name="username" class="text-black" type="text" autocomplete="username" required />
</label>
{#if data.disabled}
<p class="error">Registration is currently disabled by an administrator.</p>
{:else}
<form method="POST">
<label>
Username
<input name="username" class="text-black" type="text" autocomplete="username" required />
</label>
<label>
Password
<input
class="text-black"
name="password"
type="password"
autocomplete="new-password"
minlength="8"
required
/>
<small>At least 8 characters</small>
</label>
<label>
Password
<input
class="text-black"
name="password"
type="password"
autocomplete="new-password"
minlength="8"
required
/>
<small>At least 8 characters</small>
</label>
{#if form?.message}
<p class="error">{form.message}</p>
{/if}
{#if form?.message}
<p class="error">{form.message}</p>
{/if}
<button type="submit">Create account</button>
</form>
<button type="submit">Create account</button>
</form>
<p class="switch">Already have an account? <a href="/login">Log in</a></p>
<p class="switch">Already have an account? <a href="/login">Log in</a></p>
{/if}
</div>
<style>

View File

@@ -0,0 +1,58 @@
import { error, redirect, fail } from '@sveltejs/kit';
import { eq } from 'drizzle-orm';
import { db } from '$lib/server/db';
import { scorers } from '$lib/server/db/schema';
import { getSetting, setSetting } from '$lib/server/databaseManager';
import type { PageServerLoad, Actions } from './$types';
export const load: PageServerLoad = async ({ locals }) => {
if (!locals.user) {
throw redirect(303, '/login');
}
const [row] = await db
.select({ role: scorers.role })
.from(scorers)
.where(eq(scorers.id, locals.user.id));
if (row?.role !== 'admin') {
throw error(403, 'Forbidden');
}
const disableRegistration = (await getSetting('disableRegistration')) === 'true';
const requireLoginForLeaderboard = (await getSetting('requireLoginForLeaderboard')) === 'true';
return { disableRegistration, requireLoginForLeaderboard };
};
export const actions: Actions = {
toggleRegistration: async ({ locals }) => {
if (!locals.user) throw error(401, 'Unauthorized');
const [row] = await db
.select({ role: scorers.role })
.from(scorers)
.where(eq(scorers.id, locals.user.id));
if (row?.role !== 'admin') throw error(403, 'Forbidden');
const current = (await getSetting('disableRegistration')) === 'true';
await setSetting('disableRegistration', current ? 'false' : 'true');
return { success: true };
},
toggleLeaderboardLock: async ({ locals }) => {
if (!locals.user) throw error(401, 'Unauthorized');
const [row] = await db
.select({ role: scorers.role })
.from(scorers)
.where(eq(scorers.id, locals.user.id));
if (row?.role !== 'admin') throw error(403, 'Forbidden');
const current = (await getSetting('requireLoginForLeaderboard')) === 'true';
await setSetting('requireLoginForLeaderboard', current ? 'false' : 'true');
return { success: true };
}
};

View File

@@ -0,0 +1,46 @@
<script lang="ts">
import { enhance } from '$app/forms';
import type { PageData } from './$types';
let { data }: { data: PageData } = $props();
</script>
<div class="p-4">
<h2 class="mb-4 text-lg font-bold">Settings</h2>
<div class="flex flex-col gap-4">
<form method="POST" action="?/toggleRegistration" use:enhance>
<div class="flex items-center gap-4 border rounded p-4">
<div class="flex-1">
<p class="font-semibold">Disable Registration</p>
<p class="text-sm opacity-70">Prevents new users from signing up via /register</p>
</div>
<button
type="submit"
class="border rounded px-4 py-1 {data.disableRegistration
? 'bg-red-700 text-white'
: 'bg-green-700 text-white'}"
>
{data.disableRegistration ? 'Disabled' : 'Enabled'}
</button>
</div>
</form>
<form method="POST" action="?/toggleLeaderboardLock" use:enhance>
<div class="flex items-center gap-4 border rounded p-4">
<div class="flex-1">
<p class="font-semibold">Require Login for Leaderboard</p>
<p class="text-sm opacity-70">Non-logged-in users will be redirected to /login</p>
</div>
<button
type="submit"
class="border rounded px-4 py-1 {data.requireLoginForLeaderboard
? 'bg-red-700 text-white'
: 'bg-green-700 text-white'}"
>
{data.requireLoginForLeaderboard ? 'Locked' : 'Public'}
</button>
</div>
</form>
</div>
</div>