140 lines
5.3 KiB
TypeScript
140 lines
5.3 KiB
TypeScript
/**
|
|
* 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<any> {
|
|
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<string> {
|
|
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<string | null> {
|
|
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<string | null> {
|
|
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<void> {
|
|
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<string> {
|
|
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<string> {
|
|
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<void> {
|
|
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<void> {
|
|
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);
|
|
}
|