383 lines
11 KiB
TypeScript
383 lines
11 KiB
TypeScript
import assert from "node:assert/strict";
|
|
|
|
import type { AccessFieldsDTO, AccessItemDTO, CompanyDTO } from "@metis/companies/common";
|
|
import { AccessResponseSchema } from "@metis/companies/common";
|
|
|
|
export async function verifyAccess(
|
|
request: (path: string, body?: unknown, origin?: string, token?: string) => Promise<Response>,
|
|
company: CompanyDTO,
|
|
other: CompanyDTO
|
|
) {
|
|
const base = `/access/${company.id}`;
|
|
|
|
async function create(scope: string, values: AccessFieldsDTO) {
|
|
const response = await request(`/access/${scope}`, { values });
|
|
|
|
assert.equal(response.status, 201, JSON.stringify(await response.clone().json()));
|
|
const result = AccessResponseSchema.parse(await response.json());
|
|
const item = result.items.at(-1);
|
|
|
|
assert.ok(item);
|
|
assert.equal(item.values.kind, values.kind);
|
|
assert.equal(item.id[14], "7");
|
|
assert.equal(item.history.length, 1);
|
|
|
|
return item;
|
|
}
|
|
|
|
async function update(item: AccessItemDTO, values: AccessFieldsDTO) {
|
|
const response = await request(`${base}/${item.id}/update`, { values });
|
|
|
|
assert.equal(response.status, 200, JSON.stringify(await response.clone().json()));
|
|
|
|
return AccessResponseSchema.parse(await response.json());
|
|
}
|
|
|
|
const system = await create("global", { kind: "system", name: "Directorio", active: true });
|
|
const resourceType = await create("global", {
|
|
kind: "resource_type",
|
|
name: "Carpeta",
|
|
active: true,
|
|
});
|
|
const permission = await create("global", {
|
|
kind: "permission",
|
|
name: "Modificar",
|
|
description: null,
|
|
resourceTypeId: resourceType.id,
|
|
active: true,
|
|
});
|
|
const template = await create("global", {
|
|
kind: "template",
|
|
name: "Administración",
|
|
description: "Acceso a documentos",
|
|
systemId: system.id,
|
|
active: true,
|
|
});
|
|
|
|
assert.equal(
|
|
(await request(base, { values: { kind: "system", name: " DIRECTORIO ", active: false } }))
|
|
.status,
|
|
409
|
|
);
|
|
assert.equal(
|
|
(
|
|
await request(base, {
|
|
values: { kind: "system", name: "Zoom", active: true, password: "secret" },
|
|
})
|
|
).status,
|
|
400
|
|
);
|
|
assert.equal(
|
|
(
|
|
await request(
|
|
base,
|
|
{ values: { kind: "system", name: "Zoom", active: true } },
|
|
"https://wrong.example"
|
|
)
|
|
).status,
|
|
403
|
|
);
|
|
assert.equal(
|
|
(
|
|
await request(
|
|
base,
|
|
{ values: { kind: "system", name: "Zoom", active: true } },
|
|
undefined,
|
|
"wrong"
|
|
)
|
|
).status,
|
|
403
|
|
);
|
|
await create(company.id, { kind: "system", name: "ERP propio", active: true });
|
|
assert.equal(
|
|
(
|
|
await request("/access/global", {
|
|
values: { kind: "system", name: "ERP PROPIO", active: true },
|
|
})
|
|
).status,
|
|
409
|
|
);
|
|
const environment = await create(company.id, {
|
|
kind: "environment",
|
|
name: "Oficina",
|
|
systemId: system.id,
|
|
active: true,
|
|
});
|
|
const otherEnvironment = await create(other.id, {
|
|
kind: "environment",
|
|
name: "Oficina",
|
|
systemId: system.id,
|
|
active: true,
|
|
});
|
|
const accountValues: AccessFieldsDTO = {
|
|
kind: "account",
|
|
systemId: system.id,
|
|
environmentId: environment.id,
|
|
login: "ana",
|
|
usage: "personal",
|
|
active: true,
|
|
expiresOn: null,
|
|
notes: null,
|
|
};
|
|
const account = await create(company.id, accountValues);
|
|
|
|
assert.equal((await request(base, { values: accountValues })).status, 409);
|
|
assert.equal(
|
|
(
|
|
await request(base, {
|
|
values: {
|
|
...accountValues,
|
|
systemId: system.id.toUpperCase(),
|
|
environmentId: environment.id.toUpperCase(),
|
|
},
|
|
})
|
|
).status,
|
|
409
|
|
);
|
|
assert.equal(
|
|
(
|
|
await request(base, {
|
|
values: { ...accountValues, login: "foreign", environmentId: otherEnvironment.id },
|
|
})
|
|
).status,
|
|
409
|
|
);
|
|
assert.equal(
|
|
(
|
|
await request(`${base}/${account.id}/update`, {
|
|
values: { ...accountValues, usage: "shared" },
|
|
})
|
|
).status,
|
|
409
|
|
);
|
|
const renamed = { ...accountValues, login: "ana.garcia" };
|
|
const changed = await update(account, renamed);
|
|
|
|
assert.equal(changed.items.find((item) => item.id === account.id)?.history.length, 2);
|
|
const repeated = await update(account, renamed);
|
|
|
|
assert.equal(repeated.items.find((item) => item.id === account.id)?.history.length, 2);
|
|
const person = company.people.find((item) => item.active);
|
|
|
|
assert.ok(person);
|
|
const relationValues: AccessFieldsDTO = {
|
|
kind: "account_person",
|
|
accountId: account.id,
|
|
personId: person.id,
|
|
startDate: "2026-01-01",
|
|
endDate: null,
|
|
configuration: "configured",
|
|
};
|
|
const relation = await create(company.id, relationValues);
|
|
|
|
assert.equal((await request(base, { values: relationValues })).status, 409);
|
|
const foreignPerson = other.people[0];
|
|
|
|
if (foreignPerson) {
|
|
assert.equal(
|
|
(await request(base, { values: { ...relationValues, personId: foreignPerson.id } })).status,
|
|
409
|
|
);
|
|
}
|
|
const groupValues: AccessFieldsDTO = {
|
|
kind: "group",
|
|
name: "Administración",
|
|
identifier: "GG_ADMIN",
|
|
systemId: system.id,
|
|
environmentId: environment.id,
|
|
templateId: template.id,
|
|
description: "Documentos",
|
|
active: true,
|
|
};
|
|
const group = await create(company.id, groupValues);
|
|
const membershipValues: AccessFieldsDTO = {
|
|
kind: "membership",
|
|
accountId: account.id,
|
|
groupId: group.id,
|
|
startDate: "2026-01-01",
|
|
endDate: null,
|
|
configuration: "configured",
|
|
};
|
|
const membership = await create(company.id, membershipValues);
|
|
const resource = await create(company.id, {
|
|
kind: "resource",
|
|
name: "Documentos",
|
|
resourceTypeId: resourceType.id,
|
|
systemId: null,
|
|
environmentId: null,
|
|
reference: "\\\\NAS\\Administracion",
|
|
notes: null,
|
|
active: true,
|
|
});
|
|
const grantValues: AccessFieldsDTO = {
|
|
kind: "grant",
|
|
resourceId: resource.id,
|
|
permissionId: permission.id,
|
|
accountId: null,
|
|
groupId: group.id,
|
|
startDate: "2026-01-01",
|
|
endDate: null,
|
|
configuration: "configured",
|
|
};
|
|
const grant = await create(company.id, grantValues);
|
|
const needValues: AccessFieldsDTO = {
|
|
kind: "need",
|
|
resourceId: resource.id,
|
|
personId: person.id,
|
|
permissionIds: [permission.id],
|
|
startDate: "2026-01-01",
|
|
endDate: null,
|
|
notes: null,
|
|
};
|
|
const need = await create(company.id, needValues);
|
|
let response = AccessResponseSchema.parse(await (await request(base)).json());
|
|
|
|
assert.equal(response.coverage.find((item) => item.needId === need.id)?.covered, false);
|
|
assert.ok(
|
|
response.reviews.some((item) => item.itemId === grant.id && item.reason === "unjustified")
|
|
);
|
|
await create(company.id, {
|
|
kind: "coverage",
|
|
needId: need.id,
|
|
grantId: grant.id,
|
|
accountPersonId: relation.id,
|
|
membershipId: membership.id,
|
|
startDate: "2026-01-01",
|
|
endDate: null,
|
|
});
|
|
response = AccessResponseSchema.parse(await (await request(base)).json());
|
|
assert.equal(response.coverage.find((item) => item.needId === need.id)?.covered, true);
|
|
assert.equal(
|
|
response.reviews.some((item) => item.itemId === grant.id && item.reason === "unjustified"),
|
|
false
|
|
);
|
|
const awaitingConfiguration = await update(relation, {
|
|
...relationValues,
|
|
configuration: "pending",
|
|
});
|
|
|
|
assert.equal(
|
|
awaitingConfiguration.coverage.find((item) => item.needId === need.id)?.covered,
|
|
false
|
|
);
|
|
assert.equal(
|
|
awaitingConfiguration.reviews.some(
|
|
(item) => item.itemId === grant.id && item.reason === "unjustified"
|
|
),
|
|
false
|
|
);
|
|
await update(relation, relationValues);
|
|
const readPermission = await create("global", {
|
|
kind: "permission",
|
|
name: "Lectura",
|
|
description: null,
|
|
resourceTypeId: resourceType.id,
|
|
active: true,
|
|
});
|
|
const differentNeed = await update(need, { ...needValues, permissionIds: [readPermission.id] });
|
|
|
|
assert.equal(differentNeed.coverage.find((item) => item.needId === need.id)?.covered, false);
|
|
assert.ok(
|
|
differentNeed.reviews.some((item) => item.itemId === grant.id && item.reason === "unjustified")
|
|
);
|
|
await update(need, needValues);
|
|
const closed = await update(membership, {
|
|
...membershipValues,
|
|
endDate: "2026-10-03",
|
|
configuration: "removal_pending",
|
|
});
|
|
|
|
assert.equal(closed.coverage.find((item) => item.needId === need.id)?.covered, false);
|
|
assert.ok(
|
|
closed.reviews.some(
|
|
(item) => item.itemId === membership.id && item.reason === "pending_removal"
|
|
)
|
|
);
|
|
const removed = await update(membership, {
|
|
...membershipValues,
|
|
endDate: "2026-10-03",
|
|
configuration: "removed",
|
|
});
|
|
|
|
assert.equal(
|
|
removed.reviews.some(
|
|
(item) => item.itemId === membership.id && item.reason === "pending_removal"
|
|
),
|
|
false
|
|
);
|
|
assert.equal(removed.items.find((item) => item.id === membership.id)?.history.length, 3);
|
|
assert.equal(
|
|
removed.items
|
|
.find((item) => item.id === membership.id)
|
|
?.history.every((item) => Boolean(item.actorId)),
|
|
true
|
|
);
|
|
const expired = await update(account, { ...renamed, expiresOn: "2000-01-01" });
|
|
|
|
assert.ok(
|
|
expired.reviews.some((item) => item.itemId === account.id && item.reason === "expired")
|
|
);
|
|
assert.equal(
|
|
(await request(base, { values: { ...membershipValues, startDate: "2026-10-03" } })).status,
|
|
409
|
|
);
|
|
const technical = await create(company.id, {
|
|
...accountValues,
|
|
login: "svc-backup",
|
|
usage: "technical",
|
|
active: false,
|
|
expiresOn: "2000-01-01",
|
|
});
|
|
|
|
await create(company.id, { ...relationValues, accountId: technical.id, configuration: null });
|
|
const otherTechnical = await create(company.id, {
|
|
...accountValues,
|
|
login: "svc-clean",
|
|
usage: "technical",
|
|
active: true,
|
|
});
|
|
|
|
assert.equal(
|
|
(
|
|
await request(base, {
|
|
values: { ...relationValues, accountId: otherTechnical.id, configuration: "configured" },
|
|
})
|
|
).status,
|
|
400
|
|
);
|
|
const shared = await create(company.id, { ...accountValues, login: "shared", usage: "shared" });
|
|
const sharedResponse = AccessResponseSchema.parse(await (await request(base)).json());
|
|
|
|
assert.ok(
|
|
sharedResponse.reviews.some((item) => item.itemId === shared.id && item.reason === "incomplete")
|
|
);
|
|
const concurrent = await Promise.all([
|
|
request(base, { values: { ...accountValues, login: "concurrent" } }),
|
|
request(base, { values: { ...accountValues, login: "concurrent" } }),
|
|
]);
|
|
|
|
assert.deepEqual(concurrent.map((item) => item.status).sort(), [201, 409]);
|
|
const otherScope = AccessResponseSchema.parse(
|
|
await (await request(`/access/${other.id}`)).json()
|
|
);
|
|
|
|
assert.equal(
|
|
otherScope.items.some((item) => item.id === account.id),
|
|
false
|
|
);
|
|
assert.equal(
|
|
otherScope.items.some((item) => item.id === system.id),
|
|
true
|
|
);
|
|
const global = AccessResponseSchema.parse(await (await request("/access/global")).json());
|
|
|
|
assert.equal(
|
|
global.items.every((item) => item.companyId === null),
|
|
true
|
|
);
|
|
assert.equal(
|
|
(await request(`/access/${other.id}/${account.id}/update`, { values: renamed })).status,
|
|
404
|
|
);
|
|
}
|