import assert from "node:assert/strict"; import { once } from "node:events"; import { test } from "node:test"; import type { AccessFieldsDTO } from "@metis/companies/common"; import type { Sequelize } from "sequelize"; import { QueryTypes } from "sequelize"; import { WorkstationUseCases } from "../../../modules/assets/src/api/application/workstation.use-cases"; import { SequelizeAssetRepository } from "../../../modules/assets/src/api/infrastructure/persistence/sequelize-asset.repository"; import { AccessUseCases } from "../../../modules/companies/src/api/application/access.use-cases"; import { FolderMappingUseCases } from "../../../modules/companies/src/api/application/folder-mapping.use-cases"; import { buildFolderResponse } from "../../../modules/companies/src/api/application/folder-mapping-response.builder"; import { WorkProfileUseCases } from "../../../modules/companies/src/api/application/work-profile.use-cases"; import { AccessKindSchema } from "../../../modules/companies/src/api/domain/access/access-definition"; import { registerFolderMappingRoutes } from "../../../modules/companies/src/api/infrastructure/http/folder-mapping.routes"; import { AccessPersistenceMapper, SequelizeAccessRepository, } from "../../../modules/companies/src/api/infrastructure/persistence/access-persistence"; import { CompanyPersistenceMapper } from "../../../modules/companies/src/api/infrastructure/persistence/company-persistence.mapper"; import { migrateFolderMappings } from "../../../modules/companies/src/api/infrastructure/persistence/folder-mapping-migration"; import { completeLocalIdentityAssetConstraint, migrateLocalIdentityEnvironments, } from "../../../modules/companies/src/api/infrastructure/persistence/local-identity-migration"; import { SequelizeCompanyRepository } from "../../../modules/companies/src/api/infrastructure/persistence/sequelize-company.repository"; import { SequelizeFolderMappingRepository } from "../../../modules/companies/src/api/infrastructure/persistence/sequelize-folder-mapping.repository"; import { SequelizeWorkProfileRepository } from "../../../modules/companies/src/api/infrastructure/persistence/sequelize-work-profile.repository"; import { migrateWorkProfiles } from "../../../modules/companies/src/api/infrastructure/persistence/work-profile-migration"; import { FolderMappingResponseSchema } from "../../../modules/companies/src/common/folder-mappings"; import { LocalIdentityPageSchema } from "../../../modules/companies/src/common/local-identity-environments"; import { UniqueID } from "../../../packages/rdx-ddd/src/index"; import { cleanupMembershipFixture, prepareMembershipFixture, } from "./asset-directory-memberships.fixture"; import { createDatabase, readDatabaseEnvironment } from "./config/database"; test("MariaDB: identidades locales y cuenta documental de FolderMapping", async (t) => { const env = readDatabaseEnvironment(process.env); assert.equal(env.NODE_ENV, "test"); assert.equal(env.DB_NAME, "metis_desk_test"); const db = createDatabase(env); const company = UniqueID.generateNewID().toPrimitive(); const otherCompany = UniqueID.generateNewID().toPrimitive(); const actor = UniqueID.generateNewID().toPrimitive(); const person = UniqueID.generateNewID().toPrimitive(); const otherPerson = UniqueID.generateNewID().toPrimitive(); const workstations = new WorkstationUseCases(new SequelizeAssetRepository(db)); let workstationId: string | undefined; let ready = false; try { const f = await prepareMembershipFixture(db, "http://localhost:5173", actor, [ company, otherCompany, ]); ready = true; await migrateWorkProfiles(db); await migrateFolderMappings(db); await migrateFolderMappings(db); await migrateLocalIdentityEnvironments(db); await completeLocalIdentityAssetConstraint(db); const access = new AccessUseCases( new SequelizeAccessRepository( db, new SequelizeCompanyRepository(db, new CompanyPersistenceMapper()), new AccessPersistenceMapper() ) ); const folders = new FolderMappingUseCases( new SequelizeFolderMappingRepository(db, f.inventory) ); const profiles = new WorkProfileUseCases(new SequelizeWorkProfileRepository(db, f.inventory)); registerFolderMappingRoutes(f.app, folders, f.authenticate); for (const id of [person, otherPerson]) { await db.query( "INSERT INTO company_contacts (id,companyId,name,isContact,active) VALUES (:id,:company,'Local identity fixture',0,1)", { replacements: { id, company } } ); } const add = async (values: AccessFieldsDTO, scope = company) => { const before = await access.get(scope); assert.ok(before.isSuccess); const ids = new Set(before.data.workspace.items.map((item) => item.id.toPrimitive())); const saved = await access.save(scope, undefined, values, actor); assert.ok(saved.isSuccess, saved.isSuccess ? "" : saved.error.code); const item = saved.data.workspace.items.find((item) => !ids.has(item.id.toPrimitive())); assert.ok(item); return item; }; const nas = await f.asset(company, "nas"); const nas2 = await f.asset(company, "nas"); const desktop = await f.asset(company, "desktop"); const laptop = await f.asset(company, "laptop"); const foreign = await f.asset(otherCompany, "nas"); const system = await add({ kind: "system", name: "Identidades explícitas", active: true }); const local = (input: unknown) => f.localIdentities.execute(company, actor, input); const created = await local({ action: "create", assetId: nas.id.toPrimitive(), systemId: system.id.toPrimitive(), name: "NAS identidades", }); assert.ok(created.isSuccess); const environmentId = created.data.toPrimitive().environmentId; await t.test( "vínculos NAS, PC y portátil, sin dominio y con dominio; cuentas homónimas diferenciadas", async () => { for (const [asset, name] of [ [nas2, "NAS segundo"], [desktop, "PC"], [laptop, "Portátil"], ] as const) { assert.ok( ( await local({ action: "create", assetId: asset.id.toPrimitive(), systemId: system.id.toPrimitive(), name, }) ).isSuccess ); } const domain = await f.domain(company, `local-${company.slice(0, 8)}.local`); assert.ok( ( await f.membershipUseCases.execute( company, desktop.id.toPrimitive(), { action: "join", domainResourceId: domain.id.toPrimitive(), role: "member" }, actor ) ).isSuccess ); const desktopLinks = await f.localIdentities.list(company, { assetId: desktop.id.toPrimitive(), }); assert.ok(desktopLinks.isSuccess); assert.equal(desktopLinks.data.environments.length, 1); const second = await f.localIdentities.list(company, { assetId: nas2.id.toPrimitive() }); assert.ok(second.isSuccess && second.data.environments[0]); for (const environment of [environmentId, second.data.environments[0].environmentId]) { await add({ kind: "account", login: "juan", systemId: system.id.toPrimitive(), environmentId: environment, usage: "shared", active: true, expiresOn: null, notes: null, }); } const snapshot = await access.get(company); assert.ok(snapshot.isSuccess); assert.equal( snapshot.data.workspace.items.filter( (item) => item.values.data.kind === "account" && item.values.data.login === "juan" ).length, 2 ); } ); await t.test( "asociación idempotente, propietario inmutable, ámbitos y rechazo AD", async () => { const repeat = await local({ action: "associate", environmentId, assetId: nas.id.toPrimitive(), }); assert.ok(repeat.isSuccess); assert.equal(repeat.data.id.toPrimitive(), created.data.id.toPrimitive()); assert.equal( (await local({ action: "associate", environmentId, assetId: nas2.id.toPrimitive() })) .isSuccess, false ); assert.equal( (await local({ action: "associate", environmentId, assetId: foreign.id.toPrimitive() })) .isSuccess, false ); const domainRows = await db.query<{ environmentId: string; systemId: string }>( "SELECT environmentId,systemId FROM access_directory_environments WHERE companyId=:company", { replacements: { company }, type: QueryTypes.SELECT } ); assert.ok(domainRows[0]); assert.equal( ( await local({ action: "associate", environmentId: domainRows[0].environmentId, assetId: nas.id.toPrimitive(), }) ).isSuccess, false ); assert.equal( ( await local({ action: "create", systemId: domainRows[0].systemId, assetId: nas.id.toPrimitive(), name: "No clasificar AD como local", }) ).isSuccess, false ); assert.equal( ( await local({ action: "associate", environmentId: system.id.toPrimitive(), assetId: nas.id.toPrimitive(), }) ).isSuccess, false ); const otherEnvironment = await add( { kind: "environment", name: "Otra compañía", systemId: ( await add({ kind: "system", name: "Otro", active: true }, otherCompany) ).id.toPrimitive(), active: true, }, otherCompany ); assert.equal( ( await local({ action: "associate", environmentId: otherEnvironment.id.toPrimitive(), assetId: nas.id.toPrimitive(), }) ).isSuccess, false ); } ); await t.test( "asocia un entorno existente sin reescribirlo y serializa altas duplicadas", async () => { const environment = await add({ kind: "environment", name: "Entorno previamente creado", systemId: system.id.toPrimitive(), active: true, }); const command = { action: "associate", environmentId: environment.id.toPrimitive(), assetId: laptop.id.toPrimitive(), }; const results = await Promise.all([local(command), local(command)]); assert.ok(results[0]?.isSuccess && results[1]?.isSuccess); assert.equal(results[0].data.id.toPrimitive(), results[1].data.id.toPrimitive()); const loaded = await access.get(company); assert.ok(loaded.isSuccess); const unchanged = loaded.data.workspace.items.find((item) => item.id.equals(environment.id) ); assert.deepEqual( unchanged?.history.map((item) => item.id.toPrimitive()), environment.history.map((item) => item.id.toPrimitive()) ); } ); await t.test( "renombrado y desactivación conservan entorno, cuentas e historial; FK protege compañía y subtipo", async () => { assert.ok( ( await f.assetUseCases.save( company, nas.id.toPrimitive(), { ...nas.values.toPrimitive(), name: "NAS renombrado", status: "retired" }, actor ) ).isSuccess ); assert.equal( ( await local({ action: "create", assetId: nas.id.toPrimitive(), systemId: system.id.toPrimitive(), name: "Activo retirado", }) ).isSuccess, false ); const links = await f.localIdentities.list(company, { assetId: nas.id.toPrimitive() }); assert.ok(links.isSuccess); assert.equal(links.data.environments[0]?.environmentId, environmentId); const snapshot = await access.get(company); assert.ok(snapshot.isSuccess); assert.equal( snapshot.data.workspace.items.find((item) => item.id.toPrimitive() === environmentId) ?.values.data.kind, "environment" ); const rows = await db.query<{ name: string; active: number }>( "SELECT name,active FROM access_environment_values WHERE ownerId=:environmentId", { replacements: { environmentId }, type: QueryTypes.SELECT } ); assert.equal(rows[0]?.name, "NAS identidades"); assert.equal(rows[0]?.active, 1); assert.equal( (await f.assetUseCases.remove(company, nas.id.toPrimitive())).isSuccess, false ); await assert.rejects( db.query( "UPDATE access_local_identity_environments SET assetId=:foreign WHERE environmentId=:environmentId", { replacements: { foreign: foreign.id.toPrimitive(), environmentId } } ) ); await assert.rejects( db.query("UPDATE access_items SET kind='group' WHERE id=:environmentId", { replacements: { environmentId }, }) ); const retired = await local({ action: "retire", environmentId }); assert.ok(retired.isSuccess); const repeat = await local({ action: "retire", environmentId }); assert.ok(repeat.isSuccess); assert.deepEqual(repeat.data.toPrimitive(), retired.data.toPrimitive()); assert.equal( (await f.assetUseCases.remove(company, nas.id.toPrimitive())).isSuccess, false ); assert.equal( (await local({ action: "associate", environmentId, assetId: nas2.id.toPrimitive() })) .isSuccess, false ); } ); await t.test( "rollback al crear vínculo revierte también el entorno y su revisión", async () => { const before = await access.get(company); assert.ok(before.isSuccess); const trigger = `local_fixture_${company.replaceAll("-", "")}`; await db.query( `CREATE TRIGGER ${trigger} BEFORE INSERT ON access_local_identity_environments FOR EACH ROW BEGIN IF NEW.companyId='${company}' THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='local fixture rollback'; END IF; END` ); try { await assert.rejects( local({ action: "create", assetId: desktop.id.toPrimitive(), systemId: system.id.toPrimitive(), name: "Rollback", }) ); } finally { await db.query(`DROP TRIGGER ${trigger}`); } const after = await access.get(company); assert.ok(after.isSuccess); assert.deepEqual( after.data.workspace.items.map((item) => [ item.id.toPrimitive(), item.history.map((revision) => revision.id.toPrimitive()), ]), before.data.workspace.items.map((item) => [ item.id.toPrimitive(), item.history.map((revision) => revision.id.toPrimitive()), ]) ); } ); const resourceCatalog = await f.resourceUseCases.get(company); assert.ok(resourceCatalog.isSuccess); const template = resourceCatalog.data.catalog.definitions.find( (item) => item.stockKey.getOrUndefined() === "template:shared_folder" ); const unc = resourceCatalog.data.catalog.definitions.find( (item) => item.stockKey.getOrUndefined() === "field:unc" ); assert.ok(template && unc); const shared = await f.resourceUseCases.save( company, undefined, { name: "Docs", templateId: template.id.toPrimitive(), active: true, notes: "", characteristics: { [unc.id.toPrimitive()]: String.raw`\\NAS\Docs` }, }, actor ); assert.ok(shared.isSuccess); const resourceId = shared.data.resource.id.toPrimitive(); const resourceValues = shared.data.resource.values.toPrimitive(); assert.ok(resourceValues.integration?.kind === "access"); const resourceTypeId = resourceValues.integration.resourceTypeId; const accountBase = { kind: "account" as const, systemId: system.id.toPrimitive(), environmentId, usage: "shared" as const, active: true, expiresOn: null, notes: null, }; const firstAccount = await add({ ...accountBase, login: "perfil" }); const secondAccount = await add({ ...accountBase, login: "alternativa" }); const stranger = await add({ ...accountBase, login: "otra persona" }); const technical = await add({ ...accountBase, login: "servicio", usage: "technical" }); const period = { startDate: "2020-01-01", endDate: null }; const firstRelation = await add({ kind: "account_person", accountId: firstAccount.id.toPrimitive(), personId: person, ...period, configuration: "configured", }); const secondRelation = await add({ kind: "account_person", accountId: secondAccount.id.toPrimitive(), personId: person, ...period, configuration: "configured", }); await add({ kind: "account_person", accountId: stranger.id.toPrimitive(), personId: otherPerson, ...period, configuration: "configured", }); await add({ kind: "account_person", accountId: technical.id.toPrimitive(), personId: person, ...period, configuration: null, }); const permission = await add({ kind: "permission", name: "Lectura", active: true, resourceTypeId, description: null, }); const need = await add({ kind: "need", personId: person, resourceId, permissionIds: [permission.id.toPrimitive()], ...period, notes: null, }); const grant = await add({ kind: "grant", accountId: firstAccount.id.toPrimitive(), groupId: null, permissionId: permission.id.toPrimitive(), resourceId, ...period, configuration: "configured", }); await add({ kind: "coverage", needId: need.id.toPrimitive(), grantId: grant.id.toPrimitive(), accountPersonId: firstRelation.id.toPrimitive(), membershipId: null, ...period, }); const station = await workstations.save( company, undefined, { name: "Puesto fixture", active: true, siteId: null, personId: null, computerAssetId: desktop.id.toPrimitive(), assetIds: [desktop.id.toPrimitive()], }, actor ); assert.ok(station.isSuccess); workstationId = station.data.workstation.id.toPrimitive(); const profile = await profiles.save( company, undefined, { name: "Perfil local fixture", personId: person, assetId: desktop.id.toPrimitive(), accountId: firstAccount.id.toPrimitive(), active: true, notes: null, }, actor ); assert.ok(profile.isSuccess, profile.isSuccess ? "" : profile.error.code); const folderInput = { profileId: profile.data.profile.id.toPrimitive(), needId: need.id.toPrimitive(), path: String.raw`\\NAS\Docs`, driveLetter: "F:", state: "configured" as const, notes: null, }; const original = await folders.save(company, undefined, folderInput, actor); assert.ok(original.isSuccess); const mappingId = original.data.mapping.id.toPrimitive(); const read = async () => { const snapshot = await folders.get(company); assert.ok(snapshot.isSuccess); const mapping = snapshot.data.mappings.find((item) => item.id.toPrimitive() === mappingId); assert.ok(mapping); return buildFolderResponse(mapping, snapshot.data); }; await t.test( "mapeo antiguo desconocido; cuenta del perfil y alternativa sin atribuir cobertura de otra cuenta", async () => { assert.equal((await read()).accessAccountCoverage, "unknown"); assert.ok( ( await folders.save( company, mappingId, { ...folderInput, accessAccountId: firstAccount.id.toPrimitive() }, actor ) ).isSuccess ); assert.equal((await read()).accessAccountCoverage, "covered"); assert.ok( ( await folders.save( company, mappingId, { ...folderInput, accessAccountId: secondAccount.id.toPrimitive() }, actor ) ).isSuccess ); const response = await read(); assert.equal(response.permissionsCovered, true); assert.equal(response.accessAccountCoverage, "not-covered"); assert.equal(response.values.accessAccountId, secondAccount.id.toPrimitive()); assert.equal(response.history[0]?.values.accessAccountId, null); assert.equal(response.history.length, 3); assert.equal(response.history[0]?.id, original.data.mapping.history[0]?.id.toPrimitive()); } ); await t.test( "actualización ausente conserva, null retira; selecciones inválidas y cuentas técnicas documentales", async () => { assert.ok( (await folders.save(company, mappingId, { ...folderInput, notes: "Solo notas" }, actor)) .isSuccess ); assert.equal((await read()).values.accessAccountId, secondAccount.id.toPrimitive()); for (const id of [ stranger.id.toPrimitive(), system.id.toPrimitive(), UniqueID.generateNewID().toPrimitive(), ]) { assert.equal( (await folders.save(company, mappingId, { ...folderInput, accessAccountId: id }, actor)) .isSuccess, false ); } const foreignSystem = await add( { kind: "system", name: "Sistema ajeno", active: true }, otherCompany ); const foreignAccount = await add( { ...accountBase, systemId: foreignSystem.id.toPrimitive(), environmentId: null, login: "ajena", }, otherCompany ); assert.equal( ( await folders.save( company, mappingId, { ...folderInput, accessAccountId: foreignAccount.id.toPrimitive() }, actor ) ).isSuccess, false ); assert.ok( ( await folders.save( company, mappingId, { ...folderInput, accessAccountId: technical.id.toPrimitive() }, actor ) ).isSuccess ); assert.equal((await read()).accessAccountCoverage, "not-covered"); assert.ok( (await folders.save(company, mappingId, { ...folderInput, accessAccountId: null }, actor)) .isSuccess ); assert.equal((await read()).accessAccountCoverage, "unknown"); assert.equal((await read()).values.accessAccountId, null); const foreignWorkspace = await db.query<{ id: string }>( "SELECT id FROM access_workspaces WHERE companyId=:otherCompany", { replacements: { otherCompany }, type: QueryTypes.SELECT } ); await assert.rejects( db.query( "UPDATE folder_mappings SET accessAccountId=:id,accessAccountWorkspaceId=:workspace WHERE id=:mappingId", { replacements: { id: foreignAccount.id.toPrimitive(), workspace: foreignWorkspace[0]?.id, mappingId, }, } ) ); const workspace = await db.query<{ id: string }>( "SELECT id FROM access_workspaces WHERE companyId=:company", { replacements: { company }, type: QueryTypes.SELECT } ); await assert.rejects( db.query( "UPDATE folder_mappings SET accessAccountId=:id,accessAccountWorkspaceId=:workspace WHERE id=:mappingId", { replacements: { id: system.id.toPrimitive(), workspace: workspace[0]?.id, mappingId }, } ) ); } ); await t.test("revisiones conservan ámbito y subtipo de cuenta en MariaDB", async () => { const scope = await db.query<{ id: string }>( "SELECT id FROM access_workspaces WHERE companyId=:company", { replacements: { company }, type: QueryTypes.SELECT } ); const revision = original.data.mapping.history[0]; assert.ok(revision && scope[0]); await assert.rejects( db.query( "UPDATE folder_mapping_revisions SET accessAccountId=:account,accessAccountWorkspaceId=:workspace WHERE id=:id", { replacements: { account: system.id.toPrimitive(), workspace: scope[0].id, id: revision.id.toPrimitive(), }, } ) ); }); await t.test( "cobertura de grupo solo por la cuenta seleccionada y pertenencia vigente; caducidad documental derivada", async () => { const group = await add({ kind: "group", name: "Grupo NAS", identifier: "nas", systemId: system.id.toPrimitive(), environmentId, templateId: null, description: null, active: true, }); assert.equal( ( await folders.save( company, mappingId, { ...folderInput, accessAccountId: group.id.toPrimitive() }, actor ) ).isSuccess, false ); const membership = await add({ kind: "membership", accountId: secondAccount.id.toPrimitive(), groupId: group.id.toPrimitive(), ...period, configuration: "configured", }); const groupGrant = await add({ kind: "grant", accountId: null, groupId: group.id.toPrimitive(), permissionId: permission.id.toPrimitive(), resourceId, ...period, configuration: "configured", }); await add({ kind: "coverage", needId: need.id.toPrimitive(), grantId: groupGrant.id.toPrimitive(), accountPersonId: secondRelation.id.toPrimitive(), membershipId: membership.id.toPrimitive(), ...period, }); assert.ok( ( await folders.save( company, mappingId, { ...folderInput, accessAccountId: secondAccount.id.toPrimitive() }, actor ) ).isSuccess ); assert.equal((await read()).accessAccountCoverage, "covered"); assert.ok( ( await access.save( company, membership.id.toPrimitive(), { kind: "membership", accountId: secondAccount.id.toPrimitive(), groupId: group.id.toPrimitive(), startDate: "2020-01-01", endDate: "2021-01-01", configuration: "removal_pending", }, actor ) ).isSuccess ); assert.equal((await read()).accessAccountCoverage, "not-covered"); assert.ok( ( await access.save( company, secondAccount.id.toPrimitive(), { ...accountBase, login: "alternativa", active: false }, actor ) ).isSuccess ); assert.equal((await read()).accessAccountCoverage, "not-covered"); const preserved = await folders.save( company, mappingId, { ...folderInput, notes: "Cuenta inactiva conservada" }, actor ); assert.ok(preserved.isSuccess); assert.equal((await read()).values.accessAccountId, secondAccount.id.toPrimitive()); assert.ok( (await f.resourceUseCases.setActive(company, resourceId, false, actor)).isSuccess ); assert.equal((await read()).accessAccountCoverage, "not-covered"); assert.equal((await read()).permissionsCovered, false); } ); await t.test( "HTTP con sesión, CSRF, validación estricta, filtros y lectura de cuenta/cobertura", async () => { const http = f.app.listen(0, "127.0.0.1"); try { await once(http, "listening"); const address = http.address(); assert.ok(address && typeof address !== "string"); const base = `http://127.0.0.1:${address.port}`; const endpoint = `${base}/api/local-identity-environments/${company}`; assert.equal((await fetch(endpoint)).status, 401); const login = await fetch(`${base}/fixture-session`); const cookie = login.headers.get("set-cookie")?.split(";")[0]; assert.ok(cookie); const body = { action: "associate", assetId: desktop.id.toPrimitive(), environmentId }; const request = ( value: unknown, token = "a".repeat(64), origin = "http://localhost:5173" ) => fetch(endpoint, { method: "POST", headers: { cookie, origin, "x-csrf-token": token, "content-type": "application/json", }, body: JSON.stringify(value), }); assert.equal((await request(body, "invalid")).status, 403); assert.equal((await request(body, "a".repeat(64), "https://wrong.invalid")).status, 403); assert.equal((await request({ ...body, operatorId: actor })).status, 400); assert.equal((await request(body)).status, 409); assert.equal( ( await fetch( `${base}/api/local-identity-environments/${UniqueID.generateNewID().toPrimitive()}`, { headers: { cookie } } ) ).status, 404 ); const page = await fetch(`${endpoint}?pageSize=1&includeEnded=true`, { headers: { cookie }, }); assert.equal(page.status, 200); const data = LocalIdentityPageSchema.parse(await page.json()); assert.ok(data.nextAfterId); const next = LocalIdentityPageSchema.parse( await ( await fetch(`${endpoint}?pageSize=1&includeEnded=true&afterId=${data.nextAfterId}`, { headers: { cookie }, }) ).json() ); assert.notEqual(data.environments[0]?.id, next.environments[0]?.id); assert.equal( (await fetch(`${endpoint}?operatorId=${actor}`, { headers: { cookie } })).status, 400 ); const update = await fetch(`${base}/api/folder-mappings/${company}/${mappingId}/update`, { method: "POST", headers: { cookie, origin: "http://localhost:5173", "x-csrf-token": "a".repeat(64), "content-type": "application/json", }, body: JSON.stringify({ values: { ...folderInput, notes: "HTTP" } }), }); assert.equal(update.status, 200); const response = FolderMappingResponseSchema.parse(await update.json()); assert.equal(response.mapping.values.accessAccountId, secondAccount.id.toPrimitive()); assert.equal(response.mapping.accessAccountCoverage, "not-covered"); } finally { await new Promise((resolve, reject) => http.close((error) => (error ? reject(error) : resolve())) ); } } ); } finally { try { if (ready) { await cleanupLocalFixture( db, company, otherCompany, person, otherPerson, actor, workstations, workstationId ); } } finally { await db.close(); } } }); async function cleanupLocalFixture( db: Sequelize, company: string, otherCompany: string, person: string, otherPerson: string, actor: string, workstations: WorkstationUseCases, workstationId: string | undefined ) { for (const table of [ "folder_mapping_revisions", "folder_mappings", "work_profile_revisions", "work_profiles", ]) { const clause = table.endsWith("revisions") ? table === "folder_mapping_revisions" ? "mappingId IN (SELECT id FROM folder_mappings WHERE companyId=:company)" : "profileId IN (SELECT id FROM work_profiles WHERE companyId=:company)" : "companyId=:company"; await db.query(`DELETE FROM ${table} WHERE ${clause}`, { replacements: { company } }); } if (workstationId) { assert.ok((await workstations.remove(company, workstationId)).isSuccess); } await db.query( "DELETE p FROM access_need_revision_permissions p JOIN access_revisions r ON r.id=p.ownerId JOIN access_items i ON i.id=r.itemId JOIN access_workspaces w ON w.id=i.workspaceId WHERE w.companyId IN (:companies)", { replacements: { companies: [company, otherCompany] } } ); await db.query( "DELETE p FROM access_need_permissions p JOIN access_items i ON i.id=p.ownerId JOIN access_workspaces w ON w.id=i.workspaceId WHERE w.companyId IN (:companies)", { replacements: { companies: [company, otherCompany] } } ); for (const kind of AccessKindSchema.options) { await db.query( `DELETE v FROM access_${kind}_revision_values v JOIN access_revisions r ON r.id=v.ownerId JOIN access_items i ON i.id=r.itemId JOIN access_workspaces w ON w.id=i.workspaceId WHERE w.companyId IN (:companies)`, { replacements: { companies: [company, otherCompany] } } ); await db.query( `DELETE v FROM access_${kind}_values v JOIN access_items i ON i.id=v.ownerId JOIN access_workspaces w ON w.id=i.workspaceId WHERE w.companyId IN (:companies)`, { replacements: { companies: [company, otherCompany] } } ); } await db.query("DELETE FROM access_person_references WHERE personId IN (:people)", { replacements: { people: [person, otherPerson] }, }); await db.query("DELETE FROM company_contacts WHERE id IN (:people)", { replacements: { people: [person, otherPerson] }, }); await cleanupMembershipFixture(db, [company, otherCompany], actor); }