From 14f00be3c0dd88a8a2dce30192216811be6da896 Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Thu, 19 Dec 2024 11:01:14 +0100 Subject: [PATCH 01/12] Api Gateway tenant and Catalog API return descriptor filtered by Draft and Wating for approval --- .../src/api/catalogApiConverter.ts | 13 ++-- .../src/services/catalogService.ts | 71 ++++++++----------- .../api-gateway/src/services/validators.ts | 20 +++--- 3 files changed, 50 insertions(+), 54 deletions(-) diff --git a/packages/api-gateway/src/api/catalogApiConverter.ts b/packages/api-gateway/src/api/catalogApiConverter.ts index edc7a6e960..ddfc6e3beb 100644 --- a/packages/api-gateway/src/api/catalogApiConverter.ts +++ b/packages/api-gateway/src/api/catalogApiConverter.ts @@ -5,12 +5,15 @@ import { } from "pagopa-interop-api-clients"; import { Logger } from "pagopa-interop-commons"; import { - assertNonDraftDescriptor, + assertNonValidDescriptor, assertRegistryAttributeExists, } from "../services/validators.js"; -export type NonDraftCatalogApiDescriptor = catalogApi.EServiceDescriptor & { - state: Exclude; +export type validCatalogApiDescriptor = catalogApi.EServiceDescriptor & { + state: Exclude< + catalogApi.EServiceDescriptorState, + "DRAFT" | "WAITING_FOR_APPROVAL" + >; }; export function toApiGatewayCatalogEservice( @@ -94,12 +97,12 @@ export function toApiGatewayDescriptorDocument( }; } -export function toApiGatewayDescriptorIfNotDraft( +export function toApiGatewayDescriptorIfIsValid( descriptor: catalogApi.EServiceDescriptor, eserviceId: catalogApi.EService["id"], logger: Logger ): apiGatewayApi.EServiceDescriptor { - assertNonDraftDescriptor(descriptor, descriptor.id, eserviceId, logger); + assertNonValidDescriptor(descriptor, eserviceId, logger); return { id: descriptor.id, diff --git a/packages/api-gateway/src/services/catalogService.ts b/packages/api-gateway/src/services/catalogService.ts index 08fd23d14d..f0039379d2 100644 --- a/packages/api-gateway/src/services/catalogService.ts +++ b/packages/api-gateway/src/services/catalogService.ts @@ -5,29 +5,30 @@ import { removeDuplicates, WithLogger, } from "pagopa-interop-commons"; +import { + toApiGatewayCatalogEservice, + toApiGatewayDescriptorIfIsValid, + toApiGatewayEserviceAttributes, + validCatalogApiDescriptor, +} from "../api/catalogApiConverter.js"; +import { clientStatusCodeToError } from "../clients/catchClientError.js"; import { AttributeProcessClient, CatalogProcessClient, TenantProcessClient, } from "../clients/clientsProvider.js"; -import { ApiGatewayAppContext } from "../utilities/context.js"; -import { - NonDraftCatalogApiDescriptor, - toApiGatewayCatalogEservice, - toApiGatewayDescriptorIfNotDraft, - toApiGatewayEserviceAttributes, -} from "../api/catalogApiConverter.js"; import { eserviceDescriptorNotFound, eserviceNotFound, } from "../models/errors.js"; -import { clientStatusCodeToError } from "../clients/catchClientError.js"; +import { ApiGatewayAppContext } from "../utilities/context.js"; +import { getAllBulkAttributes } from "./attributeService.js"; +import { getOrganization } from "./tenantService.js"; import { assertAvailableDescriptorExists, - assertNonDraftDescriptor, + assertNonValidDescriptor, + invalidDescriptorStates, } from "./validators.js"; -import { getAllBulkAttributes } from "./attributeService.js"; -import { getOrganization } from "./tenantService.js"; export function getAllEservices( catalogProcessClient: CatalogProcessClient, @@ -132,7 +133,7 @@ export function catalogServiceBuilder( const descriptor = retrieveEserviceDescriptor(eservice, descriptorId); - return toApiGatewayDescriptorIfNotDraft(descriptor, eserviceId, logger); + return toApiGatewayDescriptorIfIsValid(descriptor, eserviceId, logger); }, getEserviceDescriptors: async ( { logger, headers }: WithLogger, @@ -147,16 +148,16 @@ export function catalogServiceBuilder( ); const descriptors = eservice.descriptors - .filter(isNonDraft) - .map((d) => toApiGatewayDescriptorIfNotDraft(d, eserviceId, logger)); + .filter(isValidDescriptorState) + .map((d) => toApiGatewayDescriptorIfIsValid(d, eserviceId, logger)); return { descriptors }; }, }; } -const isNonDraft = (d: catalogApi.EServiceDescriptor): boolean => - d.state !== catalogApi.EServiceDescriptorState.Values.DRAFT; +const isValidDescriptorState = (d: catalogApi.EServiceDescriptor): boolean => + !invalidDescriptorStates.includes(d.state); function retrieveEserviceDescriptor( eservice: catalogApi.EService, @@ -171,34 +172,25 @@ function retrieveEserviceDescriptor( return descriptor; } -function getLatestNonDraftDescriptor( +function getLatestValidDescriptor( eservice: catalogApi.EService, logger: Logger -): NonDraftCatalogApiDescriptor { - const latestNonDraftDescriptor = eservice.descriptors - .filter(isNonDraft) +): validCatalogApiDescriptor { + const latestValidDescriptor = eservice.descriptors + .filter(isValidDescriptorState) .sort((a, b) => Number(a.version) - Number(b.version)) .at(-1); - assertAvailableDescriptorExists( - latestNonDraftDescriptor, - eservice.id, - logger - ); - assertNonDraftDescriptor( - latestNonDraftDescriptor, - latestNonDraftDescriptor.id, - eservice.id, - logger - ); + assertAvailableDescriptorExists(latestValidDescriptor, eservice.id, logger); + assertNonValidDescriptor(latestValidDescriptor, eservice.id, logger); - return latestNonDraftDescriptor; + return latestValidDescriptor; } async function getDescriptorAttributes( attributeProcessClient: AttributeProcessClient, headers: ApiGatewayAppContext["headers"], - descriptor: NonDraftCatalogApiDescriptor + descriptor: validCatalogApiDescriptor ): Promise { const allDescriptorAttributesIds = removeDuplicates( [ @@ -227,14 +219,11 @@ export async function enhanceEservice( eservice: catalogApi.EService, logger: Logger ): Promise { - const latestNonDraftDescriptor = getLatestNonDraftDescriptor( - eservice, - logger - ); + const latestValidDescriptor = getLatestValidDescriptor(eservice, logger); const descriptorAttributes = await getDescriptorAttributes( attributeProcessClient, headers, - latestNonDraftDescriptor + latestValidDescriptor ); const producerOrganization = await getOrganization( @@ -249,10 +238,10 @@ export async function enhanceEservice( name: eservice.name, description: eservice.description, technology: eservice.technology, - version: latestNonDraftDescriptor.version, + version: latestValidDescriptor.version, attributes: descriptorAttributes, - state: latestNonDraftDescriptor.state, - serverUrls: latestNonDraftDescriptor.serverUrls, + state: latestValidDescriptor.state, + serverUrls: latestValidDescriptor.serverUrls, producer: producerOrganization, isSignalHubEnabled: eservice.isSignalHubEnabled, }; diff --git a/packages/api-gateway/src/services/validators.ts b/packages/api-gateway/src/services/validators.ts index f484336e66..4824015d7a 100644 --- a/packages/api-gateway/src/services/validators.ts +++ b/packages/api-gateway/src/services/validators.ts @@ -6,19 +6,24 @@ import { delegationApi, purposeApi, } from "pagopa-interop-api-clients"; -import { operationForbidden, TenantId } from "pagopa-interop-models"; import { Logger } from "pagopa-interop-commons"; +import { operationForbidden, TenantId } from "pagopa-interop-models"; +import { validCatalogApiDescriptor } from "../api/catalogApiConverter.js"; import { activeAgreementByEserviceAndConsumerNotFound, attributeNotFoundInRegistry, invalidAgreementState, missingActivePurposeVersion, missingAvailableDescriptor, + multipleActiveProducerDelegationsForEservice, multipleAgreementForEserviceAndConsumer, unexpectedDescriptorState, - multipleActiveProducerDelegationsForEservice, } from "../models/errors.js"; -import { NonDraftCatalogApiDescriptor } from "../api/catalogApiConverter.js"; + +export const invalidDescriptorStates: catalogApi.EServiceDescriptorState[] = [ + catalogApi.EServiceDescriptorState.Values.DRAFT, + catalogApi.EServiceDescriptorState.Values.WAITING_FOR_APPROVAL, +]; export function assertAgreementStateNotDraft( agreementState: agreementApi.AgreementState, @@ -71,17 +76,16 @@ export function assertAvailableDescriptorExists( } } -export function assertNonDraftDescriptor( +export function assertNonValidDescriptor( descriptor: catalogApi.EServiceDescriptor, - descriptorId: catalogApi.EServiceDescriptor["id"], eserviceId: catalogApi.EService["id"], logger: Logger -): asserts descriptor is NonDraftCatalogApiDescriptor { - if (descriptor.state === catalogApi.EServiceDescriptorState.Values.DRAFT) { +): asserts descriptor is validCatalogApiDescriptor { + if (invalidDescriptorStates.includes(descriptor.state)) { throw unexpectedDescriptorState( descriptor.state, eserviceId, - descriptorId, + descriptor.id, logger ); } From cfb11208c9b84bb9c7d69af8c43b5ce9c33891b4 Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Thu, 19 Dec 2024 11:34:01 +0100 Subject: [PATCH 02/12] BFF catalog API return eservice data filtered by Descriptor not in state DRAFT or Waiting for approval --- .../src/api/catalogApiConverter.ts | 16 ++++++++-------- .../src/model/modelMappingUtils.ts | 9 +++++++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/backend-for-frontend/src/api/catalogApiConverter.ts b/packages/backend-for-frontend/src/api/catalogApiConverter.ts index d788ecadd8..2892b1e2f0 100644 --- a/packages/backend-for-frontend/src/api/catalogApiConverter.ts +++ b/packages/backend-for-frontend/src/api/catalogApiConverter.ts @@ -15,19 +15,19 @@ import { import { attributeNotExists } from "../model/errors.js"; import { getLatestActiveDescriptor, - getNotDraftDescriptor, getLatestTenantContactEmail, + getValidDescriptor, } from "../model/modelMappingUtils.js"; -import { - isRequesterEserviceProducer, - isAgreementSubscribed, - isAgreementUpgradable, - hasCertifiedAttributes, -} from "../services/validators.js"; import { ConfigurationRiskAnalysis, catalogApiDescriptorState, } from "../model/types.js"; +import { + hasCertifiedAttributes, + isAgreementSubscribed, + isAgreementUpgradable, + isRequesterEserviceProducer, +} from "../services/validators.js"; import { toBffCompactAgreement } from "./agreementApiConverter.js"; export function toEserviceCatalogProcessQueryParams( @@ -105,7 +105,7 @@ export function toBffCatalogDescriptorEService( }, description: eservice.description, technology: eservice.technology, - descriptors: getNotDraftDescriptor(eservice).map(toCompactDescriptor), + descriptors: getValidDescriptor(eservice).map(toCompactDescriptor), agreement: agreement && toBffCompactAgreement(agreement, eservice), isMine: isRequesterEserviceProducer(requesterTenant.id, eservice), hasCertifiedAttributes: hasCertifiedAttributes(descriptor, requesterTenant), diff --git a/packages/backend-for-frontend/src/model/modelMappingUtils.ts b/packages/backend-for-frontend/src/model/modelMappingUtils.ts index 3b11ecd874..4cf02b7c72 100644 --- a/packages/backend-for-frontend/src/model/modelMappingUtils.ts +++ b/packages/backend-for-frontend/src/model/modelMappingUtils.ts @@ -17,6 +17,11 @@ const activeDescriptorStatesFilter: catalogApi.EServiceDescriptorState[] = [ catalogApiDescriptorState.DEPRECATED, ]; +const invalidDescriptorState: catalogApi.EServiceDescriptorState[] = [ + catalogApiDescriptorState.DRAFT, + catalogApiDescriptorState.WAITING_FOR_APPROVAL, +]; + export function getLatestActiveDescriptor( eservice: catalogApi.EService ): catalogApi.EServiceDescriptor | undefined { @@ -26,11 +31,11 @@ export function getLatestActiveDescriptor( .at(-1); } -export function getNotDraftDescriptor( +export function getValidDescriptor( eservice: catalogApi.EService ): catalogApi.EServiceDescriptor[] { return eservice.descriptors.filter( - (d) => d.state !== catalogApiDescriptorState.DRAFT + (d) => !invalidDescriptorState.includes(d.state) ); } From 3764bcf727d3e17e73b78f50f9c366c8b5a95d16 Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Thu, 19 Dec 2024 12:12:34 +0100 Subject: [PATCH 03/12] BFF validators check validity of actionable Descriptor considering Waiting for approval state --- .../src/api/catalogApiConverter.ts | 15 +++++---------- .../src/services/validators.ts | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/packages/backend-for-frontend/src/api/catalogApiConverter.ts b/packages/backend-for-frontend/src/api/catalogApiConverter.ts index 2892b1e2f0..f4ef8a0910 100644 --- a/packages/backend-for-frontend/src/api/catalogApiConverter.ts +++ b/packages/backend-for-frontend/src/api/catalogApiConverter.ts @@ -18,15 +18,14 @@ import { getLatestTenantContactEmail, getValidDescriptor, } from "../model/modelMappingUtils.js"; -import { - ConfigurationRiskAnalysis, - catalogApiDescriptorState, -} from "../model/types.js"; +import { ConfigurationRiskAnalysis } from "../model/types.js"; import { hasCertifiedAttributes, isAgreementSubscribed, isAgreementUpgradable, + isInvalidDescriptor, isRequesterEserviceProducer, + isValidDescriptor, } from "../services/validators.js"; import { toBffCompactAgreement } from "./agreementApiConverter.js"; @@ -240,14 +239,10 @@ export function toBffCatalogApiProducerDescriptorEService( const producerMail = getLatestTenantContactEmail(producer); const notDraftDecriptors = eservice.descriptors - .filter((d) => d.state !== catalogApiDescriptorState.DRAFT) + .filter(isValidDescriptor) .map(toCompactDescriptor); - const draftDescriptor = eservice.descriptors.find( - (d) => - d.state === catalogApiDescriptorState.DRAFT || - d.state === catalogApiDescriptorState.WAITING_FOR_APPROVAL - ); + const draftDescriptor = eservice.descriptors.find(isInvalidDescriptor); return { id: eservice.id, diff --git a/packages/backend-for-frontend/src/services/validators.ts b/packages/backend-for-frontend/src/services/validators.ts index 8faa98b956..f37d91feb2 100644 --- a/packages/backend-for-frontend/src/services/validators.ts +++ b/packages/backend-for-frontend/src/services/validators.ts @@ -29,6 +29,23 @@ import { import { BffAppContext } from "../utilities/context.js"; import { getAllDelegations } from "./delegationService.js"; +export const invalidDescriptorStates: catalogApi.EServiceDescriptorState[] = [ + catalogApi.EServiceDescriptorState.Values.DRAFT, + catalogApi.EServiceDescriptorState.Values.WAITING_FOR_APPROVAL, +]; + +export function isValidDescriptor( + descriptor: catalogApi.EServiceDescriptor +): boolean { + return !invalidDescriptorStates.includes(descriptor.state); +} + +export function isInvalidDescriptor( + descriptor: catalogApi.EServiceDescriptor +): boolean { + return invalidDescriptorStates.includes(descriptor.state); +} + export function isRequesterEserviceProducer( requesterId: string, eservice: catalogApi.EService @@ -145,7 +162,7 @@ export function hasCertifiedAttributes( export function verifyExportEligibility( descriptor: catalogApi.EServiceDescriptor ): void { - if (descriptor.state === catalogApiDescriptorState.DRAFT) { + if (isValidDescriptor(descriptor)) { throw notValidDescriptor(descriptor.id, descriptor.state); } } From 714eaa2b3d9afa55543873c57949ebfd4ab4387d Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Thu, 19 Dec 2024 17:47:37 +0100 Subject: [PATCH 04/12] Refactor validator and logic for draft and waiting for approval descriptor states --- .../src/api/catalogApiConverter.ts | 2 + .../src/services/catalogService.ts | 12 ++---- .../src/services/catalogService.ts | 32 ++++++---------- .../src/services/validators.ts | 37 ++++++++++++++++--- 4 files changed, 49 insertions(+), 34 deletions(-) diff --git a/packages/backend-for-frontend/src/api/catalogApiConverter.ts b/packages/backend-for-frontend/src/api/catalogApiConverter.ts index f4ef8a0910..a6722b8970 100644 --- a/packages/backend-for-frontend/src/api/catalogApiConverter.ts +++ b/packages/backend-for-frontend/src/api/catalogApiConverter.ts @@ -373,6 +373,8 @@ export function toCompactProducerDescriptor( version: descriptor.version, requireCorrections: isRequesterProducerDelegate && + // The WAITING_FOR_APPROVAL state is not relevant for the producer descriptor's requireCorrections field, + // so we don't consider it when determining whether corrections are required. descriptor.state === catalogApi.EServiceDescriptorState.Values.DRAFT && descriptor.rejectionReasons && descriptor.rejectionReasons.length > 0, diff --git a/packages/backend-for-frontend/src/services/catalogService.ts b/packages/backend-for-frontend/src/services/catalogService.ts index 9bd1b1303b..00361b552e 100644 --- a/packages/backend-for-frontend/src/services/catalogService.ts +++ b/packages/backend-for-frontend/src/services/catalogService.ts @@ -52,16 +52,14 @@ import { toBffCatalogApiEserviceRiskAnalysisSeed, toCompactProducerDescriptor, } from "../api/catalogApiConverter.js"; -import { - catalogApiDescriptorState, - ConfigurationEservice, -} from "../model/types.js"; +import { ConfigurationEservice } from "../model/types.js"; import { getAllAgreements, getLatestAgreement } from "./agreementService.js"; import { getAllBulkAttributes } from "./attributeService.js"; import { assertNotDelegatedEservice, assertRequesterIsProducer, assertRequesterCanActAsProducer, + isInvalidDescriptor, } from "./validators.js"; export type CatalogService = ReturnType; @@ -117,11 +115,7 @@ const enhanceProducerEService = ( requesterId: TenantId ): bffApi.ProducerEService => { const activeDescriptor = getLatestActiveDescriptor(eservice); - const draftDescriptor = eservice.descriptors.find( - (d) => - d.state === catalogApiDescriptorState.DRAFT || - d.state === catalogApiDescriptorState.WAITING_FOR_APPROVAL - ); + const draftDescriptor = eservice.descriptors.find(isInvalidDescriptor); const isRequesterDelegateProducer = requesterId !== eservice.producerId; diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 288da4bad1..23c80d320f 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -114,6 +114,10 @@ import { assertRequesterIsProducer, assertRiskAnalysisIsValidForPublication, assertTenantKindExists, + descriptorStatesAllowingDocumentOperations, + isActiveDescriptor, + isNotActiveDescriptor, + isNotDescriptorUpdeatable, validateRiskAnalysisSchemaOrThrow, } from "./validators.js"; @@ -709,10 +713,7 @@ export function catalogServiceBuilder( const descriptor = retrieveDescriptor(descriptorId, eservice); if ( - descriptor.state !== descriptorState.draft && - descriptor.state !== descriptorState.deprecated && - descriptor.state !== descriptorState.published && - descriptor.state !== descriptorState.suspended + !descriptorStatesAllowingDocumentOperations.includes(descriptor.state) ) { throw notValidDescriptorState(descriptor.id, descriptor.state); } @@ -876,10 +877,7 @@ export function catalogServiceBuilder( const descriptor = retrieveDescriptor(descriptorId, eservice); if ( - descriptor.state !== descriptorState.draft && - descriptor.state !== descriptorState.deprecated && - descriptor.state !== descriptorState.published && - descriptor.state !== descriptorState.suspended + !descriptorStatesAllowingDocumentOperations.includes(descriptor.state) ) { throw notValidDescriptorState(descriptor.id, descriptor.state); } @@ -1081,6 +1079,7 @@ export function catalogServiceBuilder( const descriptor = retrieveDescriptor(descriptorId, eservice); + // Descriptor in state WaitingForApproval can be deleted if (descriptor.state !== descriptorState.draft) { throw notValidDescriptorState(descriptorId, descriptor.state); } @@ -1137,6 +1136,7 @@ export function catalogServiceBuilder( const descriptor = retrieveDescriptor(descriptorId, eservice); + // Descriptor in state WaitingForApproval can be updated if (descriptor.state !== descriptorState.draft) { throw notValidDescriptorState( descriptorId, @@ -1204,6 +1204,7 @@ export function catalogServiceBuilder( assertRequesterCanPublish(producerDelegation, eservice.data, authData); const descriptor = retrieveDescriptor(descriptorId, eservice); + // Descriptor in state WaitingForApproval can be published if (descriptor.state !== descriptorState.draft) { throw notValidDescriptorState( descriptor.id, @@ -1783,10 +1784,7 @@ export function catalogServiceBuilder( ); const hasValidDescriptor = eservice.data.descriptors.some( - (descriptor) => - descriptor.state !== descriptorState.draft && - descriptor.state !== descriptorState.waitingForApproval && - descriptor.state !== descriptorState.archived + isNotDescriptorUpdeatable ); if (!hasValidDescriptor) { throw eserviceWithoutValidDescriptors(eserviceId); @@ -2044,9 +2042,7 @@ async function applyVisibilityToEService( } const hasNoActiveDescriptor = eservice.descriptors.every( - (descriptor) => - descriptor.state === descriptorState.draft || - descriptor.state === delegationState.waitingForApproval + isNotActiveDescriptor ); if (!producerDelegation && hasNoActiveDescriptor) { @@ -2055,11 +2051,7 @@ async function applyVisibilityToEService( return { ...eservice, - descriptors: eservice.descriptors.filter( - (d) => - d.state !== descriptorState.draft && - d.state !== descriptorState.waitingForApproval - ), + descriptors: eservice.descriptors.filter(isActiveDescriptor), }; } diff --git a/packages/catalog-process/src/services/validators.ts b/packages/catalog-process/src/services/validators.ts index 7beef7f529..ae27961a6b 100644 --- a/packages/catalog-process/src/services/validators.ts +++ b/packages/catalog-process/src/services/validators.ts @@ -7,6 +7,7 @@ import { } from "pagopa-interop-commons"; import { Descriptor, + DescriptorState, EService, EServiceId, Tenant, @@ -32,6 +33,36 @@ import { } from "../model/domain/errors.js"; import { ReadModelService } from "./readModelService.js"; +export const descriptorStatesAllowingDocumentOperations: DescriptorState[] = [ + descriptorState.draft, + descriptorState.deprecated, + descriptorState.published, + descriptorState.suspended, +]; + +export const updatableDescriptorStates: DescriptorState[] = [ + descriptorState.deprecated, + descriptorState.published, + descriptorState.suspended, +]; + +export const notActiveDescriptorState: DescriptorState[] = [ + descriptorState.draft, + delegationState.waitingForApproval, +]; + +export function isNotActiveDescriptor(descriptor: Descriptor): boolean { + return notActiveDescriptorState.includes(descriptor.state); +} + +export function isActiveDescriptor(descriptor: Descriptor): boolean { + return !notActiveDescriptorState.includes(descriptor.state); +} + +export function isNotDescriptorUpdeatable(descriptor: Descriptor): boolean { + return !updatableDescriptorStates.includes(descriptor.state); +} + export async function assertRequesterIsDelegateProducerOrProducer( producerId: TenantId, eserviceId: EServiceId, @@ -116,11 +147,7 @@ export function assertTenantKindExists( export function assertHasNoDraftOrWaitingForApprovalDescriptor( eservice: EService ): void { - const hasInvalidDescriptor = eservice.descriptors.some( - (d: Descriptor) => - d.state === descriptorState.draft || - d.state === descriptorState.waitingForApproval - ); + const hasInvalidDescriptor = eservice.descriptors.some(isNotActiveDescriptor); if (hasInvalidDescriptor) { throw draftDescriptorAlreadyExists(eservice.id); } From d5e0b61f4cda78fcb4dd6cb86f9a00b98ebe48cf Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Thu, 19 Dec 2024 22:37:37 +0100 Subject: [PATCH 05/12] Clarify valid and invalid descriptors definitions usages --- packages/api-gateway/src/services/catalogService.ts | 4 ++-- packages/api-gateway/src/services/validators.ts | 7 +++++++ packages/backend-for-frontend/src/services/validators.ts | 9 ++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/api-gateway/src/services/catalogService.ts b/packages/api-gateway/src/services/catalogService.ts index f0039379d2..d69bcfae9d 100644 --- a/packages/api-gateway/src/services/catalogService.ts +++ b/packages/api-gateway/src/services/catalogService.ts @@ -27,7 +27,7 @@ import { getOrganization } from "./tenantService.js"; import { assertAvailableDescriptorExists, assertNonValidDescriptor, - invalidDescriptorStates, + validDescriptorStates, } from "./validators.js"; export function getAllEservices( @@ -157,7 +157,7 @@ export function catalogServiceBuilder( } const isValidDescriptorState = (d: catalogApi.EServiceDescriptor): boolean => - !invalidDescriptorStates.includes(d.state); + validDescriptorStates.includes(d.state); function retrieveEserviceDescriptor( eservice: catalogApi.EService, diff --git a/packages/api-gateway/src/services/validators.ts b/packages/api-gateway/src/services/validators.ts index 4824015d7a..4da095805c 100644 --- a/packages/api-gateway/src/services/validators.ts +++ b/packages/api-gateway/src/services/validators.ts @@ -25,6 +25,13 @@ export const invalidDescriptorStates: catalogApi.EServiceDescriptorState[] = [ catalogApi.EServiceDescriptorState.Values.WAITING_FOR_APPROVAL, ]; +export const validDescriptorStates: catalogApi.EServiceDescriptorState[] = [ + catalogApi.EServiceDescriptorState.Values.ARCHIVED, + catalogApi.EServiceDescriptorState.Values.DEPRECATED, + catalogApi.EServiceDescriptorState.Values.PUBLISHED, + catalogApi.EServiceDescriptorState.Values.SUSPENDED, +]; + export function assertAgreementStateNotDraft( agreementState: agreementApi.AgreementState, agreementId: agreementApi.Agreement["id"], diff --git a/packages/backend-for-frontend/src/services/validators.ts b/packages/backend-for-frontend/src/services/validators.ts index f37d91feb2..ba07e4b768 100644 --- a/packages/backend-for-frontend/src/services/validators.ts +++ b/packages/backend-for-frontend/src/services/validators.ts @@ -34,10 +34,17 @@ export const invalidDescriptorStates: catalogApi.EServiceDescriptorState[] = [ catalogApi.EServiceDescriptorState.Values.WAITING_FOR_APPROVAL, ]; +export const validDescriptorStates: catalogApi.EServiceDescriptorState[] = [ + catalogApi.EServiceDescriptorState.Values.PUBLISHED, + catalogApi.EServiceDescriptorState.Values.DEPRECATED, + catalogApi.EServiceDescriptorState.Values.SUSPENDED, + catalogApi.EServiceDescriptorState.Values.ARCHIVED, +]; + export function isValidDescriptor( descriptor: catalogApi.EServiceDescriptor ): boolean { - return !invalidDescriptorStates.includes(descriptor.state); + return validDescriptorStates.includes(descriptor.state); } export function isInvalidDescriptor( From 3e91fb71463cfc236b2333ad8b8ea572c3a8eaf7 Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Thu, 19 Dec 2024 22:43:50 +0100 Subject: [PATCH 06/12] Fix typo --- packages/api-gateway/src/api/catalogApiConverter.ts | 4 ++-- packages/api-gateway/src/services/catalogService.ts | 4 ++-- packages/api-gateway/src/services/validators.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/api-gateway/src/api/catalogApiConverter.ts b/packages/api-gateway/src/api/catalogApiConverter.ts index ddfc6e3beb..c178836a0c 100644 --- a/packages/api-gateway/src/api/catalogApiConverter.ts +++ b/packages/api-gateway/src/api/catalogApiConverter.ts @@ -5,7 +5,7 @@ import { } from "pagopa-interop-api-clients"; import { Logger } from "pagopa-interop-commons"; import { - assertNonValidDescriptor, + assertNotValidDescriptor, assertRegistryAttributeExists, } from "../services/validators.js"; @@ -102,7 +102,7 @@ export function toApiGatewayDescriptorIfIsValid( eserviceId: catalogApi.EService["id"], logger: Logger ): apiGatewayApi.EServiceDescriptor { - assertNonValidDescriptor(descriptor, eserviceId, logger); + assertNotValidDescriptor(descriptor, eserviceId, logger); return { id: descriptor.id, diff --git a/packages/api-gateway/src/services/catalogService.ts b/packages/api-gateway/src/services/catalogService.ts index d69bcfae9d..4049855e2c 100644 --- a/packages/api-gateway/src/services/catalogService.ts +++ b/packages/api-gateway/src/services/catalogService.ts @@ -26,7 +26,7 @@ import { getAllBulkAttributes } from "./attributeService.js"; import { getOrganization } from "./tenantService.js"; import { assertAvailableDescriptorExists, - assertNonValidDescriptor, + assertNotValidDescriptor, validDescriptorStates, } from "./validators.js"; @@ -182,7 +182,7 @@ function getLatestValidDescriptor( .at(-1); assertAvailableDescriptorExists(latestValidDescriptor, eservice.id, logger); - assertNonValidDescriptor(latestValidDescriptor, eservice.id, logger); + assertNotValidDescriptor(latestValidDescriptor, eservice.id, logger); return latestValidDescriptor; } diff --git a/packages/api-gateway/src/services/validators.ts b/packages/api-gateway/src/services/validators.ts index 4da095805c..b6a368af39 100644 --- a/packages/api-gateway/src/services/validators.ts +++ b/packages/api-gateway/src/services/validators.ts @@ -83,7 +83,7 @@ export function assertAvailableDescriptorExists( } } -export function assertNonValidDescriptor( +export function assertNotValidDescriptor( descriptor: catalogApi.EServiceDescriptor, eserviceId: catalogApi.EService["id"], logger: Logger From 9c4aec138d3a88a71e6677f3b32e60d29645fbc2 Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Fri, 20 Dec 2024 11:27:51 +0100 Subject: [PATCH 07/12] Fix and test add more test use case coverage --- .../catalog-process/src/services/catalogService.ts | 14 +++++++------- .../catalog-process/src/services/validators.ts | 4 ++-- .../test/updateEserviceDescription.test.ts | 8 ++++++-- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 23c80d320f..71a5331428 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -54,6 +54,7 @@ import { import { attributeNotFound, audienceCannotBeEmpty, + descriptorAttributeGroupSupersetMissingInAttributesSeed, eServiceDescriptorNotFound, eServiceDescriptorWithoutInterface, eServiceDocumentNotFound, @@ -61,6 +62,7 @@ import { eServiceNotFound, eServiceRiskAnalysisNotFound, eserviceWithoutValidDescriptors, + inconsistentAttributesSeedGroupsCount, inconsistentDailyCalls, interfaceAlreadyExists, notValidDescriptorState, @@ -69,8 +71,6 @@ import { riskAnalysisDuplicated, tenantNotFound, unchangedAttributes, - inconsistentAttributesSeedGroupsCount, - descriptorAttributeGroupSupersetMissingInAttributesSeed, } from "../model/domain/errors.js"; import { ApiGetEServicesFilters, Consumer } from "../model/domain/models.js"; import { @@ -80,13 +80,13 @@ import { toCreateEventEServiceDescriptionUpdated, toCreateEventEServiceDescriptorActivated, toCreateEventEServiceDescriptorAdded, - toCreateEventEServiceDescriptorArchived, - toCreateEventEServiceDescriptorSubmittedByDelegate, toCreateEventEServiceDescriptorApprovedByDelegator, - toCreateEventEServiceDescriptorRejectedByDelegator, + toCreateEventEServiceDescriptorArchived, toCreateEventEServiceDescriptorAttributesUpdated, toCreateEventEServiceDescriptorPublished, toCreateEventEServiceDescriptorQuotasUpdated, + toCreateEventEServiceDescriptorRejectedByDelegator, + toCreateEventEServiceDescriptorSubmittedByDelegate, toCreateEventEServiceDescriptorSuspended, toCreateEventEServiceDocumentAdded, toCreateEventEServiceDocumentDeleted, @@ -116,8 +116,8 @@ import { assertTenantKindExists, descriptorStatesAllowingDocumentOperations, isActiveDescriptor, + isDescriptorUpdeatable, isNotActiveDescriptor, - isNotDescriptorUpdeatable, validateRiskAnalysisSchemaOrThrow, } from "./validators.js"; @@ -1784,7 +1784,7 @@ export function catalogServiceBuilder( ); const hasValidDescriptor = eservice.data.descriptors.some( - isNotDescriptorUpdeatable + isDescriptorUpdeatable ); if (!hasValidDescriptor) { throw eserviceWithoutValidDescriptors(eserviceId); diff --git a/packages/catalog-process/src/services/validators.ts b/packages/catalog-process/src/services/validators.ts index ae27961a6b..27b43b9f68 100644 --- a/packages/catalog-process/src/services/validators.ts +++ b/packages/catalog-process/src/services/validators.ts @@ -59,8 +59,8 @@ export function isActiveDescriptor(descriptor: Descriptor): boolean { return !notActiveDescriptorState.includes(descriptor.state); } -export function isNotDescriptorUpdeatable(descriptor: Descriptor): boolean { - return !updatableDescriptorStates.includes(descriptor.state); +export function isDescriptorUpdeatable(descriptor: Descriptor): boolean { + return updatableDescriptorStates.includes(descriptor.state); } export async function assertRequesterIsDelegateProducerOrProducer( diff --git a/packages/catalog-process/test/updateEserviceDescription.test.ts b/packages/catalog-process/test/updateEserviceDescription.test.ts index 99906570e9..6a6236b757 100644 --- a/packages/catalog-process/test/updateEserviceDescription.test.ts +++ b/packages/catalog-process/test/updateEserviceDescription.test.ts @@ -183,7 +183,7 @@ describe("update eService description", () => { ) ).rejects.toThrowError(operationForbidden); }); - it("shoudl throw eserviceWithoutValidDescriptors if the eservice doesn't have any descriptors", async () => { + it("should throw eserviceWithoutValidDescriptors if the eservice doesn't have any descriptors", async () => { const eservice = getMockEService(); await addOneEService(eservice); @@ -200,7 +200,11 @@ describe("update eService description", () => { ) ).rejects.toThrowError(eserviceWithoutValidDescriptors(eservice.id)); }); - it.each([descriptorState.draft, descriptorState.archived])( + it.each([ + descriptorState.draft, + descriptorState.archived, + descriptorState.waitingForApproval, + ])( "should throw eserviceWithoutValidDescriptors if the eservice doesn't have valid descriptors (Descriptor with state %s)", async (state) => { const descriptor: Descriptor = { From 1dbd20fa6e4a9647f6aced02b70417b90b430a9b Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Tue, 21 Jan 2025 10:29:26 +0100 Subject: [PATCH 08/12] Minor Fix and refactorizze function naming --- .../src/api/catalogApiConverter.ts | 6 ++-- .../src/services/catalogService.ts | 10 +++--- .../api-gateway/src/services/validators.ts | 36 +++++++++++++------ 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/packages/api-gateway/src/api/catalogApiConverter.ts b/packages/api-gateway/src/api/catalogApiConverter.ts index c178836a0c..0cb6dcb6c0 100644 --- a/packages/api-gateway/src/api/catalogApiConverter.ts +++ b/packages/api-gateway/src/api/catalogApiConverter.ts @@ -5,11 +5,11 @@ import { } from "pagopa-interop-api-clients"; import { Logger } from "pagopa-interop-commons"; import { - assertNotValidDescriptor, + assertIsValidDescriptor, assertRegistryAttributeExists, } from "../services/validators.js"; -export type validCatalogApiDescriptor = catalogApi.EServiceDescriptor & { +export type ValidCatalogApiDescriptor = catalogApi.EServiceDescriptor & { state: Exclude< catalogApi.EServiceDescriptorState, "DRAFT" | "WAITING_FOR_APPROVAL" @@ -102,7 +102,7 @@ export function toApiGatewayDescriptorIfIsValid( eserviceId: catalogApi.EService["id"], logger: Logger ): apiGatewayApi.EServiceDescriptor { - assertNotValidDescriptor(descriptor, eserviceId, logger); + assertIsValidDescriptor(descriptor, eserviceId, logger); return { id: descriptor.id, diff --git a/packages/api-gateway/src/services/catalogService.ts b/packages/api-gateway/src/services/catalogService.ts index 4049855e2c..63edab1930 100644 --- a/packages/api-gateway/src/services/catalogService.ts +++ b/packages/api-gateway/src/services/catalogService.ts @@ -9,7 +9,7 @@ import { toApiGatewayCatalogEservice, toApiGatewayDescriptorIfIsValid, toApiGatewayEserviceAttributes, - validCatalogApiDescriptor, + ValidCatalogApiDescriptor, } from "../api/catalogApiConverter.js"; import { clientStatusCodeToError } from "../clients/catchClientError.js"; import { @@ -26,7 +26,7 @@ import { getAllBulkAttributes } from "./attributeService.js"; import { getOrganization } from "./tenantService.js"; import { assertAvailableDescriptorExists, - assertNotValidDescriptor, + assertIsValidDescriptor, validDescriptorStates, } from "./validators.js"; @@ -175,14 +175,14 @@ function retrieveEserviceDescriptor( function getLatestValidDescriptor( eservice: catalogApi.EService, logger: Logger -): validCatalogApiDescriptor { +): ValidCatalogApiDescriptor { const latestValidDescriptor = eservice.descriptors .filter(isValidDescriptorState) .sort((a, b) => Number(a.version) - Number(b.version)) .at(-1); assertAvailableDescriptorExists(latestValidDescriptor, eservice.id, logger); - assertNotValidDescriptor(latestValidDescriptor, eservice.id, logger); + assertIsValidDescriptor(latestValidDescriptor, eservice.id, logger); return latestValidDescriptor; } @@ -190,7 +190,7 @@ function getLatestValidDescriptor( async function getDescriptorAttributes( attributeProcessClient: AttributeProcessClient, headers: ApiGatewayAppContext["headers"], - descriptor: validCatalogApiDescriptor + descriptor: ValidCatalogApiDescriptor ): Promise { const allDescriptorAttributesIds = removeDuplicates( [ diff --git a/packages/api-gateway/src/services/validators.ts b/packages/api-gateway/src/services/validators.ts index b6a368af39..9e2bb7eaab 100644 --- a/packages/api-gateway/src/services/validators.ts +++ b/packages/api-gateway/src/services/validators.ts @@ -8,7 +8,8 @@ import { } from "pagopa-interop-api-clients"; import { Logger } from "pagopa-interop-commons"; import { operationForbidden, TenantId } from "pagopa-interop-models"; -import { validCatalogApiDescriptor } from "../api/catalogApiConverter.js"; +import { match } from "ts-pattern"; +import { ValidCatalogApiDescriptor } from "../api/catalogApiConverter.js"; import { activeAgreementByEserviceAndConsumerNotFound, attributeNotFoundInRegistry, @@ -83,19 +84,32 @@ export function assertAvailableDescriptorExists( } } -export function assertNotValidDescriptor( +export function assertIsValidDescriptor( descriptor: catalogApi.EServiceDescriptor, eserviceId: catalogApi.EService["id"], logger: Logger -): asserts descriptor is validCatalogApiDescriptor { - if (invalidDescriptorStates.includes(descriptor.state)) { - throw unexpectedDescriptorState( - descriptor.state, - eserviceId, - descriptor.id, - logger - ); - } +): asserts descriptor is ValidCatalogApiDescriptor { + match(descriptor.state) + .with( + catalogApi.EServiceDescriptorState.Values.DRAFT, + catalogApi.EServiceDescriptorState.Values.WAITING_FOR_APPROVAL, + () => { + throw unexpectedDescriptorState( + descriptor.state, + eserviceId, + descriptor.id, + logger + ); + } + ) + .with( + catalogApi.EServiceDescriptorState.Values.PUBLISHED, + catalogApi.EServiceDescriptorState.Values.DEPRECATED, + catalogApi.EServiceDescriptorState.Values.SUSPENDED, + catalogApi.EServiceDescriptorState.Values.ARCHIVED, + () => descriptor + ) + .exhaustive(); } export function assertRegistryAttributeExists( From 9deccfc24c4e85e5dc4c188ac83423e2ebc70068 Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Tue, 21 Jan 2025 14:35:39 +0100 Subject: [PATCH 09/12] Fix using properly state enum for not active descriptor state --- packages/catalog-process/src/services/validators.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/catalog-process/src/services/validators.ts b/packages/catalog-process/src/services/validators.ts index 27b43b9f68..d5bcba3792 100644 --- a/packages/catalog-process/src/services/validators.ts +++ b/packages/catalog-process/src/services/validators.ts @@ -48,7 +48,7 @@ export const updatableDescriptorStates: DescriptorState[] = [ export const notActiveDescriptorState: DescriptorState[] = [ descriptorState.draft, - delegationState.waitingForApproval, + descriptorState.waitingForApproval, ]; export function isNotActiveDescriptor(descriptor: Descriptor): boolean { From f33f693d6b0544d5e61092bb9ecc37a680f545a2 Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Tue, 21 Jan 2025 14:36:05 +0100 Subject: [PATCH 10/12] Add pattern matching instead using Array.includes --- .../src/services/catalogService.ts | 17 ++++++++-- .../api-gateway/src/services/validators.ts | 12 ------- .../src/services/validators.ts | 31 +++++++++++++++++-- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/packages/api-gateway/src/services/catalogService.ts b/packages/api-gateway/src/services/catalogService.ts index 63edab1930..f1c0521f6c 100644 --- a/packages/api-gateway/src/services/catalogService.ts +++ b/packages/api-gateway/src/services/catalogService.ts @@ -5,6 +5,7 @@ import { removeDuplicates, WithLogger, } from "pagopa-interop-commons"; +import { match } from "ts-pattern"; import { toApiGatewayCatalogEservice, toApiGatewayDescriptorIfIsValid, @@ -27,7 +28,6 @@ import { getOrganization } from "./tenantService.js"; import { assertAvailableDescriptorExists, assertIsValidDescriptor, - validDescriptorStates, } from "./validators.js"; export function getAllEservices( @@ -157,7 +157,20 @@ export function catalogServiceBuilder( } const isValidDescriptorState = (d: catalogApi.EServiceDescriptor): boolean => - validDescriptorStates.includes(d.state); + match(d.state) + .with( + catalogApi.EServiceDescriptorState.Values.ARCHIVED, + catalogApi.EServiceDescriptorState.Values.DEPRECATED, + catalogApi.EServiceDescriptorState.Values.PUBLISHED, + catalogApi.EServiceDescriptorState.Values.SUSPENDED, + () => true + ) + .with( + catalogApi.EServiceDescriptorState.Values.DRAFT, + catalogApi.EServiceDescriptorState.Values.WAITING_FOR_APPROVAL, + () => false + ) + .exhaustive(); function retrieveEserviceDescriptor( eservice: catalogApi.EService, diff --git a/packages/api-gateway/src/services/validators.ts b/packages/api-gateway/src/services/validators.ts index 9e2bb7eaab..8455ac306e 100644 --- a/packages/api-gateway/src/services/validators.ts +++ b/packages/api-gateway/src/services/validators.ts @@ -21,18 +21,6 @@ import { unexpectedDescriptorState, } from "../models/errors.js"; -export const invalidDescriptorStates: catalogApi.EServiceDescriptorState[] = [ - catalogApi.EServiceDescriptorState.Values.DRAFT, - catalogApi.EServiceDescriptorState.Values.WAITING_FOR_APPROVAL, -]; - -export const validDescriptorStates: catalogApi.EServiceDescriptorState[] = [ - catalogApi.EServiceDescriptorState.Values.ARCHIVED, - catalogApi.EServiceDescriptorState.Values.DEPRECATED, - catalogApi.EServiceDescriptorState.Values.PUBLISHED, - catalogApi.EServiceDescriptorState.Values.SUSPENDED, -]; - export function assertAgreementStateNotDraft( agreementState: agreementApi.AgreementState, agreementId: agreementApi.Agreement["id"], diff --git a/packages/backend-for-frontend/src/services/validators.ts b/packages/backend-for-frontend/src/services/validators.ts index ba07e4b768..5bbfe42da9 100644 --- a/packages/backend-for-frontend/src/services/validators.ts +++ b/packages/backend-for-frontend/src/services/validators.ts @@ -10,6 +10,7 @@ import { EServiceId, TenantId, } from "pagopa-interop-models"; +import { match } from "ts-pattern"; import { descriptorAttributesFromApi } from "../api/catalogApiConverter.js"; import { toDelegationKind, @@ -44,13 +45,39 @@ export const validDescriptorStates: catalogApi.EServiceDescriptorState[] = [ export function isValidDescriptor( descriptor: catalogApi.EServiceDescriptor ): boolean { - return validDescriptorStates.includes(descriptor.state); + return match(descriptor.state) + .with( + catalogApi.EServiceDescriptorState.Values.ARCHIVED, + catalogApi.EServiceDescriptorState.Values.DEPRECATED, + catalogApi.EServiceDescriptorState.Values.PUBLISHED, + catalogApi.EServiceDescriptorState.Values.SUSPENDED, + () => true + ) + .with( + catalogApi.EServiceDescriptorState.Values.DRAFT, + catalogApi.EServiceDescriptorState.Values.WAITING_FOR_APPROVAL, + () => false + ) + .exhaustive(); } export function isInvalidDescriptor( descriptor: catalogApi.EServiceDescriptor ): boolean { - return invalidDescriptorStates.includes(descriptor.state); + return match(descriptor.state) + .with( + catalogApi.EServiceDescriptorState.Values.DRAFT, + catalogApi.EServiceDescriptorState.Values.WAITING_FOR_APPROVAL, + () => true + ) + .with( + catalogApi.EServiceDescriptorState.Values.ARCHIVED, + catalogApi.EServiceDescriptorState.Values.DEPRECATED, + catalogApi.EServiceDescriptorState.Values.PUBLISHED, + catalogApi.EServiceDescriptorState.Values.SUSPENDED, + () => false + ) + .exhaustive(); } export function isRequesterEserviceProducer( From dc33f4025ec6bbe2162fbcfa848d37d25e6c9e9b Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Tue, 21 Jan 2025 14:36:48 +0100 Subject: [PATCH 11/12] ReadModel service use static definition of notActiveDescriptorState --- .../catalog-process/src/services/readModelService.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/catalog-process/src/services/readModelService.ts b/packages/catalog-process/src/services/readModelService.ts index 87a2cd0100..50add7bbcd 100644 --- a/packages/catalog-process/src/services/readModelService.ts +++ b/packages/catalog-process/src/services/readModelService.ts @@ -41,6 +41,7 @@ import { Consumer, consumer, } from "../model/domain/models.js"; +import { notActiveDescriptorState } from "./validators.js"; async function getEService( eservices: EServiceCollection, @@ -255,10 +256,7 @@ export function readModelServiceBuilder( { "data.descriptors": { $size: 1 } }, { "data.descriptors.state": { - $in: [ - descriptorState.draft, - descriptorState.waitingForApproval, - ], + $in: notActiveDescriptorState, }, }, ], @@ -273,10 +271,7 @@ export function readModelServiceBuilder( { "data.descriptors": { $size: 1 } }, { "data.descriptors.state": { - $in: [ - descriptorState.draft, - descriptorState.waitingForApproval, - ], + $in: notActiveDescriptorState, }, }, ], From 30207cfa6a447a6ee39a93d11663ed2e5a279550 Mon Sep 17 00:00:00 2001 From: Vittorio Caprio Date: Tue, 21 Jan 2025 15:01:21 +0100 Subject: [PATCH 12/12] Refactor using match instead Array.includes and removed unused state array constants --- .../src/services/validators.ts | 35 +++++------ .../src/services/catalogService.ts | 14 ++--- .../src/services/validators.ts | 60 ++++++++++++++----- 3 files changed, 65 insertions(+), 44 deletions(-) diff --git a/packages/backend-for-frontend/src/services/validators.ts b/packages/backend-for-frontend/src/services/validators.ts index 5bbfe42da9..b97467f22a 100644 --- a/packages/backend-for-frontend/src/services/validators.ts +++ b/packages/backend-for-frontend/src/services/validators.ts @@ -30,18 +30,6 @@ import { import { BffAppContext } from "../utilities/context.js"; import { getAllDelegations } from "./delegationService.js"; -export const invalidDescriptorStates: catalogApi.EServiceDescriptorState[] = [ - catalogApi.EServiceDescriptorState.Values.DRAFT, - catalogApi.EServiceDescriptorState.Values.WAITING_FOR_APPROVAL, -]; - -export const validDescriptorStates: catalogApi.EServiceDescriptorState[] = [ - catalogApi.EServiceDescriptorState.Values.PUBLISHED, - catalogApi.EServiceDescriptorState.Values.DEPRECATED, - catalogApi.EServiceDescriptorState.Values.SUSPENDED, - catalogApi.EServiceDescriptorState.Values.ARCHIVED, -]; - export function isValidDescriptor( descriptor: catalogApi.EServiceDescriptor ): boolean { @@ -168,16 +156,25 @@ export function isAgreementUpgradable( ); } -const subscribedAgreementStates: agreementApi.AgreementState[] = [ - agreementApiState.PENDING, - agreementApiState.ACTIVE, - agreementApiState.SUSPENDED, -]; - export function isAgreementSubscribed( agreement: agreementApi.Agreement | undefined ): boolean { - return !!agreement && subscribedAgreementStates.includes(agreement.state); + return match(agreement?.state) + .with( + agreementApiState.PENDING, + agreementApiState.ACTIVE, + agreementApiState.SUSPENDED, + () => true + ) + .with( + agreementApiState.REJECTED, + agreementApiState.ARCHIVED, + agreementApiState.MISSING_CERTIFIED_ATTRIBUTES, + agreementApiState.DRAFT, + () => false + ) + .with(undefined, () => false) + .exhaustive(); } export function hasCertifiedAttributes( diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index 71a5331428..98226365c3 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -114,9 +114,9 @@ import { assertRequesterIsProducer, assertRiskAnalysisIsValidForPublication, assertTenantKindExists, - descriptorStatesAllowingDocumentOperations, + descriptorStatesNotAllowingDocumentOperations, isActiveDescriptor, - isDescriptorUpdeatable, + isDescriptorUpdatable, isNotActiveDescriptor, validateRiskAnalysisSchemaOrThrow, } from "./validators.js"; @@ -712,9 +712,7 @@ export function catalogServiceBuilder( const descriptor = retrieveDescriptor(descriptorId, eservice); - if ( - !descriptorStatesAllowingDocumentOperations.includes(descriptor.state) - ) { + if (descriptorStatesNotAllowingDocumentOperations(descriptor)) { throw notValidDescriptorState(descriptor.id, descriptor.state); } @@ -876,9 +874,7 @@ export function catalogServiceBuilder( const descriptor = retrieveDescriptor(descriptorId, eservice); - if ( - !descriptorStatesAllowingDocumentOperations.includes(descriptor.state) - ) { + if (descriptorStatesNotAllowingDocumentOperations(descriptor)) { throw notValidDescriptorState(descriptor.id, descriptor.state); } @@ -1784,7 +1780,7 @@ export function catalogServiceBuilder( ); const hasValidDescriptor = eservice.data.descriptors.some( - isDescriptorUpdeatable + isDescriptorUpdatable ); if (!hasValidDescriptor) { throw eserviceWithoutValidDescriptors(eserviceId); diff --git a/packages/catalog-process/src/services/validators.ts b/packages/catalog-process/src/services/validators.ts index d5bcba3792..ee70af2b3e 100644 --- a/packages/catalog-process/src/services/validators.ts +++ b/packages/catalog-process/src/services/validators.ts @@ -33,18 +33,24 @@ import { } from "../model/domain/errors.js"; import { ReadModelService } from "./readModelService.js"; -export const descriptorStatesAllowingDocumentOperations: DescriptorState[] = [ - descriptorState.draft, - descriptorState.deprecated, - descriptorState.published, - descriptorState.suspended, -]; - -export const updatableDescriptorStates: DescriptorState[] = [ - descriptorState.deprecated, - descriptorState.published, - descriptorState.suspended, -]; +export function descriptorStatesNotAllowingDocumentOperations( + descriptor: Descriptor +): boolean { + return match(descriptor.state) + .with( + descriptorState.draft, + descriptorState.deprecated, + descriptorState.published, + descriptorState.suspended, + () => false + ) + .with( + descriptorState.archived, + descriptorState.waitingForApproval, + () => true + ) + .exhaustive(); +} export const notActiveDescriptorState: DescriptorState[] = [ descriptorState.draft, @@ -52,15 +58,37 @@ export const notActiveDescriptorState: DescriptorState[] = [ ]; export function isNotActiveDescriptor(descriptor: Descriptor): boolean { - return notActiveDescriptorState.includes(descriptor.state); + return match(descriptor.state) + .with(descriptorState.draft, descriptorState.waitingForApproval, () => true) + .with( + descriptorState.archived, + descriptorState.deprecated, + descriptorState.published, + descriptorState.suspended, + () => false + ) + .exhaustive(); } export function isActiveDescriptor(descriptor: Descriptor): boolean { - return !notActiveDescriptorState.includes(descriptor.state); + return !isNotActiveDescriptor(descriptor); } -export function isDescriptorUpdeatable(descriptor: Descriptor): boolean { - return updatableDescriptorStates.includes(descriptor.state); +export function isDescriptorUpdatable(descriptor: Descriptor): boolean { + return match(descriptor.state) + .with( + descriptorState.deprecated, + descriptorState.published, + descriptorState.suspended, + () => true + ) + .with( + descriptorState.draft, + descriptorState.waitingForApproval, + descriptorState.archived, + () => false + ) + .exhaustive(); } export async function assertRequesterIsDelegateProducerOrProducer(