Files
planner.sori.studio/backend/src/lib/authSession.js

94 lines
2.1 KiB
JavaScript

import { eq } from 'drizzle-orm'
import { env } from '../config.js'
import { db } from '../db/client.js'
import { authSessions, users } from '../db/schema.js'
import { createSessionToken, hashSessionToken } from './password.js'
function getBearerToken(request) {
const authorization = request.headers.authorization
if (!authorization?.startsWith('Bearer ')) {
return null
}
return authorization.slice('Bearer '.length).trim()
}
export function getSessionTokenFromRequest(request) {
return getBearerToken(request)
}
export async function createSession(userId) {
const token = createSessionToken()
const tokenHash = hashSessionToken(token)
const now = Date.now()
const expiresAt = now + env.SESSION_TTL_DAYS * 24 * 60 * 60 * 1000
const [session] = await db
.insert(authSessions)
.values({
userId,
tokenHash,
expiresAt: new Date(expiresAt),
createdAt: new Date(now),
})
.returning()
return {
token,
session,
}
}
export async function findAuthenticatedUser(request) {
const token = getBearerToken(request)
if (!token) {
return null
}
const tokenHash = hashSessionToken(token)
const [session] = await db
.select()
.from(authSessions)
.where(eq(authSessions.tokenHash, tokenHash))
.limit(1)
if (!session || new Date(session.expiresAt).getTime() <= Date.now()) {
return null
}
const [user] = await db
.select()
.from(users)
.where(eq(users.id, session.userId))
.limit(1)
if (user?.disabledAt) {
await db.delete(authSessions).where(eq(authSessions.id, session.id))
return null
}
if (user && user.role !== 'admin' && !user.emailVerifiedAt) {
await db.delete(authSessions).where(eq(authSessions.id, session.id))
return null
}
return user ?? null
}
export async function revokeSessionByToken(token) {
if (!token) {
return false
}
const tokenHash = hashSessionToken(token)
const deletedSessions = await db
.delete(authSessions)
.where(eq(authSessions.tokenHash, tokenHash))
.returning({ id: authSessions.id })
return deletedSessions.length > 0
}