import { AppError } from '../common/errors/app-error'; import { Injectable } from '@nestjs/common'; import { DatabaseService } from '../database/database.service'; import type { Prisma } from '../generated/prisma/client'; import { hashToken } from './tokens'; import type { Principal } from './identity.types'; export const userAccess = { roles: { include: { role: true } } } as const; export async function readPrincipal( tx: Prisma.TransactionClient, sessionId: string, ): Promise { const session = await tx.session.findUnique({ where: { id: sessionId }, include: { user: { include: userAccess } }, }); if ( !session || session.expiresAt <= new Date() || session.user.status !== 'ACTIVE' ) { throw new AppError('SESSION_INVALID'); } return { userId: session.userId, organizationId: session.user.organizationId, sessionId, permissions: [ ...new Set(session.user.roles.flatMap((item) => item.role.permissions)), ], }; } @Injectable() export class SessionStore { constructor(private readonly db: DatabaseService) {} async authenticate(token: string): Promise { const session = await this.db.session.findUnique({ where: { tokenHash: hashToken(token) }, }); if (!session) throw new AppError('SESSION_INVALID'); return readPrincipal(this.db, session.id); } }