metis-desk/apps/server/src/local-identities-folder-mapping.integration.test.ts

1003 lines
34 KiB
TypeScript
Raw Normal View History

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<void>((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);
}