added login with pages and database, also correct errors in score submit
This commit is contained in:
73
src/lib/server/auth.ts
Normal file
73
src/lib/server/auth.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
// src/lib/server/auth.ts
|
||||
import { sha256 } from '@oslojs/crypto/sha2';
|
||||
import { encodeBase32LowerCaseNoPadding, encodeHexLowerCase } from '@oslojs/encoding';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { db } from '$lib/server/db';
|
||||
import { sessions, scorers as scorers } from '$lib/server/db/schema';
|
||||
import type { RequestEvent } from '@sveltejs/kit';
|
||||
|
||||
const DAY_MS = 1000 * 60 * 60 * 24;
|
||||
const SESSION_COOKIE = 'session';
|
||||
|
||||
export function generateSessionToken(): string {
|
||||
const bytes = new Uint8Array(20);
|
||||
crypto.getRandomValues(bytes);
|
||||
return encodeBase32LowerCaseNoPadding(bytes);
|
||||
}
|
||||
|
||||
export async function createSession(token: string, userId: string) {
|
||||
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
|
||||
const expiresAt = new Date(Date.now() + DAY_MS * 30);
|
||||
|
||||
await db.insert(sessions).values({ id: sessionId, userId, expiresAt });
|
||||
return { id: sessionId, userId, expiresAt };
|
||||
}
|
||||
|
||||
export async function validateSessionToken(token: string) {
|
||||
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
|
||||
|
||||
const [row] = await db
|
||||
.select({ session: sessions, user: scorers })
|
||||
.from(sessions)
|
||||
.innerJoin(scorers, eq(sessions.userId, scorers.id))
|
||||
.where(eq(sessions.id, sessionId));
|
||||
|
||||
if (!row) return { session: null, user: null };
|
||||
|
||||
// Expired — clean up and reject
|
||||
if (Date.now() >= row.session.expiresAt.getTime()) {
|
||||
await db.delete(sessions).where(eq(sessions.id, sessionId));
|
||||
return { session: null, user: null };
|
||||
}
|
||||
|
||||
// Sliding expiration: renew if past the halfway mark
|
||||
if (Date.now() >= row.session.expiresAt.getTime() - DAY_MS * 15) {
|
||||
const newExpiresAt = new Date(Date.now() + DAY_MS * 30);
|
||||
await db.update(sessions).set({ expiresAt: newExpiresAt }).where(eq(sessions.id, sessionId));
|
||||
row.session.expiresAt = newExpiresAt;
|
||||
}
|
||||
|
||||
return { session: row.session, user: { id: row.user.id, username: row.user.username } };
|
||||
}
|
||||
|
||||
export async function invalidateSession(sessionId: string) {
|
||||
await db.delete(sessions).where(eq(sessions.id, sessionId));
|
||||
}
|
||||
|
||||
export function setSessionTokenCookie(event: RequestEvent, token: string, expiresAt: Date) {
|
||||
event.cookies.set(SESSION_COOKIE, token, {
|
||||
expires: expiresAt,
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
secure: !import.meta.env.DEV, // allow http in local dev
|
||||
sameSite: 'lax'
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteSessionTokenCookie(event: RequestEvent) {
|
||||
event.cookies.delete(SESSION_COOKIE, { path: '/' });
|
||||
}
|
||||
|
||||
export function getSessionToken(event: RequestEvent) {
|
||||
return event.cookies.get(SESSION_COOKIE) ?? null;
|
||||
}
|
||||
@@ -1,6 +1,21 @@
|
||||
import { sql, eq } from 'drizzle-orm';
|
||||
import { integer, sqliteTable, text, sqliteView } from 'drizzle-orm/sqlite-core';
|
||||
|
||||
export const scorers = sqliteTable('users', {
|
||||
id: text('id').primaryKey(),
|
||||
username: text('username').notNull().unique(),
|
||||
role: text('scorer_role').notNull().default('scorer'),
|
||||
passwordHash: text('password_hash').notNull()
|
||||
});
|
||||
|
||||
export const sessions = sqliteTable('sessions', {
|
||||
id: text('id').primaryKey(), // SHA-256 hash of the token, never the raw token
|
||||
userId: text('user_id')
|
||||
.notNull()
|
||||
.references(() => scorers.id),
|
||||
expiresAt: integer('expires_at', { mode: 'timestamp' }).notNull()
|
||||
});
|
||||
|
||||
export const players = sqliteTable('players', {
|
||||
id: integer('players_id').primaryKey({ autoIncrement: true }),
|
||||
firstName: text('firstName').notNull(),
|
||||
|
||||
Reference in New Issue
Block a user