/** * Helpers para crear y borrar usuarios de test vía la API de ogCore. * Se usan en globalSetup / globalTeardown de Playwright. */ import { Agent } from 'undici'; import * as fs from 'fs'; import * as path from 'path'; export const API_URL = process.env['API_URL'] || 'https://ogserver.local/api'; export const APP_URL = process.env['APP_URL'] || 'https://localhost:4200/oggui'; export const ADMIN_USER = process.env['ADMIN_USER'] || 'ogadmin'; export const ADMIN_PASS = process.env['ADMIN_PASS'] || '12345678'; export const TEST_PASS = 'Test1234!'; // Nombres fijos — sin timestamp para que sean consistentes entre procesos export const TEST_USERS = { superAdmin: { username: 'e2e-superadmin', role: 'ROLE_SUPER_ADMIN' }, ouAdmin: { username: 'e2e-ouadmin', role: 'ROLE_ORGANIZATIONAL_UNIT_ADMIN' }, operator: { username: 'e2e-operator', role: 'ROLE_ORGANIZATIONAL_UNIT_OPERATOR' }, minimal: { username: 'e2e-minimal', role: 'ROLE_ORGANIZATIONAL_UNIT_MINIMAL' }, }; // Fichero temporal para pasar IRIs del setup al teardown const STATE_FILE = path.join(__dirname, '../../.e2e-state.json'); // undici Agent que ignora certificados autofirmados (equivalente a curl -k) const insecureAgent = new Agent({ connect: { rejectUnauthorized: false } }); async function fetchJson(url: string, init: RequestInit): Promise { const res = await fetch(url, { ...init, headers: { 'Content-Type': 'application/ld+json', ...(init.headers as any) }, dispatcher: insecureAgent, } as any); const text = await res.text(); try { return JSON.parse(text); } catch { return text; } } export async function getAdminToken(): Promise { const data = await fetchJson(`${API_URL}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: ADMIN_USER, password: ADMIN_PASS }), }); if (!data.token) throw new Error(`Login fallido: ${JSON.stringify(data)}`); return data.token; } async function findUserByUsername(token: string, username: string): Promise { const data = await fetchJson(`${API_URL}/users?username=${encodeURIComponent(username)}`, { method: 'GET', headers: { Authorization: `Bearer ${token}` }, }); const members = data['hydra:member'] ?? []; return members.length > 0 ? members[0]['@id'] : null; } async function findUserGroupByName(token: string, name: string): Promise { const data = await fetchJson(`${API_URL}/user-groups?name=${encodeURIComponent(name)}`, { method: 'GET', headers: { Authorization: `Bearer ${token}` }, }); const members = data['hydra:member'] ?? []; return members.length > 0 ? members[0]['@id'] : null; } async function deleteResource(token: string, iri: string): Promise { await fetch(`${API_URL.replace('/api', '')}${iri}`, { method: 'DELETE', headers: { Authorization: `Bearer ${token}` }, dispatcher: insecureAgent, } as any); } async function createUserGroup(token: string, role: string, name: string): Promise { const data = await fetchJson(`${API_URL}/user-groups`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ name, permissions: [role], enabled: true }), }); if (!data['@id']) throw new Error(`No se pudo crear UserGroup ${name}: ${JSON.stringify(data)}`); return data['@id']; } async function createUser(token: string, username: string, ugIri: string): Promise { const data = await fetchJson(`${API_URL}/users`, { method: 'POST', headers: { Authorization: `Bearer ${token}` }, body: JSON.stringify({ username, password: TEST_PASS, enabled: true, userGroups: [ugIri] }), }); if (!data['@id']) throw new Error(`No se pudo crear usuario ${username}: ${JSON.stringify(data)}`); return data['@id']; } export async function setupTestUsers(): Promise { const token = await getAdminToken(); const userIris: string[] = []; const ugIris: string[] = []; for (const { username, role } of Object.values(TEST_USERS)) { const ugName = `e2e-ug-${username}`; // Eliminar usuario previo si existe (limpia runs anteriores) const existingUser = await findUserByUsername(token, username); if (existingUser) { await deleteResource(token, existingUser); console.log(` ↺ Eliminado usuario previo: ${username}`); } // Eliminar UserGroup previo si existe const existingUg = await findUserGroupByName(token, ugName); if (existingUg) { await deleteResource(token, existingUg); } const ugIri = await createUserGroup(token, role, ugName); const userIri = await createUser(token, username, ugIri); ugIris.push(ugIri); userIris.push(userIri); console.log(` ✓ ${username} [${role}]`); } // Guarda IRIs en fichero para que teardown pueda leerlos (env vars no siempre pasan entre procesos) fs.writeFileSync(STATE_FILE, JSON.stringify({ userIris, ugIris }, null, 2)); } export async function teardownTestUsers(): Promise { if (!fs.existsSync(STATE_FILE)) return; const { userIris, ugIris } = JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8')); const token = await getAdminToken(); for (const iri of [...userIris, ...ugIris]) { await deleteResource(token, iri); console.log(` ✓ Eliminado: ${iri}`); } fs.unlinkSync(STATE_FILE); }