im getting lazy but now i can disable the register page
This commit is contained in:
11
TODO.md
11
TODO.md
@@ -2,15 +2,6 @@
|
||||
player view - all registered events and scores for those events
|
||||
team view - all registered players and all points gained from them - Do i need this?
|
||||
|
||||
# Login stuff - HIGH PRIORITY
|
||||
disableable register button on the login page for end users
|
||||
make a way to toggle on and off the register page
|
||||
protect the register endpoint?? (low prio)
|
||||
|
||||
# Ledger - HIGH PRIORITY
|
||||
ledger view
|
||||
inserting manually into ledger
|
||||
|
||||
# Database - HIGH PRIORITY
|
||||
load results from the excel sheet i made
|
||||
export whole contest results to csv
|
||||
@@ -29,7 +20,5 @@ result amendments
|
||||
|
||||
## Easy shit
|
||||
animations for all leaderboards
|
||||
Ongoing since... or ongoing for... on the main page
|
||||
displaying averages of loaded scores when there's more than one (easy, low prio)
|
||||
fix the layout on event view to match the homepage view
|
||||
fix the marquee animation thing and make it global
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<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>
|
||||
|
||||
{#if data.disabled}
|
||||
<p class="error">Registration is currently disabled by an administrator.</p>
|
||||
{:else}
|
||||
<form method="POST">
|
||||
<label>
|
||||
Username
|
||||
@@ -33,6 +37,7 @@
|
||||
</form>
|
||||
|
||||
<p class="switch">Already have an account? <a href="/login">Log in</a></p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
58
src/routes/settings/+page.server.ts
Normal file
58
src/routes/settings/+page.server.ts
Normal 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 };
|
||||
}
|
||||
};
|
||||
46
src/routes/settings/+page.svelte
Normal file
46
src/routes/settings/+page.svelte
Normal 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>
|
||||
Reference in New Issue
Block a user