First pass

This commit is contained in:
2025-12-25 22:10:06 -07:00
parent a2af6195f9
commit 455c3dbd9a
58 changed files with 10299 additions and 3 deletions

58
src/lib/auth.ts Normal file
View File

@@ -0,0 +1,58 @@
import { db } from '../db';
import { users, sessions } from '../db/schema';
import { eq } from 'drizzle-orm';
import bcrypt from 'bcryptjs';
import { nanoid } from 'nanoid';
const SESSION_DURATION = 1000 * 60 * 60 * 24 * 30; // 30 days
export async function createSession(userId: string) {
const sessionId = nanoid();
const expiresAt = new Date(Date.now() + SESSION_DURATION);
await db.insert(sessions).values({
id: sessionId,
userId,
expiresAt,
});
return { sessionId, expiresAt };
}
export async function validateSession(sessionId: string) {
const result = await db.select({
user: users,
session: sessions
})
.from(sessions)
.innerJoin(users, eq(sessions.userId, users.id))
.where(eq(sessions.id, sessionId))
.get();
if (!result) {
return null;
}
const { session, user } = result;
if (Date.now() >= session.expiresAt.getTime()) {
await db.delete(sessions).where(eq(sessions.id, sessionId));
return null;
}
// Extend session if close to expiry (optional, skipping for simplicity)
return { session, user };
}
export async function invalidateSession(sessionId: string) {
await db.delete(sessions).where(eq(sessions.id, sessionId));
}
export async function hashPassword(password: string) {
return await bcrypt.hash(password, 10);
}
export async function verifyPassword(password: string, hash: string) {
return await bcrypt.compare(password, hash);
}