actually start implementing the backend slowly

This commit is contained in:
Soph :3 2026-01-04 15:49:32 +02:00
parent 37ae49b66e
commit 342fd30d62
19 changed files with 977 additions and 136 deletions

View file

@ -1,7 +1,7 @@
import type { RequestEvent } from '@sveltejs/kit';
import { eq } from 'drizzle-orm';
import { eq, inArray } from 'drizzle-orm';
import { sha256 } from '@oslojs/crypto/sha2';
import { encodeBase32LowerCase, encodeBase64url, encodeHexLowerCase } from '@oslojs/encoding';
import { encodeBase64url, encodeHexLowerCase } from '@oslojs/encoding';
import { db } from '$lib/server/db';
import * as table from '$lib/server/db/schema';
@ -28,20 +28,25 @@ export async function createSession(token: string, userId: string) {
export async function validateSessionToken(token: string) {
const sessionId = encodeHexLowerCase(sha256(new TextEncoder().encode(token)));
const [result] = await db
const [row] = await db
.select({
// Adjust user table here to tweak returned data
user: { id: table.user.id, username: table.user.username },
session: table.session
user: {
id: table.user.id,
username: table.user.username,
friends: table.user.friends,
servers: table.user.servers,
groups: table.user.groups,
},
session: table.session,
})
.from(table.session)
.innerJoin(table.user, eq(table.session.userId, table.user.id))
.where(eq(table.session.id, sessionId));
if (!result) {
if (!row) {
return { session: null, user: null };
}
const { session, user } = result;
const { session, user } = row;
const sessionExpired = Date.now() >= session.expiresAt.getTime();
if (sessionExpired) {
@ -57,8 +62,40 @@ export async function validateSessionToken(token: string) {
.set({ expiresAt: session.expiresAt })
.where(eq(table.session.id, session.id));
}
const friends = (user.friends as string[]).length
? await db
.select({
id: table.user.id,
username: table.user.username,
})
.from(table.user)
.where(inArray(table.user.id, (user.friends as string[])))
: [];
return { session, user };
const servers = (user.servers as string[]).length
? await db
.select({
id: table.server.id,
name: table.server.name,
ownerId: table.server.owner,
})
.from(table.server)
.where(inArray(table.server.id, (user.servers as string[])))
: [];
const groups = (user.groups as string[]).length
? await db
.select({
id: table.group.id,
name: table.group.name,
ownerId: table.group.owner,
members: table.group.members
})
.from(table.group)
.where(inArray(table.group.id, (user.groups as string[])))
: [];
return { session, user: {...user, servers, friends, groups: groups.map(z => { return { ...z, members: (z.members as string[]).length}})} };
}
export type SessionValidationResult = Awaited<ReturnType<typeof validateSessionToken>>;
@ -80,14 +117,6 @@ export function deleteSessionTokenCookie(event: RequestEvent) {
});
}
export function generateUserId() {
// ID with 120 bits of entropy, or about the same as UUID v4.
const bytes = crypto.getRandomValues(new Uint8Array(15));
const id = encodeBase32LowerCase(bytes);
return id;
}
export function validateUsername(username: unknown): username is string {
return (
typeof username === 'string' &&