Files
fosterflow/src/lib/server/auth.ts
T

72 lines
1.8 KiB
TypeScript

import { db } from './db';
import { users, sessions } from './schema';
import { eq, and, gt } from 'drizzle-orm';
import { generateSessionToken, hashSessionToken, verifyPassword } from './auth-utils';
const SESSION_DURATION_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
export async function createSession(userId: number): Promise<string> {
const token = generateSessionToken();
const sessionId = hashSessionToken(token);
const expiresAt = new Date(Date.now() + SESSION_DURATION_MS);
await db.insert(sessions).values({ sessionId, userId, expiresAt });
return token;
}
export async function validateSession(token: string) {
const sessionId = hashSessionToken(token);
const result = await db
.select({
session: sessions,
user: {
id: users.id,
email: users.email,
name: users.name,
role: users.role,
active: users.active,
mustChangePassword: users.mustChangePassword
}
})
.from(sessions)
.innerJoin(users, eq(sessions.userId, users.id))
.where(
and(
eq(sessions.sessionId, sessionId),
gt(sessions.expiresAt, new Date())
)
)
.limit(1);
if (result.length === 0) return null;
const { session, user } = result[0];
if (!user.active) return null;
return { session, user };
}
export async function destroySession(token: string): Promise<void> {
const sessionId = hashSessionToken(token);
await db.delete(sessions).where(eq(sessions.sessionId, sessionId));
}
export async function authenticateUser(email: string, password: string) {
const result = await db
.select()
.from(users)
.where(eq(users.email, email.toLowerCase()))
.limit(1);
if (result.length === 0) return null;
const user = result[0];
if (!user.active) return null;
const valid = await verifyPassword(user.passwordHash, password);
if (!valid) return null;
return user;
}