Add scouthub-attivit-be

This commit is contained in:
Lorenzo Sanesi
2026-07-23 19:34:00 +02:00
parent 904cd2ee9b
commit 2ee7d402b6
55 changed files with 9783 additions and 0 deletions
@@ -0,0 +1,41 @@
import { generateKeyPairSync } from 'crypto';
import jwt from 'jsonwebtoken';
import nock from 'nock';
import { env } from '../../src/config/env';
const KID = 'test-kid';
const CERTS_PATH = `/realms/${env.keycloak.realm}/protocol/openid-connect/certs`;
const { publicKey, privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 });
const jwk = publicKey.export({ format: 'jwk' }) as Record<string, unknown>;
const privateKeyPem = privateKey.export({ type: 'pkcs1', format: 'pem' }) as string;
const { privateKey: rogueKey } = generateKeyPairSync('rsa', { modulusLength: 2048 });
export const rogueKeyPem = rogueKey.export({ type: 'pkcs1', format: 'pem' }) as string;
export function mockKeycloakJwks(): void {
nock(env.keycloak.baseUrl)
.persist()
.get(CERTS_PATH)
.reply(200, { keys: [{ ...jwk, kid: KID, alg: 'RS256', use: 'sig' }] });
}
interface TokenPayload {
sub: string;
email?: string;
name?: string;
realm_access?: { roles?: string[] };
}
export function signValidToken(payload: TokenPayload, signOptions: jwt.SignOptions = {}): string {
return jwt.sign(payload, privateKeyPem, {
algorithm: 'RS256',
keyid: KID,
expiresIn: '5m',
...signOptions,
});
}
export function bearer(payload: TokenPayload, signOptions: jwt.SignOptions = {}): string {
return `Bearer ${signValidToken(payload, signOptions)}`;
}
@@ -0,0 +1,26 @@
import { execSync } from 'child_process';
import dotenv from 'dotenv';
export default async function globalSetup(): Promise<void> {
dotenv.config();
const databaseUrlTest = process.env.DATABASE_URL_TEST;
if (!databaseUrlTest) {
throw new Error("Variabile d'ambiente mancante: DATABASE_URL_TEST");
}
// Fa puntare tutto il codice applicativo (incluso src/db/prisma.ts) al DB di test,
// senza bisogno di modifiche altrove: dotenv.config() non sovrascrive DATABASE_URL
// gia' impostata qui.
process.env.DATABASE_URL = databaseUrlTest;
execSync('npx prisma migrate deploy', {
env: process.env,
stdio: 'inherit',
});
execSync('npx prisma db seed', {
env: process.env,
stdio: 'inherit',
});
}
@@ -0,0 +1,5 @@
import { prisma } from '../../src/db/prisma';
export default async function globalTeardown(): Promise<void> {
await prisma.$disconnect();
}
@@ -0,0 +1,18 @@
import { prisma } from '../../src/db/prisma';
// Solo le tabelle "transazionali" popolate dai test: le anagrafiche di base
// seedate una volta sola (stato_attivita, tipo_categoria, tipo_paragrafo,
// branca, periodo_anno, categoria, materiale) restano intatte tra un test e l'altro.
const TABLES_TO_RESET = [
'paragrafo',
'branca_attivita',
'categoria_attivita',
'materiale_attivita',
'periodo_anno_attivita',
'attivita',
];
export async function resetDatabase(): Promise<void> {
const tables = TABLES_TO_RESET.map((table) => `"${table}"`).join(', ');
await prisma.$executeRawUnsafe(`TRUNCATE TABLE ${tables} RESTART IDENTITY CASCADE`);
}