Import source: backend/src/lib/auth
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
import type { FastifyInstance, FastifyRequest } from "fastify";
|
||||||
|
import type { SessionContext } from "./serializers.js";
|
||||||
|
import { forbidden, permissionDenied } from "./envelope.js";
|
||||||
|
|
||||||
|
export function parseCookies(header: string | undefined) {
|
||||||
|
const cookies: Record<string, string> = {};
|
||||||
|
if (!header) return cookies;
|
||||||
|
|
||||||
|
for (const part of header.split(";")) {
|
||||||
|
const [rawKey, ...rawValue] = part.trim().split("=");
|
||||||
|
if (!rawKey) continue;
|
||||||
|
cookies[rawKey] = decodeURIComponent(rawValue.join("="));
|
||||||
|
}
|
||||||
|
|
||||||
|
return cookies;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sessionCookie(request: FastifyRequest) {
|
||||||
|
return parseCookies(request.headers.cookie).session_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function requireSession(app: FastifyInstance, request: FastifyRequest) {
|
||||||
|
const sessionId = sessionCookie(request);
|
||||||
|
if (!sessionId) throw permissionDenied();
|
||||||
|
|
||||||
|
const session = await app.prisma.session.findUnique({
|
||||||
|
where: { id: sessionId },
|
||||||
|
include: {
|
||||||
|
user: {
|
||||||
|
include: {
|
||||||
|
permissions: true,
|
||||||
|
accounts: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!session || session.expiresAt <= new Date()) {
|
||||||
|
if (session) {
|
||||||
|
await app.prisma.session.delete({ where: { id: session.id } }).catch(() => undefined);
|
||||||
|
}
|
||||||
|
throw permissionDenied();
|
||||||
|
}
|
||||||
|
|
||||||
|
return session as SessionContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function requireRole(
|
||||||
|
app: FastifyInstance,
|
||||||
|
request: FastifyRequest,
|
||||||
|
roles: string[],
|
||||||
|
) {
|
||||||
|
const session = await requireSession(app, request);
|
||||||
|
if (!roles.includes(session.user.role)) {
|
||||||
|
throw forbidden(`Role ${session.user.role} is not authorized for this operation.`);
|
||||||
|
}
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function accountIdFor(session: SessionContext) {
|
||||||
|
return session.user.accounts[0]?.accountId ?? "acct-main";
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user