113 lines
4.9 KiB
TypeScript
113 lines
4.9 KiB
TypeScript
|
|
import assert from "node:assert/strict";
|
||
|
|
|
||
|
|
import { InventoryResponseSchema } from "@metis/assets/common";
|
||
|
|
import {
|
||
|
|
SoftwareInstallationResponseSchema,
|
||
|
|
SoftwareInstallationsResponseSchema,
|
||
|
|
} from "@metis/companies/common";
|
||
|
|
import { CatalogResponseSchema, ResourceResponseSchema } from "@metis/resources/common";
|
||
|
|
import type { Sequelize } from "sequelize";
|
||
|
|
|
||
|
|
import { migrateSoftwareInstallations } from "../../../modules/companies/src/api/infrastructure/persistence/software-installation-migration";
|
||
|
|
|
||
|
|
type Request = (path: string, body?: unknown, origin?: string, token?: string) => Promise<Response>;
|
||
|
|
|
||
|
|
export async function verifySoftwareInstallations(
|
||
|
|
request: Request,
|
||
|
|
companyId: string,
|
||
|
|
otherId: string,
|
||
|
|
database: Sequelize
|
||
|
|
) {
|
||
|
|
await migrateSoftwareInstallations(database);
|
||
|
|
const inventory = InventoryResponseSchema.parse(
|
||
|
|
await (await request(`/assets/${companyId}`)).json()
|
||
|
|
);
|
||
|
|
const host = inventory.assets.find((asset) => asset.values.status !== "retired");
|
||
|
|
const otherHost = InventoryResponseSchema.parse(
|
||
|
|
await (await request(`/assets/${otherId}`)).json()
|
||
|
|
).assets[0];
|
||
|
|
const catalog = CatalogResponseSchema.parse(
|
||
|
|
await (await request(`/resource-catalog/${companyId}`)).json()
|
||
|
|
);
|
||
|
|
const template = catalog.items.find((item) => item.builtinKey === "template:os");
|
||
|
|
const application = catalog.items.find((item) => item.builtinKey === "template:application");
|
||
|
|
const certificate = catalog.items.find((item) => item.builtinKey === "template:certificate");
|
||
|
|
|
||
|
|
assert.ok(host && otherHost && template && application && certificate);
|
||
|
|
assert.ok(template.values.kind === "template" && template.values.usage === "os");
|
||
|
|
|
||
|
|
const addResource = async (templateId: string, name: string) => {
|
||
|
|
const response = await request(`/resources/${companyId}`, {
|
||
|
|
values: { name, templateId, active: true, notes: "", characteristics: {} },
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(response.status, 201, await response.clone().text());
|
||
|
|
|
||
|
|
return ResourceResponseSchema.parse(await response.json()).resource;
|
||
|
|
};
|
||
|
|
|
||
|
|
const os = await addResource(template.id, "Windows 11 Pro test");
|
||
|
|
const app = await addResource(application.id, "Office equipo test");
|
||
|
|
const cert = await addResource(certificate.id, "Certificado no instalable como software");
|
||
|
|
const path = `/software-installations/${companyId}`;
|
||
|
|
const values = {
|
||
|
|
assetId: host.id,
|
||
|
|
resourceId: os.id,
|
||
|
|
version: "24H2",
|
||
|
|
state: "configured",
|
||
|
|
notes: null,
|
||
|
|
};
|
||
|
|
const foreign = await request(path, { values: { ...values, assetId: otherHost.id } });
|
||
|
|
|
||
|
|
assert.equal(foreign.status, 404);
|
||
|
|
assert.equal((await request(path, { values: { ...values, resourceId: cert.id } })).status, 404);
|
||
|
|
assert.equal((await request(path, { values: { ...values, profileId: host.id } })).status, 400);
|
||
|
|
assert.equal((await request(path, { values }, "https://other.example")).status, 403);
|
||
|
|
assert.equal((await request(path, { values }, undefined, "a".repeat(64))).status, 403);
|
||
|
|
const responses = await Promise.all([request(path, { values }), request(path, { values })]);
|
||
|
|
|
||
|
|
assert.deepEqual(responses.map((response) => response.status).sort(), [201, 409]);
|
||
|
|
const success = responses.find((response) => response.status === 201);
|
||
|
|
|
||
|
|
assert.ok(success);
|
||
|
|
const created = SoftwareInstallationResponseSchema.parse(await success.json()).configuration;
|
||
|
|
|
||
|
|
const save = async (data: typeof values) => {
|
||
|
|
const response = await request(`${path}/${created.id}/update`, { values: data });
|
||
|
|
|
||
|
|
assert.equal(response.status, 200, await response.clone().text());
|
||
|
|
|
||
|
|
return SoftwareInstallationResponseSchema.parse(await response.json()).configuration;
|
||
|
|
};
|
||
|
|
|
||
|
|
assert.deepEqual(await save(values), created);
|
||
|
|
const updated = await save({ ...values, version: "25H2" });
|
||
|
|
|
||
|
|
assert.equal(updated.history.length, 2);
|
||
|
|
assert.equal(updated.history[0]?.values.version, "24H2");
|
||
|
|
assert.equal(updated.history[1]?.values.version, "25H2");
|
||
|
|
assert.equal((await request(path, { values: { ...values, resourceId: app.id } })).status, 201);
|
||
|
|
assert.equal(
|
||
|
|
(await request(`/software-installations/${otherId}/${created.id}/update`, { values })).status,
|
||
|
|
404
|
||
|
|
);
|
||
|
|
assert.equal(
|
||
|
|
SoftwareInstallationsResponseSchema.parse(
|
||
|
|
await (await request(`/software-installations/${otherId}`)).json()
|
||
|
|
).configurations.length,
|
||
|
|
0
|
||
|
|
);
|
||
|
|
const deactivate = await request(`/resources/${companyId}/${os.id}/update`, {
|
||
|
|
values: { ...os.values, active: false },
|
||
|
|
});
|
||
|
|
|
||
|
|
assert.equal(deactivate.status, 200);
|
||
|
|
const listed = SoftwareInstallationsResponseSchema.parse(await (await request(path)).json());
|
||
|
|
|
||
|
|
assert.equal(listed.configurations.find((item) => item.id === created.id)?.needsReview, true);
|
||
|
|
await save({ ...values, version: "25H2", state: "removal_pending" });
|
||
|
|
await save({ ...values, version: "25H2", state: "removed" });
|
||
|
|
assert.equal((await request(`${path}/${created.id}/delete`, {})).status, 200);
|
||
|
|
assert.equal((await request(`${path}/${created.id}/delete`, {})).status, 404);
|
||
|
|
}
|