- Asociar entornos locales con activos y conservar su trazabilidad. - Registrar la cuenta de acceso del mapeo con historial de cambios. - Calcular cobertura documental específica sin alterar la cobertura general. - Añadir migraciones, validaciones, endpoints protegidos, pruebas y documentación.
187 lines
6.0 KiB
TypeScript
187 lines
6.0 KiB
TypeScript
import type { UniqueID } from "@repo/rdx-ddd";
|
|
import { Maybe, Result } from "@repo/rdx-utils";
|
|
|
|
import type { Resource } from "../domain/resource.aggregate";
|
|
import { ResourceCatalogError } from "../domain/resource-definition";
|
|
import type { ResourceInput } from "../domain/resource-values";
|
|
import { ResourceSpecification, ResourceValues } from "../domain/value-objects/resource-values.vo";
|
|
|
|
import { directoryDomainInput } from "./directory-domain-input";
|
|
import type { InventoryContext } from "./resource.repository";
|
|
import { mapSmbAccessInput } from "./smb-access-input";
|
|
|
|
export function mapResourceInput(
|
|
input: ResourceInput,
|
|
companyId: UniqueID,
|
|
context: InventoryContext,
|
|
previous?: Resource
|
|
) {
|
|
if (previous && previous.values.toPrimitive().templateId !== input.templateId.toLowerCase()) {
|
|
return Result.fail(new ResourceCatalogError("TEMPLATE_FIXED"));
|
|
}
|
|
const captured = previous
|
|
? Result.ok(previous.specification)
|
|
: captureResourceSpecification(input, companyId, context);
|
|
|
|
if (!captured.isSuccess) {
|
|
return captured;
|
|
}
|
|
const specification = captured.data;
|
|
const directory = directoryDomainInput(input, context.catalog);
|
|
|
|
if (!directory.isSuccess) {
|
|
return directory;
|
|
}
|
|
const normalized = directory.data
|
|
? {
|
|
...input,
|
|
characteristics: {
|
|
...directory.data.characteristics,
|
|
[directory.data.dnsId]: directory.data.identity.dnsName,
|
|
[directory.data.netbiosId]: directory.data.identity.netbiosName ?? "",
|
|
},
|
|
}
|
|
: input;
|
|
const mailboxInput = withMailboxIntegration(normalized, context);
|
|
const integrated = mapSmbAccessInput(mailboxInput, context, previous);
|
|
|
|
if (!integrated.isSuccess) {
|
|
return integrated;
|
|
}
|
|
const compatibleInput = integrated.data;
|
|
const templateKey = context.catalog.definitions
|
|
.find((item) => item.id.toPrimitive() === input.templateId.toLowerCase())
|
|
?.stockKey.getOrUndefined();
|
|
|
|
if (templateKey === "template:access" && compatibleInput.integration?.kind !== "access") {
|
|
return Result.fail(new ResourceCatalogError("REFERENCE_UNAVAILABLE"));
|
|
}
|
|
const references = validateReferences(compatibleInput, context);
|
|
|
|
if (!references.isSuccess) {
|
|
return references;
|
|
}
|
|
const values = ResourceValues.create(compatibleInput, specification);
|
|
|
|
return values.isSuccess ? Result.ok({ specification, values: values.data }) : values;
|
|
}
|
|
|
|
export function captureResourceSpecification(
|
|
input: Pick<ResourceInput, "templateId">,
|
|
companyId: UniqueID,
|
|
context: Pick<InventoryContext, "catalog">,
|
|
options: { existing?: boolean } = {}
|
|
) {
|
|
const template = context.catalog
|
|
.visible(Maybe.some(companyId))
|
|
.find((item) => item.id.toPrimitive() === input.templateId.toLowerCase());
|
|
|
|
if (
|
|
!template ||
|
|
template.values.data.kind !== "template" ||
|
|
!(options.existing || context.catalog.active(template, Maybe.some(companyId)))
|
|
) {
|
|
return Result.fail(new ResourceCatalogError("TEMPLATE_UNAVAILABLE"));
|
|
}
|
|
const fields = template.values.data.fields.map((binding) => {
|
|
const field = context.catalog.definitions.find(
|
|
(item) => item.id.toPrimitive() === binding.fieldId
|
|
);
|
|
|
|
if (!field || field.values.data.kind !== "field") {
|
|
throw new Error("Plantilla persistida inconsistente.");
|
|
}
|
|
|
|
return {
|
|
fieldId: field.id.toPrimitive(),
|
|
name: field.values.data.name,
|
|
type: field.values.data.type,
|
|
unit: field.values.data.unit,
|
|
choices: [...field.values.data.choices],
|
|
required: binding.required,
|
|
...(binding.sectionId ? { sectionId: binding.sectionId } : {}),
|
|
};
|
|
});
|
|
const created = ResourceSpecification.create({
|
|
templateId: template.id.toPrimitive(),
|
|
templateName: template.values.data.name,
|
|
...(template.values.data.sections ? { sections: [...template.values.data.sections] } : {}),
|
|
fields,
|
|
});
|
|
|
|
if (!created.isSuccess) {
|
|
return created;
|
|
}
|
|
|
|
return created;
|
|
}
|
|
|
|
function withMailboxIntegration(input: ResourceInput, context: InventoryContext): ResourceInput {
|
|
const compatibleInput = { ...input };
|
|
|
|
if (!compatibleInput.integration) {
|
|
const template = context.catalog.definitions.find(
|
|
(item) => item.id.toPrimitive() === input.templateId.toLowerCase()
|
|
);
|
|
|
|
if (template?.stockKey.getOrUndefined() === "template:mailbox") {
|
|
const addressFieldId = context.catalog.definitions
|
|
.find((item) => item.stockKey.getOrUndefined() === "field:email")
|
|
?.id.toPrimitive();
|
|
const contextFieldId = context.catalog.definitions
|
|
.find((item) => item.stockKey.getOrUndefined() === "field:context")
|
|
?.id.toPrimitive();
|
|
|
|
if (!(addressFieldId && contextFieldId)) {
|
|
throw new Error("Campos de buzón ausentes.");
|
|
}
|
|
compatibleInput.integration = {
|
|
kind: "mailbox",
|
|
addressFieldId,
|
|
contextFieldId,
|
|
mailboxKind: "corporate",
|
|
accountId: null,
|
|
};
|
|
}
|
|
}
|
|
|
|
return compatibleInput;
|
|
}
|
|
|
|
function validateReferences(compatibleInput: ResourceInput, context: InventoryContext) {
|
|
const integration = compatibleInput.integration;
|
|
|
|
if (integration) {
|
|
const expected =
|
|
integration.kind === "mailbox"
|
|
? ([[integration.accountId, "account"]] as const)
|
|
: ([
|
|
[integration.resourceTypeId, "resource_type"],
|
|
[integration.systemId, "system"],
|
|
[integration.environmentId, "environment"],
|
|
] as const);
|
|
|
|
for (const [id, kind] of expected) {
|
|
if (
|
|
id &&
|
|
!context.references.some((item) => item.id === id.toLowerCase() && item.kind === kind)
|
|
) {
|
|
return Result.fail(new ResourceCatalogError("REFERENCE_UNAVAILABLE"));
|
|
}
|
|
}
|
|
if (
|
|
integration.kind === "access" &&
|
|
integration.environmentId &&
|
|
!context.references.some(
|
|
(item) =>
|
|
item.id === integration.environmentId?.toLowerCase() &&
|
|
item.systemId === integration.systemId
|
|
)
|
|
) {
|
|
return Result.fail(new ResourceCatalogError("REFERENCE_UNAVAILABLE"));
|
|
}
|
|
}
|
|
|
|
return Result.ok(true);
|
|
}
|