From 8d9ae4c3f8513f315a541b11cd24d37bd482532c Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Thu, 13 Feb 2025 14:51:30 +0100 Subject: [PATCH 01/11] Agreement visibility checks --- .../agreement/Compute Agreeements State.bru | 2 +- .../src/model/domain/agreement-validators.ts | 8 +++-- .../src/routers/AgreementRouter.ts | 11 ++++--- .../src/services/agreementService.ts | 30 +++++++++++++++---- .../api-clients/open-api/agreementApi.yml | 6 ++-- .../compute-agreements-consumer/src/index.ts | 2 +- 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/collections/agreement/Compute Agreeements State.bru b/collections/agreement/Compute Agreeements State.bru index 8538452048..7160f51850 100644 --- a/collections/agreement/Compute Agreeements State.bru +++ b/collections/agreement/Compute Agreeements State.bru @@ -5,7 +5,7 @@ meta { } post { - url: {{host-agreement}}/compute/agreementsState + url: {{host-agreement}}/internal/compute/agreementsState body: json auth: none } diff --git a/packages/agreement-process/src/model/domain/agreement-validators.ts b/packages/agreement-process/src/model/domain/agreement-validators.ts index d9b78f698b..b90b05e82c 100644 --- a/packages/agreement-process/src/model/domain/agreement-validators.ts +++ b/packages/agreement-process/src/model/domain/agreement-validators.ts @@ -181,13 +181,15 @@ export const assertRequesterCanActAsConsumerOrProducer = ( } }; -export const assertRequesterCanRetrieveConsumerDocuments = async ( +export const assertRequesterCanRetrieveAgreement = async ( agreement: Agreement, authData: AuthData, readModelService: ReadModelService ): Promise => { - // This operation has a dedicated assertion because it's the only operation that - // can be performed also by the producer/consumer even when active producer/consumer delegations exist + // This validator is for retrieval operations that can be performed by all the tenants involved: + // the consumer, the producer, the consumer delegate, and the producer delegate. + // Consumers and producers can retrieve agreements even if delegations exist. + try { assertRequesterIsConsumer(agreement.consumerId, authData); } catch { diff --git a/packages/agreement-process/src/routers/AgreementRouter.ts b/packages/agreement-process/src/routers/AgreementRouter.ts index 434ae303f7..7144f1fafb 100644 --- a/packages/agreement-process/src/routers/AgreementRouter.ts +++ b/packages/agreement-process/src/routers/AgreementRouter.ts @@ -378,7 +378,7 @@ const agreementRouter = ( }, req.query.limit, req.query.offset, - ctx.logger + ctx ); return res.status(200).send( @@ -480,7 +480,6 @@ const agreementRouter = ( API_ROLE, SECURITY_ROLE, M2M_ROLE, - INTERNAL_ROLE, SUPPORT_ROLE, ]), async (req, res) => { @@ -489,7 +488,7 @@ const agreementRouter = ( try { const agreement = await agreementService.getAgreementById( unsafeBrandId(req.params.agreementId), - ctx.logger + ctx ); return res .status(200) @@ -673,13 +672,13 @@ const agreementRouter = ( ); agreementRouter.post( - "/compute/agreementsState", - authorizationMiddleware([ADMIN_ROLE, INTERNAL_ROLE, M2M_ROLE]), + "/internal/compute/agreementsState", + authorizationMiddleware([INTERNAL_ROLE]), async (req, res) => { const ctx = fromAppContext(req.ctx); try { - await agreementService.computeAgreementsStateByAttribute( + await agreementService.internalComputeAgreementsStateByAttribute( unsafeBrandId(req.body.attributeId), fromApiCompactTenant(req.body.consumer), ctx diff --git a/packages/agreement-process/src/services/agreementService.ts b/packages/agreement-process/src/services/agreementService.ts index 929f0dc0c0..20285bb88e 100644 --- a/packages/agreement-process/src/services/agreementService.ts +++ b/packages/agreement-process/src/services/agreementService.ts @@ -90,7 +90,7 @@ import { assertActivableState, assertRequesterCanActAsProducer, assertRequesterCanActAsConsumerOrProducer, - assertRequesterCanRetrieveConsumerDocuments, + assertRequesterCanRetrieveAgreement, assertCanWorkOnConsumerDocuments, assertExpectedState, assertRequesterIsDelegateConsumer, @@ -232,18 +232,36 @@ export function agreementServiceBuilder( filters: AgreementQueryFilters, limit: number, offset: number, - logger: Logger + { authData, logger }: WithLogger ): Promise> { logger.info("Retrieving agreements"); - return await readModelService.getAgreements(filters, limit, offset); + const agreements = await readModelService.getAgreements( + filters, + limit, + offset + ); + agreements.results.forEach( + async (a) => + await assertRequesterCanRetrieveAgreement( + a, + authData, + readModelService + ) + ); + return agreements; }, async getAgreementById( agreementId: AgreementId, - logger: Logger + { authData, logger }: WithLogger ): Promise { logger.info(`Retrieving agreement by id ${agreementId}`); const agreement = await retrieveAgreement(agreementId, readModelService); + await assertRequesterCanRetrieveAgreement( + agreement.data, + authData, + readModelService + ); return agreement.data; }, async createAgreement( @@ -876,7 +894,7 @@ export function agreementServiceBuilder( const agreement = await retrieveAgreement(agreementId, readModelService); - await assertRequesterCanRetrieveConsumerDocuments( + await assertRequesterCanRetrieveAgreement( agreement.data, authData, readModelService @@ -1332,7 +1350,7 @@ export function agreementServiceBuilder( ) ); }, - async computeAgreementsStateByAttribute( + async internalComputeAgreementsStateByAttribute( attributeId: AttributeId, consumer: CompactTenant, { logger, correlationId }: WithLogger diff --git a/packages/api-clients/open-api/agreementApi.yml b/packages/api-clients/open-api/agreementApi.yml index c91950fda6..5f6b30626c 100644 --- a/packages/api-clients/open-api/agreementApi.yml +++ b/packages/api-clients/open-api/agreementApi.yml @@ -794,7 +794,7 @@ paths: application/json: schema: $ref: "#/components/schemas/Problem" - "/compute/agreementsState": + "/internal/compute/agreementsState": parameters: - $ref: "#/components/parameters/CorrelationIdHeader" post: @@ -802,7 +802,7 @@ paths: - agreement summary: Re-calculate agreements state description: Re-calculate state for all agreements that contain the given attribute - operationId: computeAgreementsByAttribute + operationId: internalComputeAgreementsByAttribute requestBody: content: application/json: @@ -914,7 +914,7 @@ paths: schema: type: string format: uuid - - name: descriptorId + - name: descriptorId in: path description: The identifier of the e-service descriptor required: true diff --git a/packages/compute-agreements-consumer/src/index.ts b/packages/compute-agreements-consumer/src/index.ts index 1260295e8e..f7220dd7d4 100644 --- a/packages/compute-agreements-consumer/src/index.ts +++ b/packages/compute-agreements-consumer/src/index.ts @@ -65,7 +65,7 @@ async function processMessage({ ); const token = (await refreshableToken.get()).serialized; - await agreementProcessClient.computeAgreementsByAttribute( + await agreementProcessClient.internalComputeAgreementsByAttribute( { attributeId: unsafeBrandId(attributeId), consumer: toApiCompactTenant(fromTenantV2(tenant)), From 2a9353774669f383fc484713f8cb08900c62f212 Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Thu, 13 Feb 2025 14:56:57 +0100 Subject: [PATCH 02/11] Adding comments --- .../agreement-process/src/services/agreementService.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/agreement-process/src/services/agreementService.ts b/packages/agreement-process/src/services/agreementService.ts index 20285bb88e..dbbbe1bff0 100644 --- a/packages/agreement-process/src/services/agreementService.ts +++ b/packages/agreement-process/src/services/agreementService.ts @@ -333,6 +333,9 @@ export function agreementServiceBuilder( logger.info( `Retrieving producers from agreements with producer name ${producerName}` ); + // No need to assert requester permissions here, as this endpoint + // retrieves producer information from agreements without exposing any + // agreement data. return await readModelService.getProducers(producerName, limit, offset); }, async getAgreementConsumers( @@ -344,6 +347,9 @@ export function agreementServiceBuilder( logger.info( `Retrieving consumers from agreements with consumer name ${consumerName}` ); + // No need to assert requester permissions here, as this endpoint + // retrieves consumer information from agreements without exposing any + // agreement data. return await readModelService.getConsumers(consumerName, limit, offset); }, async updateAgreement( @@ -970,7 +976,9 @@ export function agreementServiceBuilder( logger.info( `Retrieving EServices with consumers ${filters.consumerIds}, producers ${filters.producerIds}, states ${filters.agreeementStates}, offset ${offset}, limit ${limit} and name matching ${filters.eserviceName}` ); - + // No need to assert requester permissions here, as this endpoint + // retrieves e-service information from agreements without exposing any + // agreement data. return await readModelService.getAgreementsEServices( filters, limit, From 0e396cdb738553f2fa1dd9375356e8b9005a7d90 Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Thu, 13 Feb 2025 14:58:51 +0100 Subject: [PATCH 03/11] Fixing tests --- .../test/computeAgreementsState.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/agreement-process/test/computeAgreementsState.test.ts b/packages/agreement-process/test/computeAgreementsState.test.ts index 04eb1f170d..47d82505e1 100644 --- a/packages/agreement-process/test/computeAgreementsState.test.ts +++ b/packages/agreement-process/test/computeAgreementsState.test.ts @@ -90,7 +90,7 @@ describe("compute Agreements state by attribute", () => { await addOneAgreement(updatableActiveAgreement); - await agreementService.computeAgreementsStateByAttribute( + await agreementService.internalComputeAgreementsStateByAttribute( invalidCertifiedAttribute.id, consumer, { @@ -140,7 +140,7 @@ describe("compute Agreements state by attribute", () => { await addOneAgreement(updatableDraftOrPendingAgreement); - await agreementService.computeAgreementsStateByAttribute( + await agreementService.internalComputeAgreementsStateByAttribute( invalidCertifiedAttribute.id, consumer, { @@ -195,7 +195,7 @@ describe("compute Agreements state by attribute", () => { await addOneAgreement(updatableSuspendedAgreement); - await agreementService.computeAgreementsStateByAttribute( + await agreementService.internalComputeAgreementsStateByAttribute( invalidCertifiedAttribute.id, consumer, { @@ -302,7 +302,7 @@ describe("compute Agreements state by attribute", () => { await addOneAgreement(updatableSuspendedAgreement); - await agreementService.computeAgreementsStateByAttribute( + await agreementService.internalComputeAgreementsStateByAttribute( randomArrayItem([ tenantCertifiedAttribute.id, tenantDeclaredAttribute.id, @@ -358,7 +358,7 @@ describe("compute Agreements state by attribute", () => { await addOneAgreement(updatableMissingCertAttributesAgreement); - await agreementService.computeAgreementsStateByAttribute( + await agreementService.internalComputeAgreementsStateByAttribute( randomArrayItem([ tenantCertifiedAttribute.id, tenantDeclaredAttribute.id, @@ -416,7 +416,7 @@ describe("compute Agreements state by attribute", () => { await addOneAgreement(updatableSuspendedAgreement); - await agreementService.computeAgreementsStateByAttribute( + await agreementService.internalComputeAgreementsStateByAttribute( randomArrayItem([ tenantCertifiedAttribute.id, tenantDeclaredAttribute.id, @@ -539,7 +539,7 @@ describe("compute Agreements state by attribute", () => { await addOneAgreement(updatableAgreement2); await addOneAgreement(nonUpdatableAgreement); - await agreementService.computeAgreementsStateByAttribute( + await agreementService.internalComputeAgreementsStateByAttribute( invalidCertifiedAttribute.id, consumer, { From 7869833aba4204865236868e2df57d423b755428 Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Mon, 17 Feb 2025 11:47:48 +0100 Subject: [PATCH 04/11] Fixing getAgreement test --- .../test/getAgreement.test.ts | 137 ++++++++++++++++-- 1 file changed, 126 insertions(+), 11 deletions(-) diff --git a/packages/agreement-process/test/getAgreement.test.ts b/packages/agreement-process/test/getAgreement.test.ts index 63c8dd5cf0..d3b5fa3a8c 100644 --- a/packages/agreement-process/test/getAgreement.test.ts +++ b/packages/agreement-process/test/getAgreement.test.ts @@ -1,21 +1,131 @@ import { genericLogger } from "pagopa-interop-commons"; -import { getMockAgreement } from "pagopa-interop-commons-test/index.js"; -import { Agreement, generateId, AgreementId } from "pagopa-interop-models"; +import { + addSomeRandomDelegations, + getMockAgreement, + getMockDelegation, + getMockDescriptorPublished, + getMockEService, + getMockTenant, + getRandomAuthData, +} from "pagopa-interop-commons-test/index.js"; +import { + generateId, + delegationKind, + delegationState, + AgreementId, +} from "pagopa-interop-models"; import { describe, it, expect } from "vitest"; -import { agreementNotFound } from "../src/model/domain/errors.js"; -import { addOneAgreement, agreementService } from "./utils.js"; +import { + agreementNotFound, + organizationNotAllowed, +} from "../src/model/domain/errors.js"; +import { + addOneAgreement, + addOneDelegation, + addOneEService, + addOneTenant, + agreementService, +} from "./utils.js"; describe("get agreement", () => { - it("should get an agreement", async () => { - const agreement: Agreement = getMockAgreement(); + it(`should succeed when the requester is the consumer, + producer, consumer delegate, or producer delegate`, async () => { + const producer = getMockTenant(); + const consumer = getMockTenant(); + const producerDelegate = getMockTenant(); + const consumerDelegate = getMockTenant(); + const eservice = { + ...getMockEService(), + producerId: producer.id, + consumerId: consumer.id, + descriptors: [getMockDescriptorPublished()], + }; + const agreement = { + ...getMockAgreement(eservice.id), + descriptorId: eservice.descriptors[0].id, + producerId: producer.id, + consumerId: consumer.id, + }; + const producerDelegation = getMockDelegation({ + kind: delegationKind.delegatedProducer, + eserviceId: eservice.id, + delegatorId: eservice.producerId, + state: delegationState.active, + delegateId: producerDelegate.id, + }); + + const consumerDelegation = getMockDelegation({ + kind: delegationKind.delegatedConsumer, + eserviceId: agreement.eserviceId, + delegatorId: agreement.consumerId, + state: delegationState.active, + delegateId: consumerDelegate.id, + }); + + await addOneTenant(producerDelegate); + await addOneTenant(consumerDelegate); + await addOneEService(eservice); await addOneAgreement(agreement); - await addOneAgreement(getMockAgreement()); + await addOneDelegation(producerDelegation); + await addOneDelegation(consumerDelegation); + await addSomeRandomDelegations(agreement, addOneDelegation); - const result = await agreementService.getAgreementById( + const retrievedDocumentByConsumer = await agreementService.getAgreementById( agreement.id, - genericLogger + { + authData: getRandomAuthData(consumer.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } ); - expect(result).toEqual(agreement); + expect(retrievedDocumentByConsumer).toEqual(agreement); + + const retrievedDocumentByProducer = await agreementService.getAgreementById( + agreement.id, + { + authData: getRandomAuthData(producer.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expect(retrievedDocumentByProducer).toEqual(agreement); + + const retrievedDocumentByProducerDelegate = + await agreementService.getAgreementById(agreement.id, { + authData: getRandomAuthData(producerDelegate.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + expect(retrievedDocumentByProducerDelegate).toEqual(agreement); + + const retrievedDocumentByConsumerDelegate = + await agreementService.getAgreementById(agreement.id, { + authData: getRandomAuthData(consumerDelegate.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + expect(retrievedDocumentByConsumerDelegate).toEqual(agreement); + }); + + it(`should throw an organizationNotAllowed error when the requester is + not the consumer, producer, consumer delegate, or producer delegate`, async () => { + const agreement = getMockAgreement(); + + await addOneAgreement(agreement); + + const authData = getRandomAuthData(); + await expect( + agreementService.getAgreementById(agreement.id, { + authData, + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }) + ).rejects.toThrowError(organizationNotAllowed(authData.organizationId)); }); it("should throw an agreementNotFound error when the agreement does not exist", async () => { @@ -24,7 +134,12 @@ describe("get agreement", () => { await addOneAgreement(getMockAgreement()); await expect( - agreementService.getAgreementById(agreementId, genericLogger) + agreementService.getAgreementById(agreementId, { + authData: getRandomAuthData(), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }) ).rejects.toThrowError(agreementNotFound(agreementId)); }); }); From fb9b63d60d14c667d47a22765ccc721030dcba63 Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Mon, 17 Feb 2025 16:00:07 +0100 Subject: [PATCH 05/11] Committing WIP, missin tests for getAgreements --- .../src/services/agreementService.ts | 18 +- .../src/services/readModelService.ts | 172 ++-- .../test/getAgreements.test.ts | 907 ++++++++++-------- 3 files changed, 608 insertions(+), 489 deletions(-) diff --git a/packages/agreement-process/src/services/agreementService.ts b/packages/agreement-process/src/services/agreementService.ts index dbbbe1bff0..de6472d7ce 100644 --- a/packages/agreement-process/src/services/agreementService.ts +++ b/packages/agreement-process/src/services/agreementService.ts @@ -234,21 +234,17 @@ export function agreementServiceBuilder( offset: number, { authData, logger }: WithLogger ): Promise> { - logger.info("Retrieving agreements"); - const agreements = await readModelService.getAgreements( + logger.info( + `Getting agreements with producerId = ${filters.producerId}, consumerId = ${filters.consumerId}, eserviceId = ${filters.eserviceId}, agreementStates = ${filters.agreementStates}, attributeId = ${filters.attributeId}, showOnlyUpgradeable = ${filters.showOnlyUpgradeable}, offset = ${offset}, limit = ${limit}` + ); + + // Permissions are checked in the readModelService + return await readModelService.getAgreements( + authData.organizationId, filters, limit, offset ); - agreements.results.forEach( - async (a) => - await assertRequesterCanRetrieveAgreement( - a, - authData, - readModelService - ) - ); - return agreements; }, async getAgreementById( agreementId: AgreementId, diff --git a/packages/agreement-process/src/services/readModelService.ts b/packages/agreement-process/src/services/readModelService.ts index f47bda65c3..759c906e8e 100644 --- a/packages/agreement-process/src/services/readModelService.ts +++ b/packages/agreement-process/src/services/readModelService.ts @@ -317,33 +317,84 @@ async function searchTenantsByName( }; } +const addProducerDelegationData: Document = { + $addFields: { + activeProducerDelegations: { + $filter: { + input: "$delegations", + as: "delegation", + cond: { + $and: [ + { + $eq: ["$$delegation.data.kind", delegationKind.delegatedProducer], + }, + { + $eq: ["$$delegation.data.state", agreementState.active], + }, + { + $eq: ["$$delegation.data.delegatorId", "$data.producerId"], + }, + ], + }, + }, + }, + }, +}; + +const addConsumerDelegationData: Document = { + $addFields: { + activeConsumerDelegations: { + $filter: { + input: "$delegations", + as: "delegation", + cond: { + $and: [ + { + $eq: ["$$delegation.data.kind", delegationKind.delegatedConsumer], + }, + { $eq: ["$$delegation.data.state", delegationState.active] }, + { + $eq: ["$$delegation.data.delegatorId", "$data.consumerId"], + }, + ], + }, + }, + }, + }, +}; + +const addDelegationDataPipeline: Document[] = [ + { + $lookup: { + from: "delegations", + localField: "data.eserviceId", + foreignField: "data.eserviceId", + as: "delegations", + }, + }, + addConsumerDelegationData, + addProducerDelegationData, +]; + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type -function getProducerDelegateAgreementsFilters(producerIds: TenantId[]) { +function getProducerOrDelegateFilter(producerIds: TenantId[]) { return producerIds && producerIds.length > 0 ? [ { $match: { $or: [ - { - $and: [ - { - "delegations.data.kind": delegationKind.delegatedProducer, - }, - { - "delegations.data.state": agreementState.active, - }, - { - "delegations.data.delegateId": { - $in: producerIds, - }, - }, - ], - }, { "data.producerId": { $in: producerIds, }, }, + { + activeProducerDelegations: { + $elemMatch: { + "data.delegateId": { $in: producerIds }, + }, + }, + }, ], }, }, @@ -352,46 +403,24 @@ function getProducerDelegateAgreementsFilters(producerIds: TenantId[]) { } // eslint-disable-next-line @typescript-eslint/explicit-function-return-type -function getConsumerDelegateAgreementsFilters(consumerIds: TenantId[]) { +function getConsumerOrDelegateFilter(consumerIds: TenantId[]) { return consumerIds && consumerIds.length > 0 ? [ { $match: { $or: [ { - $expr: { - $anyElementTrue: { - $map: { - input: "$delegations", - as: "del", - in: { - $and: [ - { - $eq: [ - "$$del.data.kind", - delegationKind.delegatedConsumer, - ], - }, - { $eq: ["$$del.data.state", delegationState.active] }, - { - // We must perform this equality to identify the right consumer delegation - // but an exact equality between the element - // of a lookup and the original data item is possible only inside an $expr, - // that's why we used an expression instead of normal filters - $eq: ["$$del.data.delegatorId", "$data.consumerId"], - }, - { - $in: ["$$del.data.delegateId", consumerIds], - }, - ], - }, - }, - }, + "data.consumerId": { + $in: consumerIds, }, }, { - "data.consumerId": { - $in: consumerIds, + activeConsumerDelegations: { + $elemMatch: { + "data.delegateId": { + $in: consumerIds, + }, + }, }, }, ], @@ -401,24 +430,33 @@ function getConsumerDelegateAgreementsFilters(consumerIds: TenantId[]) { : []; } -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -function getDelegationsFilterPipeline( - filters: Pick -) { - return filters.producerIds.length > 0 || filters.consumerIds.length > 0 - ? [ +function applyVisibilityToAgreements(requesterId: TenantId): Document { + return { + $match: { + $or: [ + { + "data.producerId": requesterId, + }, + { + "data.consumerId": requesterId, + }, { - $lookup: { - from: "delegations", - localField: "data.eserviceId", - foreignField: "data.eserviceId", - as: "delegations", + activeProducerDelegations: { + $elemMatch: { + "data.delegateId": requesterId, + }, }, }, - ...getProducerDelegateAgreementsFilters(filters.producerIds), - ...getConsumerDelegateAgreementsFilters(filters.consumerIds), - ] - : []; + { + activeConsumerDelegations: { + $elemMatch: { + "data.delegateId": requesterId, + }, + }, + }, + ], + }, + }; } // eslint-disable-next-line @typescript-eslint/explicit-function-return-type @@ -429,6 +467,7 @@ export function readModelServiceBuilder( readModelRepository; return { async getAgreements( + requesterId: TenantId, filters: AgreementQueryFilters, limit: number, offset: number @@ -449,8 +488,11 @@ export function readModelServiceBuilder( const agreementsData = await agreements .aggregate( [ + ...addDelegationDataPipeline, + ...getProducerOrDelegateFilter(producerIds), + ...getConsumerOrDelegateFilter(consumerIds), getAgreementsFilters(otherFilters), - ...getDelegationsFilterPipeline({ producerIds, consumerIds }), + applyVisibilityToAgreements(requesterId), ], { allowDiskUse: true, @@ -625,7 +667,9 @@ export function readModelServiceBuilder( }; const agreementAggregationPipeline = [ - ...getDelegationsFilterPipeline(filters), + ...addDelegationDataPipeline, + ...getProducerOrDelegateFilter(filters.producerIds), + ...getConsumerOrDelegateFilter(filters.consumerIds), { $match: agreementFilter, }, diff --git a/packages/agreement-process/test/getAgreements.test.ts b/packages/agreement-process/test/getAgreements.test.ts index a51e50f96e..f576caf76c 100644 --- a/packages/agreement-process/test/getAgreements.test.ts +++ b/packages/agreement-process/test/getAgreements.test.ts @@ -5,6 +5,7 @@ import { getMockEService, getMockAgreement, getMockDelegation, + getRandomAuthData, } from "pagopa-interop-commons-test"; import { genericLogger } from "pagopa-interop-commons"; import { @@ -19,6 +20,7 @@ import { agreementState, TenantId, delegationKind, + delegationState, } from "pagopa-interop-models"; import { describe, beforeEach, it, expect } from "vitest"; import { @@ -33,9 +35,9 @@ describe("get agreements", () => { let tenant1: Tenant; let tenant2: Tenant; let tenant3: Tenant; - let tenant4: Tenant; - let tenant5: Tenant; - let tenant6: Tenant; + let delegateProducer1: Tenant; + let delegateConsumer1: Tenant; + let delegateConsumer2: Tenant; let descriptor1: Descriptor; let descriptor2: Descriptor; let descriptor3: Descriptor; @@ -45,7 +47,6 @@ describe("get agreements", () => { let eservice2: EService; let eservice3: EService; let eservice4: EService; - let eservice5: EService; let attribute1: AgreementAttribute; let attribute2: AgreementAttribute; let attribute3: AgreementAttribute; @@ -60,15 +61,14 @@ describe("get agreements", () => { let agreement8: Agreement; let agreement9: Agreement; let agreement10: Agreement; - let agreement11: Agreement; beforeEach(async () => { tenant1 = getMockTenant(); tenant2 = getMockTenant(); tenant3 = getMockTenant(); - tenant4 = getMockTenant(); - tenant5 = getMockTenant(); - tenant6 = getMockTenant(); + delegateProducer1 = getMockTenant(); + delegateConsumer1 = getMockTenant(); + delegateConsumer2 = getMockTenant(); descriptor1 = { ...getMockDescriptorPublished(), @@ -112,20 +112,18 @@ describe("get agreements", () => { ...getMockEService(generateId(), tenant3.id, [descriptor5]), name: "EService4", // Adding name because results are sorted by esevice name }; - eservice5 = { - ...getMockEService(generateId(), tenant4.id, [descriptor5]), - name: "EService5", // Adding name because results are sorted by esevice name - }; await addOneTenant(tenant1); await addOneTenant(tenant2); await addOneTenant(tenant3); - await addOneTenant(tenant4); + await addOneTenant(delegateProducer1); + await addOneTenant(delegateConsumer1); + await addOneTenant(delegateConsumer2); + await addOneEService(eservice1); await addOneEService(eservice2); await addOneEService(eservice3); await addOneEService(eservice4); - await addOneEService(eservice5); attribute1 = { id: generateId() }; attribute2 = { id: generateId() }; @@ -183,27 +181,33 @@ describe("get agreements", () => { }; agreement8 = { - ...getMockAgreement(eservice5.id, tenant1.id, agreementState.draft), - descriptorId: eservice5.descriptors[0].id, - producerId: eservice5.producerId, + ...getMockAgreement( + eservice4.id, + delegateProducer1.id, + agreementState.active + ), + descriptorId: eservice4.descriptors[0].id, + producerId: eservice4.producerId, }; agreement9 = { - ...getMockAgreement(eservice5.id, tenant5.id, agreementState.draft), - descriptorId: eservice5.descriptors[0].id, - producerId: eservice5.producerId, + ...getMockAgreement( + eservice4.id, + delegateConsumer1.id, + agreementState.active + ), + descriptorId: eservice4.descriptors[0].id, + producerId: eservice4.producerId, }; agreement10 = { - ...getMockAgreement(eservice5.id, tenant6.id, agreementState.draft), - descriptorId: eservice5.descriptors[0].id, - producerId: eservice5.producerId, - }; - - agreement11 = { - ...getMockAgreement(eservice5.id, tenant4.id, agreementState.draft), - descriptorId: eservice5.descriptors[0].id, - producerId: eservice5.producerId, + ...getMockAgreement( + eservice4.id, + delegateConsumer2.id, + agreementState.active + ), + descriptorId: eservice4.descriptors[0].id, + producerId: eservice4.producerId, }; await addOneAgreement(agreement1); @@ -216,446 +220,521 @@ describe("get agreements", () => { await addOneAgreement(agreement8); await addOneAgreement(agreement9); await addOneAgreement(agreement10); - await addOneAgreement(agreement11); - const delegation1 = getMockDelegation({ + const producerDelegation1 = getMockDelegation({ kind: delegationKind.delegatedProducer, - delegateId: eservice4.producerId, - delegatorId: tenant3.id, - eserviceId: eservice4.id, - state: agreementState.active, + delegateId: delegateProducer1.id, + delegatorId: eservice1.producerId, + eserviceId: eservice1.id, + state: delegationState.active, }); - const delegation2 = getMockDelegation({ + const consumerDelegation1 = getMockDelegation({ kind: delegationKind.delegatedConsumer, - delegateId: tenant4.id, + delegateId: delegateConsumer1.id, delegatorId: tenant1.id, - eserviceId: eservice5.id, - state: agreementState.active, + eserviceId: eservice3.id, + state: delegationState.active, }); - const delegation3 = getMockDelegation({ + const consumerDelegation2 = getMockDelegation({ kind: delegationKind.delegatedConsumer, - delegateId: tenant6.id, - delegatorId: tenant5.id, - eserviceId: eservice5.id, - state: agreementState.active, - }); - const delegation4 = getMockDelegation({ - kind: delegationKind.delegatedConsumer, - delegateId: tenant5.id, - delegatorId: tenant6.id, - eserviceId: eservice5.id, - state: agreementState.active, + delegateId: delegateConsumer2.id, + delegatorId: tenant3.id, + eserviceId: eservice3.id, + state: delegationState.active, }); + // TODO should we also add inactive delegations? - await addOneDelegation(delegation1); - await addOneDelegation(delegation2); - await addOneDelegation(delegation3); - await addOneDelegation(delegation4); + await addOneDelegation(producerDelegation1); + await addOneDelegation(consumerDelegation1); + await addOneDelegation(consumerDelegation2); }); - it("should get all agreements if no filters are provided", async () => { - const allAgreements = await agreementService.getAgreements( + it("should get all agreements visible to consumer/producer requester if no filters are provided", async () => { + const allAgreementsVisibleToTenant1 = await agreementService.getAgreements( {}, 20, 0, - genericLogger - ); - expect(allAgreements).toEqual({ - totalCount: 11, - results: expect.arrayContaining([ - agreement1, - agreement2, - agreement3, - agreement4, - agreement5, - agreement6, - agreement7, - agreement8, - agreement9, - agreement10, - agreement11, - ]), - }); - }); - - it("should get agreements with filters: producerId", async () => { - const agreements1 = await agreementService.getAgreements( - { - producerId: eservice1.producerId, - }, - 10, - 0, - genericLogger - ); - expect(agreements1).toEqual({ - totalCount: 2, - results: expect.arrayContaining([agreement1, agreement2]), - }); - - const agreements2 = await agreementService.getAgreements( - { - producerId: [eservice1.producerId, eservice2.producerId], - }, - 10, - 0, - genericLogger - ); - - expect(agreements2).toEqual({ - totalCount: 4, - results: expect.arrayContaining([ - agreement1, - agreement2, - agreement3, - agreement4, - ]), - }); - }); - - it("should get agreements with filters: consumerId", async () => { - const agreements1 = await agreementService.getAgreements( { - consumerId: tenant1.id, - }, - 10, - 0, - genericLogger + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } ); - expect(agreements1).toEqual({ + expect(allAgreementsVisibleToTenant1).toEqual({ totalCount: 5, - results: expect.arrayContaining([ - agreement1, - agreement3, - agreement5, - agreement7, - agreement8, - ]), - }); - - const agreements2 = await agreementService.getAgreements( - { - consumerId: [tenant1.id, tenant2.id], - }, - 10, - 0, - genericLogger - ); - expect(agreements2).toEqual({ - totalCount: 7, results: expect.arrayContaining([ agreement1, agreement2, agreement3, - agreement4, agreement5, agreement7, - agreement8, ]), }); - }); - it("should get agreements with filters: eserviceId", async () => { - const agreements1 = await agreementService.getAgreements( - { - eserviceId: eservice1.id, - }, - 10, + const allAgreementsVisibleToTenant2 = await agreementService.getAgreements( + {}, + 20, 0, - genericLogger - ); - expect(agreements1).toEqual({ - totalCount: 2, - results: expect.arrayContaining([agreement1, agreement2]), - }); - - const agreements2 = await agreementService.getAgreements( { - eserviceId: [eservice1.id, eservice2.id], - }, - 10, - 0, - genericLogger + authData: getRandomAuthData(tenant2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } ); - expect(agreements2).toEqual({ - totalCount: 4, - results: expect.arrayContaining([ - agreement1, - agreement2, - agreement3, - agreement4, - ]), - }); - }); - it("should get agreements with filters: descriptorId", async () => { - const agreements1 = await agreementService.getAgreements( - { - descriptorId: descriptor1.id, - }, - 10, - 0, - genericLogger - ); - expect(agreements1).toEqual({ - totalCount: 1, - results: expect.arrayContaining([agreement1]), + expect(allAgreementsVisibleToTenant2).toEqual({ + totalCount: 3, + results: expect.arrayContaining([agreement2, agreement3, agreement4]), }); - const agreements2 = await agreementService.getAgreements( - { - descriptorId: [descriptor1.id, descriptor3.id, descriptor5.id], - }, - 10, + const allAgreementsVisibleToTenant3 = await agreementService.getAgreements( + {}, + 20, 0, - genericLogger + { + authData: getRandomAuthData(tenant3.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } ); - expect(agreements2).toEqual({ - totalCount: 9, + + expect(allAgreementsVisibleToTenant3).toEqual({ + totalCount: 6, results: expect.arrayContaining([ - agreement1, - agreement3, agreement5, agreement6, agreement7, agreement8, agreement9, agreement10, - agreement11, ]), }); }); - it("should get agreements with filters: attributeId", async () => { - const agreements1 = await agreementService.getAgreements( - { - attributeId: attribute2.id, - }, - 10, - 0, - genericLogger - ); - expect(agreements1).toEqual({ - totalCount: 1, - results: expect.arrayContaining([agreement1]), - }); - - const agreements2 = await agreementService.getAgreements( - { - attributeId: attribute3.id, - }, - 10, - 0, - genericLogger - ); - expect(agreements2).toEqual({ - totalCount: 2, - results: expect.arrayContaining([agreement1, agreement2]), - }); - - const agreements3 = await agreementService.getAgreements( - { - attributeId: [attribute1.id, attribute3.id, attribute4.id], - }, - 10, - 0, - genericLogger - ); - expect(agreements3).toEqual({ - totalCount: 2, - results: expect.arrayContaining([agreement1, agreement2]), - }); - }); - it("should get agreements with filters: state", async () => { - const agreements = await agreementService.getAgreements( - { - agreementStates: [agreementState.active, agreementState.pending], - }, - 10, - 0, - genericLogger - ); - expect(agreements).toEqual({ - totalCount: 2, - results: expect.arrayContaining([agreement2, agreement3]), - }); - }); - it("should get agreements with filters: showOnlyUpgradeable", async () => { - const agreements = await agreementService.getAgreements( - { - showOnlyUpgradeable: true, - }, - 10, - 0, - genericLogger - ); - expect(agreements).toEqual({ - totalCount: 1, - results: expect.arrayContaining([ - agreement1, - // also agreement4 has a latest descriptor to upgrade to, - // but it is not in an upgradeable state - ]), - }); - }); - - it("should get agreements with filters: producerId, consumerId, eserviceId", async () => { - const agreements = await agreementService.getAgreements( - { - producerId: [eservice1.producerId, eservice2.producerId], - consumerId: tenant1.id, - eserviceId: [eservice1.id, eservice2.id], - }, - 10, - 0, - genericLogger - ); - expect(agreements).toEqual({ - totalCount: 2, - results: expect.arrayContaining([agreement1, agreement3]), - }); - }); - - it("should get agreements with filters: producerId, consumerId, eserviceId, descriptorId", async () => { - const agreements = await agreementService.getAgreements( - { - producerId: [eservice1.producerId, eservice2.producerId], - consumerId: tenant1.id, - eserviceId: [eservice1.id, eservice2.id], - descriptorId: [descriptor1.id], - }, - 10, - 0, - genericLogger - ); - expect(agreements).toEqual({ - totalCount: 1, - results: expect.arrayContaining([agreement1]), - }); - }); - - it("should get agreements with filters: attributeId, state", async () => { - const agreements = await agreementService.getAgreements( - { - attributeId: attribute3.id, - agreementStates: [agreementState.active], - }, - 10, - 0, - genericLogger - ); - expect(agreements).toEqual({ - totalCount: 1, - results: expect.arrayContaining([agreement2]), - }); - }); + it("should get all agreements visible to delegate producer requester if no filters are provided", async () => { + const allAgreementsVisibleToDelegateProducer1 = + await agreementService.getAgreements({}, 20, 0, { + authData: getRandomAuthData(delegateProducer1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); - it("should get agreements with filters: showOnlyUpgradeable, state, descriptorId", async () => { - const agreements1 = await agreementService.getAgreements( - { - showOnlyUpgradeable: true, - agreementStates: [agreementState.draft], - descriptorId: descriptor1.id, - }, - 10, - 0, - genericLogger - ); - expect(agreements1).toEqual({ - totalCount: 1, - results: expect.arrayContaining([agreement1]), - }); - - const agreements2 = await agreementService.getAgreements( - { - showOnlyUpgradeable: true, - agreementStates: [agreementState.suspended], - descriptorId: descriptor1.id, - }, - 10, - 0, - genericLogger - ); - expect(agreements2).toEqual({ - totalCount: 0, - results: [], + expect(allAgreementsVisibleToDelegateProducer1).toEqual({ + totalCount: 3, + results: expect.arrayContaining([agreement1, agreement2, agreement8]), }); }); - it("should get agreements with limit", async () => { - const agreements = await agreementService.getAgreements( - { - eserviceId: eservice1.id, - }, + it("should get all agreements visible to delegate consumer requester if no filters are provided", async () => { + const allAgreementsVisibleToDelegateConsumer1 = + await agreementService.getAgreements({}, 20, 0, { + authData: getRandomAuthData(delegateConsumer1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); - 1, - 0, - genericLogger - ); - expect(agreements).toEqual({ + expect(allAgreementsVisibleToDelegateConsumer1).toEqual({ totalCount: 2, - results: expect.arrayContaining([agreement1]), + results: expect.arrayContaining([agreement5, agreement9]), }); - }); - it("should get agreements with offset and limit", async () => { - const agreements = await agreementService.getAgreements( - { - eserviceId: [eservice1.id, eservice2.id], - }, + const allAgreementsVisibleToDelegateConsumer2 = + await agreementService.getAgreements({}, 20, 0, { + authData: getRandomAuthData(delegateConsumer2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); - 2, - 1, - genericLogger - ); - expect(agreements).toEqual({ - totalCount: 4, - results: expect.arrayContaining([agreement2, agreement3]), - }); - }); - - it("should get no agreements in case no filters match", async () => { - const agreements = await agreementService.getAgreements( - { - producerId: generateId(), - }, - 10, - 0, - genericLogger - ); - - expect(agreements).toEqual({ - totalCount: 0, - results: [], - }); - }); - - it("should get agreements for a delegated eservice with filters: producerId and requester is producer", async () => { - const agreements = await agreementService.getAgreements( - { - producerId: eservice4.producerId, - }, - 10, - 0, - genericLogger - ); - expect(agreements).toEqual({ - totalCount: 3, - results: expect.arrayContaining([agreement5, agreement6, agreement7]), - }); - }); - - it("should get agreements for a delegated eservice with filters: consumerId and requester is consumer", async () => { - const agreements = await agreementService.getAgreements( - { - consumerId: tenant4.id, - }, - 10, - 0, - genericLogger - ); - expect(agreements).toEqual({ + expect(allAgreementsVisibleToDelegateConsumer2).toEqual({ totalCount: 2, - results: expect.arrayContaining([agreement8, agreement11]), + results: expect.arrayContaining([agreement6, agreement10]), }); }); + + // it("should get agreements with filters: producerId", async () => { + // const agreements1 = await agreementService.getAgreements( + // { + // producerId: eservice1.producerId, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements1).toEqual({ + // totalCount: 2, + // results: expect.arrayContaining([agreement1, agreement2]), + // }); + + // const agreements2 = await agreementService.getAgreements( + // { + // producerId: [eservice1.producerId, eservice2.producerId], + // }, + // 10, + // 0, + // genericLogger + // ); + + // expect(agreements2).toEqual({ + // totalCount: 4, + // results: expect.arrayContaining([ + // agreement1, + // agreement2, + // agreement3, + // agreement4, + // ]), + // }); + // }); + + // it("should get agreements with filters: consumerId", async () => { + // const agreements1 = await agreementService.getAgreements( + // { + // consumerId: tenant1.id, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements1).toEqual({ + // totalCount: 5, + // results: expect.arrayContaining([ + // agreement1, + // agreement3, + // agreement5, + // agreement7, + // agreement8, + // ]), + // }); + + // const agreements2 = await agreementService.getAgreements( + // { + // consumerId: [tenant1.id, tenant2.id], + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements2).toEqual({ + // totalCount: 7, + // results: expect.arrayContaining([ + // agreement1, + // agreement2, + // agreement3, + // agreement4, + // agreement5, + // agreement7, + // agreement8, + // ]), + // }); + // }); + + // it("should get agreements with filters: eserviceId", async () => { + // const agreements1 = await agreementService.getAgreements( + // { + // eserviceId: eservice1.id, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements1).toEqual({ + // totalCount: 2, + // results: expect.arrayContaining([agreement1, agreement2]), + // }); + + // const agreements2 = await agreementService.getAgreements( + // { + // eserviceId: [eservice1.id, eservice2.id], + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements2).toEqual({ + // totalCount: 4, + // results: expect.arrayContaining([ + // agreement1, + // agreement2, + // agreement3, + // agreement4, + // ]), + // }); + // }); + + // it("should get agreements with filters: descriptorId", async () => { + // const agreements1 = await agreementService.getAgreements( + // { + // descriptorId: descriptor1.id, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements1).toEqual({ + // totalCount: 1, + // results: expect.arrayContaining([agreement1]), + // }); + + // const agreements2 = await agreementService.getAgreements( + // { + // descriptorId: [descriptor1.id, descriptor3.id, descriptor5.id], + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements2).toEqual({ + // totalCount: 9, + // results: expect.arrayContaining([ + // agreement1, + // agreement3, + // agreement5, + // agreement6, + // agreement7, + // agreement8, + // agreement9, + // agreement10, + // agreement11, + // ]), + // }); + // }); + + // it("should get agreements with filters: attributeId", async () => { + // const agreements1 = await agreementService.getAgreements( + // { + // attributeId: attribute2.id, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements1).toEqual({ + // totalCount: 1, + // results: expect.arrayContaining([agreement1]), + // }); + + // const agreements2 = await agreementService.getAgreements( + // { + // attributeId: attribute3.id, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements2).toEqual({ + // totalCount: 2, + // results: expect.arrayContaining([agreement1, agreement2]), + // }); + + // const agreements3 = await agreementService.getAgreements( + // { + // attributeId: [attribute1.id, attribute3.id, attribute4.id], + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements3).toEqual({ + // totalCount: 2, + // results: expect.arrayContaining([agreement1, agreement2]), + // }); + // }); + // it("should get agreements with filters: state", async () => { + // const agreements = await agreementService.getAgreements( + // { + // agreementStates: [agreementState.active, agreementState.pending], + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements).toEqual({ + // totalCount: 2, + // results: expect.arrayContaining([agreement2, agreement3]), + // }); + // }); + // it("should get agreements with filters: showOnlyUpgradeable", async () => { + // const agreements = await agreementService.getAgreements( + // { + // showOnlyUpgradeable: true, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements).toEqual({ + // totalCount: 1, + // results: expect.arrayContaining([ + // agreement1, + // // also agreement4 has a latest descriptor to upgrade to, + // // but it is not in an upgradeable state + // ]), + // }); + // }); + + // it("should get agreements with filters: producerId, consumerId, eserviceId", async () => { + // const agreements = await agreementService.getAgreements( + // { + // producerId: [eservice1.producerId, eservice2.producerId], + // consumerId: tenant1.id, + // eserviceId: [eservice1.id, eservice2.id], + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements).toEqual({ + // totalCount: 2, + // results: expect.arrayContaining([agreement1, agreement3]), + // }); + // }); + + // it("should get agreements with filters: producerId, consumerId, eserviceId, descriptorId", async () => { + // const agreements = await agreementService.getAgreements( + // { + // producerId: [eservice1.producerId, eservice2.producerId], + // consumerId: tenant1.id, + // eserviceId: [eservice1.id, eservice2.id], + // descriptorId: [descriptor1.id], + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements).toEqual({ + // totalCount: 1, + // results: expect.arrayContaining([agreement1]), + // }); + // }); + + // it("should get agreements with filters: attributeId, state", async () => { + // const agreements = await agreementService.getAgreements( + // { + // attributeId: attribute3.id, + // agreementStates: [agreementState.active], + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements).toEqual({ + // totalCount: 1, + // results: expect.arrayContaining([agreement2]), + // }); + // }); + + // it("should get agreements with filters: showOnlyUpgradeable, state, descriptorId", async () => { + // const agreements1 = await agreementService.getAgreements( + // { + // showOnlyUpgradeable: true, + // agreementStates: [agreementState.draft], + // descriptorId: descriptor1.id, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements1).toEqual({ + // totalCount: 1, + // results: expect.arrayContaining([agreement1]), + // }); + + // const agreements2 = await agreementService.getAgreements( + // { + // showOnlyUpgradeable: true, + // agreementStates: [agreementState.suspended], + // descriptorId: descriptor1.id, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements2).toEqual({ + // totalCount: 0, + // results: [], + // }); + // }); + + // it("should get agreements with limit", async () => { + // const agreements = await agreementService.getAgreements( + // { + // eserviceId: eservice1.id, + // }, + + // 1, + // 0, + // genericLogger + // ); + // expect(agreements).toEqual({ + // totalCount: 2, + // results: expect.arrayContaining([agreement1]), + // }); + // }); + + // it("should get agreements with offset and limit", async () => { + // const agreements = await agreementService.getAgreements( + // { + // eserviceId: [eservice1.id, eservice2.id], + // }, + + // 2, + // 1, + // genericLogger + // ); + // expect(agreements).toEqual({ + // totalCount: 4, + // results: expect.arrayContaining([agreement2, agreement3]), + // }); + // }); + + // it("should get no agreements in case no filters match", async () => { + // const agreements = await agreementService.getAgreements( + // { + // producerId: generateId(), + // }, + // 10, + // 0, + // genericLogger + // ); + + // expect(agreements).toEqual({ + // totalCount: 0, + // results: [], + // }); + // }); + + // it("should get agreements for a delegated eservice with filters: producerId and requester is producer", async () => { + // const agreements = await agreementService.getAgreements( + // { + // producerId: eservice4.producerId, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements).toEqual({ + // totalCount: 3, + // results: expect.arrayContaining([agreement5, agreement6, agreement7]), + // }); + // }); + + // it("should get agreements for a delegated eservice with filters: consumerId and requester is consumer", async () => { + // const agreements = await agreementService.getAgreements( + // { + // consumerId: tenant4.id, + // }, + // 10, + // 0, + // genericLogger + // ); + // expect(agreements).toEqual({ + // totalCount: 2, + // results: expect.arrayContaining([agreement8, agreement11]), + // }); + // }); }); From 131f7cc2b631a824cd9e3fbf2a4e7b63c912abf5 Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Mon, 17 Feb 2025 17:09:31 +0100 Subject: [PATCH 06/11] Improving tests for getAgreements --- .../test/getAgreements.test.ts | 894 +++++++++--------- 1 file changed, 473 insertions(+), 421 deletions(-) diff --git a/packages/agreement-process/test/getAgreements.test.ts b/packages/agreement-process/test/getAgreements.test.ts index f576caf76c..87c86b83f3 100644 --- a/packages/agreement-process/test/getAgreements.test.ts +++ b/packages/agreement-process/test/getAgreements.test.ts @@ -18,9 +18,10 @@ import { generateId, EServiceId, agreementState, - TenantId, delegationKind, delegationState, + ListResult, + TenantId, } from "pagopa-interop-models"; import { describe, beforeEach, it, expect } from "vitest"; import { @@ -31,6 +32,17 @@ import { addOneDelegation, } from "./utils.js"; +function expectSinglePageListResult( + actual: ListResult, + expected: Agreement[] +): void { + expect(actual).toEqual({ + totalCount: expected.length, + results: expect.arrayContaining(expected), + }); + expect(actual.results).toHaveLength(expected.length); +} + describe("get agreements", () => { let tenant1: Tenant; let tenant2: Tenant; @@ -242,11 +254,29 @@ describe("get agreements", () => { eserviceId: eservice3.id, state: delegationState.active, }); - // TODO should we also add inactive delegations? + + // These delegations are revoked: the delegates + // should not see the corresponding agreements + const revokedProducerDelegation = getMockDelegation({ + kind: delegationKind.delegatedProducer, + delegateId: delegateProducer1.id, + delegatorId: eservice2.producerId, + eserviceId: eservice2.id, + state: delegationState.revoked, + }); + const revokedConsumerDelegation = getMockDelegation({ + kind: delegationKind.delegatedConsumer, + delegateId: delegateConsumer1.id, + delegatorId: tenant2.id, + eserviceId: eservice3.id, + state: delegationState.revoked, + }); await addOneDelegation(producerDelegation1); await addOneDelegation(consumerDelegation1); await addOneDelegation(consumerDelegation2); + await addOneDelegation(revokedProducerDelegation); + await addOneDelegation(revokedConsumerDelegation); }); it("should get all agreements visible to consumer/producer requester if no filters are provided", async () => { @@ -261,16 +291,13 @@ describe("get agreements", () => { logger: genericLogger, } ); - expect(allAgreementsVisibleToTenant1).toEqual({ - totalCount: 5, - results: expect.arrayContaining([ - agreement1, - agreement2, - agreement3, - agreement5, - agreement7, - ]), - }); + expectSinglePageListResult(allAgreementsVisibleToTenant1, [ + agreement1, + agreement2, + agreement3, + agreement5, + agreement7, + ]); const allAgreementsVisibleToTenant2 = await agreementService.getAgreements( {}, @@ -283,11 +310,11 @@ describe("get agreements", () => { logger: genericLogger, } ); - - expect(allAgreementsVisibleToTenant2).toEqual({ - totalCount: 3, - results: expect.arrayContaining([agreement2, agreement3, agreement4]), - }); + expectSinglePageListResult(allAgreementsVisibleToTenant2, [ + agreement2, + agreement3, + agreement4, + ]); const allAgreementsVisibleToTenant3 = await agreementService.getAgreements( {}, @@ -300,18 +327,14 @@ describe("get agreements", () => { logger: genericLogger, } ); - - expect(allAgreementsVisibleToTenant3).toEqual({ - totalCount: 6, - results: expect.arrayContaining([ - agreement5, - agreement6, - agreement7, - agreement8, - agreement9, - agreement10, - ]), - }); + expectSinglePageListResult(allAgreementsVisibleToTenant3, [ + agreement5, + agreement6, + agreement7, + agreement8, + agreement9, + agreement10, + ]); }); it("should get all agreements visible to delegate producer requester if no filters are provided", async () => { @@ -322,11 +345,11 @@ describe("get agreements", () => { correlationId: generateId(), logger: genericLogger, }); - - expect(allAgreementsVisibleToDelegateProducer1).toEqual({ - totalCount: 3, - results: expect.arrayContaining([agreement1, agreement2, agreement8]), - }); + expectSinglePageListResult(allAgreementsVisibleToDelegateProducer1, [ + agreement1, + agreement2, + agreement8, + ]); }); it("should get all agreements visible to delegate consumer requester if no filters are provided", async () => { @@ -338,10 +361,10 @@ describe("get agreements", () => { logger: genericLogger, }); - expect(allAgreementsVisibleToDelegateConsumer1).toEqual({ - totalCount: 2, - results: expect.arrayContaining([agreement5, agreement9]), - }); + expectSinglePageListResult(allAgreementsVisibleToDelegateConsumer1, [ + agreement5, + agreement9, + ]); const allAgreementsVisibleToDelegateConsumer2 = await agreementService.getAgreements({}, 20, 0, { @@ -351,390 +374,419 @@ describe("get agreements", () => { logger: genericLogger, }); - expect(allAgreementsVisibleToDelegateConsumer2).toEqual({ - totalCount: 2, - results: expect.arrayContaining([agreement6, agreement10]), + expectSinglePageListResult(allAgreementsVisibleToDelegateConsumer2, [ + agreement6, + agreement10, + ]); + }); + + it("should get agreements with filters: producerId", async () => { + const agreements1 = await agreementService.getAgreements( + { + producerId: eservice1.producerId, + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements1, [agreement1, agreement2]); + + const agreements2 = await agreementService.getAgreements( + { + producerId: [eservice1.producerId, eservice2.producerId], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements2, [ + agreement1, + agreement2, + agreement3, + ]); + }); + + it("should get agreements with filters: consumerId", async () => { + const agreements1 = await agreementService.getAgreements( + { + consumerId: tenant1.id, + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements1, [ + agreement1, + agreement3, + agreement5, + agreement7, + ]); + + const agreements2 = await agreementService.getAgreements( + { + consumerId: [tenant1.id, tenant2.id], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements2, [ + agreement1, + agreement2, + agreement3, + agreement5, + agreement7, + ]); + }); + + it("should get agreements with filters: eserviceId", async () => { + const agreements1 = await agreementService.getAgreements( + { + eserviceId: eservice1.id, + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements1, [agreement1, agreement2]); + + const agreements2 = await agreementService.getAgreements( + { + eserviceId: [eservice1.id, eservice2.id], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements2, [ + agreement1, + agreement2, + agreement3, + ]); + }); + + it("should get agreements with filters: descriptorId", async () => { + const agreements1 = await agreementService.getAgreements( + { + descriptorId: descriptor1.id, + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements1, [agreement1]); + + const agreements2 = await agreementService.getAgreements( + { + descriptorId: [descriptor1.id, descriptor3.id, descriptor5.id], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements2, [ + agreement1, + agreement3, + agreement5, + agreement7, + ]); + }); + + it("should get agreements with filters: attributeId", async () => { + const agreements1 = await agreementService.getAgreements( + { + attributeId: attribute2.id, + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements1, [agreement1]); + + const agreements2 = await agreementService.getAgreements( + { + attributeId: attribute3.id, + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements2, [agreement1, agreement2]); + + const agreements3 = await agreementService.getAgreements( + { + attributeId: [attribute1.id, attribute3.id, attribute4.id], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements3, [agreement1, agreement2]); + }); + + it("should get agreements with filters: state", async () => { + const agreements = await agreementService.getAgreements( + { + agreementStates: [agreementState.active, agreementState.pending], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements, [agreement2, agreement3]); + }); + + it("should get agreements with filters: showOnlyUpgradeable", async () => { + const agreements = await agreementService.getAgreements( + { + showOnlyUpgradeable: true, + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements, [ + agreement1, + // also agreement4 could upgrade to newer descriptor but it is not in an upgradeable state + ]); + }); + + it("should get agreements with filters: producerId, consumerId, eserviceId", async () => { + const agreements = await agreementService.getAgreements( + { + producerId: [eservice1.producerId, eservice2.producerId], + consumerId: tenant1.id, + eserviceId: [eservice1.id, eservice2.id], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements, [agreement1, agreement3]); + }); + + it("should get agreements with filters: producerId, consumerId, eserviceId, descriptorId", async () => { + const agreements = await agreementService.getAgreements( + { + producerId: [eservice1.producerId, eservice2.producerId], + consumerId: tenant1.id, + eserviceId: [eservice1.id, eservice2.id], + descriptorId: [descriptor1.id], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements, [agreement1]); + }); + + it("should get agreements with filters: attributeId, state", async () => { + const agreements = await agreementService.getAgreements( + { + attributeId: attribute3.id, + agreementStates: [agreementState.active], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements, [agreement2]); + }); + + it("should get agreements with filters: showOnlyUpgradeable, state, descriptorId", async () => { + const agreements1 = await agreementService.getAgreements( + { + showOnlyUpgradeable: true, + agreementStates: [agreementState.draft], + descriptorId: descriptor1.id, + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements1, [agreement1]); + + const agreements2 = await agreementService.getAgreements( + { + showOnlyUpgradeable: true, + agreementStates: [agreementState.suspended], + descriptorId: descriptor1.id, + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements2, []); + }); + + it("should get agreements with limit", async () => { + const agreements = await agreementService.getAgreements({}, 2, 0, { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + expect(agreements).toEqual({ + totalCount: 5, + results: [agreement1, agreement2], + }); + }); + + it("should get agreements with offset and limit", async () => { + const agreements = await agreementService.getAgreements({}, 2, 2, { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + expect(agreements).toEqual({ + totalCount: 5, + results: expect.arrayContaining([agreement3, agreement5]), + }); + }); + + it("should get no agreements in case no filters match", async () => { + const agreements = await agreementService.getAgreements( + { + producerId: generateId(), + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(agreements).toEqual({ + totalCount: 0, + results: [], }); }); - // it("should get agreements with filters: producerId", async () => { - // const agreements1 = await agreementService.getAgreements( - // { - // producerId: eservice1.producerId, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements1).toEqual({ - // totalCount: 2, - // results: expect.arrayContaining([agreement1, agreement2]), - // }); - - // const agreements2 = await agreementService.getAgreements( - // { - // producerId: [eservice1.producerId, eservice2.producerId], - // }, - // 10, - // 0, - // genericLogger - // ); - - // expect(agreements2).toEqual({ - // totalCount: 4, - // results: expect.arrayContaining([ - // agreement1, - // agreement2, - // agreement3, - // agreement4, - // ]), - // }); - // }); - - // it("should get agreements with filters: consumerId", async () => { - // const agreements1 = await agreementService.getAgreements( - // { - // consumerId: tenant1.id, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements1).toEqual({ - // totalCount: 5, - // results: expect.arrayContaining([ - // agreement1, - // agreement3, - // agreement5, - // agreement7, - // agreement8, - // ]), - // }); - - // const agreements2 = await agreementService.getAgreements( - // { - // consumerId: [tenant1.id, tenant2.id], - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements2).toEqual({ - // totalCount: 7, - // results: expect.arrayContaining([ - // agreement1, - // agreement2, - // agreement3, - // agreement4, - // agreement5, - // agreement7, - // agreement8, - // ]), - // }); - // }); - - // it("should get agreements with filters: eserviceId", async () => { - // const agreements1 = await agreementService.getAgreements( - // { - // eserviceId: eservice1.id, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements1).toEqual({ - // totalCount: 2, - // results: expect.arrayContaining([agreement1, agreement2]), - // }); - - // const agreements2 = await agreementService.getAgreements( - // { - // eserviceId: [eservice1.id, eservice2.id], - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements2).toEqual({ - // totalCount: 4, - // results: expect.arrayContaining([ - // agreement1, - // agreement2, - // agreement3, - // agreement4, - // ]), - // }); - // }); - - // it("should get agreements with filters: descriptorId", async () => { - // const agreements1 = await agreementService.getAgreements( - // { - // descriptorId: descriptor1.id, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements1).toEqual({ - // totalCount: 1, - // results: expect.arrayContaining([agreement1]), - // }); - - // const agreements2 = await agreementService.getAgreements( - // { - // descriptorId: [descriptor1.id, descriptor3.id, descriptor5.id], - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements2).toEqual({ - // totalCount: 9, - // results: expect.arrayContaining([ - // agreement1, - // agreement3, - // agreement5, - // agreement6, - // agreement7, - // agreement8, - // agreement9, - // agreement10, - // agreement11, - // ]), - // }); - // }); - - // it("should get agreements with filters: attributeId", async () => { - // const agreements1 = await agreementService.getAgreements( - // { - // attributeId: attribute2.id, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements1).toEqual({ - // totalCount: 1, - // results: expect.arrayContaining([agreement1]), - // }); - - // const agreements2 = await agreementService.getAgreements( - // { - // attributeId: attribute3.id, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements2).toEqual({ - // totalCount: 2, - // results: expect.arrayContaining([agreement1, agreement2]), - // }); - - // const agreements3 = await agreementService.getAgreements( - // { - // attributeId: [attribute1.id, attribute3.id, attribute4.id], - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements3).toEqual({ - // totalCount: 2, - // results: expect.arrayContaining([agreement1, agreement2]), - // }); - // }); - // it("should get agreements with filters: state", async () => { - // const agreements = await agreementService.getAgreements( - // { - // agreementStates: [agreementState.active, agreementState.pending], - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements).toEqual({ - // totalCount: 2, - // results: expect.arrayContaining([agreement2, agreement3]), - // }); - // }); - // it("should get agreements with filters: showOnlyUpgradeable", async () => { - // const agreements = await agreementService.getAgreements( - // { - // showOnlyUpgradeable: true, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements).toEqual({ - // totalCount: 1, - // results: expect.arrayContaining([ - // agreement1, - // // also agreement4 has a latest descriptor to upgrade to, - // // but it is not in an upgradeable state - // ]), - // }); - // }); - - // it("should get agreements with filters: producerId, consumerId, eserviceId", async () => { - // const agreements = await agreementService.getAgreements( - // { - // producerId: [eservice1.producerId, eservice2.producerId], - // consumerId: tenant1.id, - // eserviceId: [eservice1.id, eservice2.id], - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements).toEqual({ - // totalCount: 2, - // results: expect.arrayContaining([agreement1, agreement3]), - // }); - // }); - - // it("should get agreements with filters: producerId, consumerId, eserviceId, descriptorId", async () => { - // const agreements = await agreementService.getAgreements( - // { - // producerId: [eservice1.producerId, eservice2.producerId], - // consumerId: tenant1.id, - // eserviceId: [eservice1.id, eservice2.id], - // descriptorId: [descriptor1.id], - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements).toEqual({ - // totalCount: 1, - // results: expect.arrayContaining([agreement1]), - // }); - // }); - - // it("should get agreements with filters: attributeId, state", async () => { - // const agreements = await agreementService.getAgreements( - // { - // attributeId: attribute3.id, - // agreementStates: [agreementState.active], - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements).toEqual({ - // totalCount: 1, - // results: expect.arrayContaining([agreement2]), - // }); - // }); - - // it("should get agreements with filters: showOnlyUpgradeable, state, descriptorId", async () => { - // const agreements1 = await agreementService.getAgreements( - // { - // showOnlyUpgradeable: true, - // agreementStates: [agreementState.draft], - // descriptorId: descriptor1.id, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements1).toEqual({ - // totalCount: 1, - // results: expect.arrayContaining([agreement1]), - // }); - - // const agreements2 = await agreementService.getAgreements( - // { - // showOnlyUpgradeable: true, - // agreementStates: [agreementState.suspended], - // descriptorId: descriptor1.id, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements2).toEqual({ - // totalCount: 0, - // results: [], - // }); - // }); - - // it("should get agreements with limit", async () => { - // const agreements = await agreementService.getAgreements( - // { - // eserviceId: eservice1.id, - // }, - - // 1, - // 0, - // genericLogger - // ); - // expect(agreements).toEqual({ - // totalCount: 2, - // results: expect.arrayContaining([agreement1]), - // }); - // }); - - // it("should get agreements with offset and limit", async () => { - // const agreements = await agreementService.getAgreements( - // { - // eserviceId: [eservice1.id, eservice2.id], - // }, - - // 2, - // 1, - // genericLogger - // ); - // expect(agreements).toEqual({ - // totalCount: 4, - // results: expect.arrayContaining([agreement2, agreement3]), - // }); - // }); - - // it("should get no agreements in case no filters match", async () => { - // const agreements = await agreementService.getAgreements( - // { - // producerId: generateId(), - // }, - // 10, - // 0, - // genericLogger - // ); - - // expect(agreements).toEqual({ - // totalCount: 0, - // results: [], - // }); - // }); - - // it("should get agreements for a delegated eservice with filters: producerId and requester is producer", async () => { - // const agreements = await agreementService.getAgreements( - // { - // producerId: eservice4.producerId, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements).toEqual({ - // totalCount: 3, - // results: expect.arrayContaining([agreement5, agreement6, agreement7]), - // }); - // }); - - // it("should get agreements for a delegated eservice with filters: consumerId and requester is consumer", async () => { - // const agreements = await agreementService.getAgreements( - // { - // consumerId: tenant4.id, - // }, - // 10, - // 0, - // genericLogger - // ); - // expect(agreements).toEqual({ - // totalCount: 2, - // results: expect.arrayContaining([agreement8, agreement11]), - // }); - // }); + it("should get agreements for a delegated eservice with filters: producerId and requester is producer delegate", async () => { + const agreements = await agreementService.getAgreements( + { + producerId: eservice1.producerId, + }, + 10, + 0, + { + authData: getRandomAuthData(delegateProducer1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements, [agreement1, agreement2]); + }); + + it("should get agreements for a delegated eservice with filters: consumerId and requester is consumer delegate", async () => { + const agreements = await agreementService.getAgreements( + { + consumerId: tenant1.id, + }, + 10, + 0, + { + authData: getRandomAuthData(delegateConsumer1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult(agreements, [agreement5]); + }); }); From 28f3e5db61d77e4eb15cb8b8aa45d9fab5fa66b0 Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Wed, 19 Feb 2025 18:20:33 +0100 Subject: [PATCH 07/11] Adding checks also to all other list calls - tests still to be fixed --- .../src/routers/AgreementRouter.ts | 15 ++-- .../src/services/agreementService.ts | 44 +++++++----- .../src/services/readModelService.ts | 68 ++++++++++++------- .../api-clients/open-api/agreementApi.yml | 15 +--- packages/api-clients/open-api/bffApi.yml | 17 ++--- .../src/routers/agreementRouter.ts | 11 ++- .../src/services/agreementService.ts | 27 ++++---- 7 files changed, 99 insertions(+), 98 deletions(-) diff --git a/packages/agreement-process/src/routers/AgreementRouter.ts b/packages/agreement-process/src/routers/AgreementRouter.ts index 7144f1fafb..46b4f13f42 100644 --- a/packages/agreement-process/src/routers/AgreementRouter.ts +++ b/packages/agreement-process/src/routers/AgreementRouter.ts @@ -411,11 +411,11 @@ const agreementRouter = ( const ctx = fromAppContext(req.ctx); try { - const producers = await agreementService.getAgreementProducers( + const producers = await agreementService.getAgreementsProducers( req.query.producerName, req.query.limit, req.query.offset, - ctx.logger + ctx ); return res.status(200).send( @@ -448,11 +448,11 @@ const agreementRouter = ( const ctx = fromAppContext(req.ctx); try { - const consumers = await agreementService.getAgreementConsumers( + const consumers = await agreementService.getAgreementsConsumers( req.query.consumerName, req.query.limit, req.query.offset, - ctx.logger + ctx ); return res.status(200).send( @@ -709,18 +709,15 @@ const agreementRouter = ( const ctx = fromAppContext(req.ctx); try { - const eservices = await agreementService.getAgreementEServices( + const eservices = await agreementService.getAgreementsEServices( { eserviceName: req.query.eServiceName, consumerIds: req.query.consumersIds.map(unsafeBrandId), producerIds: req.query.producersIds.map(unsafeBrandId), - agreeementStates: req.query.states.map( - apiAgreementStateToAgreementState - ), }, req.query.limit, req.query.offset, - ctx.logger + ctx ); return res.status(200).send( diff --git a/packages/agreement-process/src/services/agreementService.ts b/packages/agreement-process/src/services/agreementService.ts index de6472d7ce..61aee51fc9 100644 --- a/packages/agreement-process/src/services/agreementService.ts +++ b/packages/agreement-process/src/services/agreementService.ts @@ -320,33 +320,41 @@ export function agreementServiceBuilder( return agreement; }, - async getAgreementProducers( + async getAgreementsProducers( producerName: string | undefined, limit: number, offset: number, - logger: Logger + { authData, logger }: WithLogger ): Promise> { logger.info( `Retrieving producers from agreements with producer name ${producerName}` ); - // No need to assert requester permissions here, as this endpoint - // retrieves producer information from agreements without exposing any - // agreement data. - return await readModelService.getProducers(producerName, limit, offset); + + // Permissions are checked in the readModelService + return await readModelService.getAgreementsProducers( + authData.organizationId, + producerName, + limit, + offset + ); }, - async getAgreementConsumers( + async getAgreementsConsumers( consumerName: string | undefined, limit: number, offset: number, - logger: Logger + { authData, logger }: WithLogger ): Promise> { logger.info( `Retrieving consumers from agreements with consumer name ${consumerName}` ); - // No need to assert requester permissions here, as this endpoint - // retrieves consumer information from agreements without exposing any - // agreement data. - return await readModelService.getConsumers(consumerName, limit, offset); + + // Permissions are checked in the readModelService + return await readModelService.getAgreementsConsumers( + authData.organizationId, + consumerName, + limit, + offset + ); }, async updateAgreement( agreementId: AgreementId, @@ -963,19 +971,19 @@ export function agreementServiceBuilder( return updatedAgreement; }, - async getAgreementEServices( + async getAgreementsEServices( filters: AgreementEServicesQueryFilters, limit: number, offset: number, - logger: Logger + { authData, logger }: WithLogger ): Promise> { logger.info( - `Retrieving EServices with consumers ${filters.consumerIds}, producers ${filters.producerIds}, states ${filters.agreeementStates}, offset ${offset}, limit ${limit} and name matching ${filters.eserviceName}` + `Retrieving EServices from agreements with consumers ${filters.consumerIds}, producers ${filters.producerIds}, offset ${offset}, limit ${limit} and name matching ${filters.eserviceName}` ); - // No need to assert requester permissions here, as this endpoint - // retrieves e-service information from agreements without exposing any - // agreement data. + + // Permissions are checked in the readModelService return await readModelService.getAgreementsEServices( + authData.organizationId, filters, limit, offset diff --git a/packages/agreement-process/src/services/readModelService.ts b/packages/agreement-process/src/services/readModelService.ts index 759c906e8e..ec40bfbd10 100644 --- a/packages/agreement-process/src/services/readModelService.ts +++ b/packages/agreement-process/src/services/readModelService.ts @@ -56,7 +56,6 @@ export type AgreementEServicesQueryFilters = { eserviceName: string | undefined; consumerIds: TenantId[]; producerIds: TenantId[]; - agreeementStates: AgreementState[]; }; type AgreementDataFields = RemoveDataPrefix>; @@ -280,16 +279,17 @@ async function getDelegation( // eslint-disable-next-line max-params async function searchTenantsByName( + requesterId: TenantId, agreements: AgreementCollection, tenantName: string | undefined, tenantIdField: "producerId" | "consumerId", limit: number, offset: number ): Promise> { - const aggregationPipeline = getTenantsByNamePipeline( - tenantName, - tenantIdField - ); + const aggregationPipeline = [ + ...getAgreementsPipeline(requesterId), + ...getTenantsByNamePipeline(tenantName, tenantIdField), + ]; const data = await agreements .aggregate([...aggregationPipeline, { $skip: offset }, { $limit: limit }], { @@ -459,6 +459,17 @@ function applyVisibilityToAgreements(requesterId: TenantId): Document { }; } +const getAgreementsPipeline = ( + requesterId: TenantId, + producerIds: TenantId[] = [], + consumerIds: TenantId[] = [] +): Document[] => [ + ...addDelegationDataPipeline, + ...getProducerOrDelegateFilter(producerIds), + ...getConsumerOrDelegateFilter(consumerIds), + applyVisibilityToAgreements(requesterId), +]; + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function readModelServiceBuilder( readModelRepository: ReadModelRepository @@ -488,11 +499,8 @@ export function readModelServiceBuilder( const agreementsData = await agreements .aggregate( [ - ...addDelegationDataPipeline, - ...getProducerOrDelegateFilter(producerIds), - ...getConsumerOrDelegateFilter(consumerIds), + ...getAgreementsPipeline(requesterId, producerIds, consumerIds), getAgreementsFilters(otherFilters), - applyVisibilityToAgreements(requesterId), ], { allowDiskUse: true, @@ -641,38 +649,48 @@ export function readModelServiceBuilder( async getAttributeById(id: AttributeId): Promise { return getAttribute(attributes, { "data.id": id }); }, - async getConsumers( + async getAgreementsConsumers( + requesterId: TenantId, name: string | undefined, limit: number, offset: number ): Promise> { - return searchTenantsByName(agreements, name, "consumerId", limit, offset); + return searchTenantsByName( + requesterId, + agreements, + name, + "consumerId", + limit, + offset + ); }, - async getProducers( + async getAgreementsProducers( + requesterId: TenantId, name: string | undefined, limit: number, offset: number ): Promise> { - return searchTenantsByName(agreements, name, "producerId", limit, offset); + return searchTenantsByName( + requesterId, + agreements, + name, + "producerId", + limit, + offset + ); }, async getAgreementsEServices( + requesterId: TenantId, filters: AgreementEServicesQueryFilters, limit: number, offset: number ): Promise> { - const agreementFilter = { - ...(filters.agreeementStates.length === 0 - ? undefined - : { "data.state": { $in: filters.agreeementStates } }), - }; - const agreementAggregationPipeline = [ - ...addDelegationDataPipeline, - ...getProducerOrDelegateFilter(filters.producerIds), - ...getConsumerOrDelegateFilter(filters.consumerIds), - { - $match: agreementFilter, - }, + ...getAgreementsPipeline( + requesterId, + filters.producerIds, + filters.consumerIds + ), { $group: { _id: "$data.eserviceId", diff --git a/packages/api-clients/open-api/agreementApi.yml b/packages/api-clients/open-api/agreementApi.yml index 5f6b30626c..186c1d0a19 100644 --- a/packages/api-clients/open-api/agreementApi.yml +++ b/packages/api-clients/open-api/agreementApi.yml @@ -523,7 +523,7 @@ paths: - agreement summary: Retrieves Tenants that are producers with existing Agreements description: Retrieves Tenants that are producers with existing Agreements - operationId: getAgreementProducers + operationId: getAgreementsProducers parameters: - in: query name: producerName @@ -566,7 +566,7 @@ paths: - agreement summary: Retrieves Tenants that are consumers with existing Agreements description: Retrieves Tenants that are consumers with existing Agreements - operationId: getAgreementConsumers + operationId: getAgreementsConsumers parameters: - in: query name: consumerName @@ -826,7 +826,7 @@ paths: - agreement summary: Retrieves agreements eservices description: Retrieves agreements eservices - operationId: getAgreementEServices + operationId: getAgreementsEServices parameters: - in: query name: eServiceName @@ -853,15 +853,6 @@ paths: format: uuid default: [] explode: false - - in: query - name: states - description: comma separated sequence of states - schema: - type: array - items: - $ref: "#/components/schemas/AgreementState" - default: [] - explode: false - in: query name: offset required: true diff --git a/packages/api-clients/open-api/bffApi.yml b/packages/api-clients/open-api/bffApi.yml index 51cfa2988d..3b02a524a2 100644 --- a/packages/api-clients/open-api/bffApi.yml +++ b/packages/api-clients/open-api/bffApi.yml @@ -434,7 +434,7 @@ paths: - agreements summary: Retrieves Tenants that are producers with existing Agreements description: Retrieves Tenants that are producers with existing Agreements - operationId: getAgreementProducers + operationId: getAgreementsProducers parameters: - in: query name: q @@ -522,7 +522,7 @@ paths: - agreements summary: Retrieves Tenants that are consumers with existing Agreements description: Retrieves Tenants that are consumers with existing Agreements - operationId: getAgreementConsumers + operationId: getAgreementsConsumers parameters: - in: query name: q @@ -5389,22 +5389,13 @@ paths: - agreements summary: Retrieves eservices for producers in agreements description: Retrieves eservices for producers in agreements - operationId: getAgreementEServiceProducers + operationId: getAgreementsProducerEServices parameters: - in: query name: q description: Query to filter EServices by name schema: type: string - - in: query - name: states - description: comma separated sequence of states - schema: - type: array - items: - $ref: "#/components/schemas/AgreementState" - default: [] - explode: false - in: query name: offset required: true @@ -5505,7 +5496,7 @@ paths: - agreements summary: Retrieves eservices for consumers in agreements description: Retrieves eservices for consumers in agreements - operationId: getAgreementEServiceConsumers + operationId: getAgreementsConsumerEServices parameters: - in: query name: q diff --git a/packages/backend-for-frontend/src/routers/agreementRouter.ts b/packages/backend-for-frontend/src/routers/agreementRouter.ts index b9b4e5f608..054b94a602 100644 --- a/packages/backend-for-frontend/src/routers/agreementRouter.ts +++ b/packages/backend-for-frontend/src/routers/agreementRouter.ts @@ -126,14 +126,13 @@ const agreementRouter = ( .get("/producers/agreements/eservices", async (req, res) => { const ctx = fromBffAppContext(req.ctx, req.headers); - const { offset, limit, states, q } = req.query; + const { offset, limit, q } = req.query; try { const requesterId = ctx.authData.organizationId; - const result = await agreementService.getAgreementsEserviceProducers( + const result = await agreementService.getAgreementsProducerEServices( { offset, limit, - states, requesterId, eServiceName: q, }, @@ -159,7 +158,7 @@ const agreementRouter = ( const { offset, limit, q } = req.query; try { const requesterId = ctx.authData.organizationId; - const result = await agreementService.getAgreementsEserviceConsumers( + const result = await agreementService.getAgreementsConsumerEServices( { offset, limit, @@ -187,7 +186,7 @@ const agreementRouter = ( const { offset, limit, q } = req.query; try { - const result = await agreementService.getAgreementProducers( + const result = await agreementService.getAgreementsProducers( { offset, limit, @@ -213,7 +212,7 @@ const agreementRouter = ( const { offset, limit, q } = req.query; try { - const result = await agreementService.getAgreementConsumers( + const result = await agreementService.getAgreementsConsumers( { offset, limit, diff --git a/packages/backend-for-frontend/src/services/agreementService.ts b/packages/backend-for-frontend/src/services/agreementService.ts index 23681bad18..18e7291ff8 100644 --- a/packages/backend-for-frontend/src/services/agreementService.ts +++ b/packages/backend-for-frontend/src/services/agreementService.ts @@ -422,37 +422,34 @@ export function agreementServiceBuilder( return { id: agreement.id }; }, - async getAgreementsEserviceProducers( + async getAgreementsProducerEServices( { offset, limit, requesterId, - states, eServiceName, }: { offset: number; limit: number; requesterId: string; - states: agreementApi.AgreementState[]; eServiceName?: string; }, { headers, logger }: WithLogger ): Promise { logger.info( - `Retrieving producer eservices from agreement filtered by eservice name ${eServiceName}, offset ${offset}, limit ${limit}` + `Retrieving producer eservices from agreements filtered by eservice name ${eServiceName}, offset ${offset}, limit ${limit}` ); if (eServiceName && eServiceName.length < 3) { return emptyPagination(offset, limit); } - const eservices = await agreementProcessClient.getAgreementEServices({ + const eservices = await agreementProcessClient.getAgreementsEServices({ queries: { offset, limit, eServiceName, producersIds: [requesterId], - states, }, headers, }); @@ -467,7 +464,7 @@ export function agreementServiceBuilder( }; }, - async getAgreementsEserviceConsumers( + async getAgreementsConsumerEServices( { offset, limit, @@ -482,14 +479,14 @@ export function agreementServiceBuilder( { headers, logger }: WithLogger ) { logger.info( - `Retrieving consumer eservices from agreement filtered by eservice name ${eServiceName}, offset ${offset}, limit ${limit}` + `Retrieving consumer eservices from agreements filtered by eservice name ${eServiceName}, offset ${offset}, limit ${limit}` ); if (eServiceName && eServiceName.length < 3) { return emptyPagination(offset, limit); } - const eservices = await agreementProcessClient.getAgreementEServices({ + const eservices = await agreementProcessClient.getAgreementsEServices({ queries: { offset, limit, @@ -509,7 +506,7 @@ export function agreementServiceBuilder( }; }, - async getAgreementProducers( + async getAgreementsProducers( { offset, limit, @@ -517,13 +514,13 @@ export function agreementServiceBuilder( }: { offset: number; limit: number; producerName?: string }, { logger, headers }: WithLogger ): Promise { - logger.info(`Retrieving agreement producers`); + logger.info(`Retrieving producers from agreements`); if (producerName && producerName.length < 3) { return emptyPagination(offset, limit); } - const producers = await agreementProcessClient.getAgreementProducers({ + const producers = await agreementProcessClient.getAgreementsProducers({ queries: { offset, limit, @@ -542,7 +539,7 @@ export function agreementServiceBuilder( }; }, - async getAgreementConsumers( + async getAgreementsConsumers( { offset, limit, @@ -550,13 +547,13 @@ export function agreementServiceBuilder( }: { offset: number; limit: number; consumerName?: string }, { logger, headers }: WithLogger ): Promise { - logger.info(`Retrieving agreement consumers`); + logger.info(`Retrieving consumers from agreements`); if (consumerName && consumerName.length < 3) { return emptyPagination(offset, limit); } - const consumers = await agreementProcessClient.getAgreementConsumers({ + const consumers = await agreementProcessClient.getAgreementsConsumers({ queries: { offset, limit, From 2f7cccd020a8c24ebcb44fb87e7333a95f3bed3d Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Thu, 20 Feb 2025 15:26:36 +0100 Subject: [PATCH 08/11] getAgreementsEservices test --- .../getAgreementConsumersOrProducers.test.ts | 254 --------- .../test/getAgreementEservices.test.ts | 343 ------------ .../test/getAgreements.test.ts | 13 +- .../test/getAgreementsEservices.test.ts | 510 ++++++++++++++++++ packages/agreement-process/test/utils.ts | 12 + 5 files changed, 523 insertions(+), 609 deletions(-) delete mode 100644 packages/agreement-process/test/getAgreementConsumersOrProducers.test.ts delete mode 100644 packages/agreement-process/test/getAgreementEservices.test.ts create mode 100644 packages/agreement-process/test/getAgreementsEservices.test.ts diff --git a/packages/agreement-process/test/getAgreementConsumersOrProducers.test.ts b/packages/agreement-process/test/getAgreementConsumersOrProducers.test.ts deleted file mode 100644 index ed620cbd0c..0000000000 --- a/packages/agreement-process/test/getAgreementConsumersOrProducers.test.ts +++ /dev/null @@ -1,254 +0,0 @@ -/* eslint-disable functional/no-let */ -import { genericLogger } from "pagopa-interop-commons"; -import { - getMockTenant, - getMockAgreement, -} from "pagopa-interop-commons-test/index.js"; -import { Tenant } from "pagopa-interop-models"; -import { describe, beforeEach, it, expect } from "vitest"; -import { CompactOrganization } from "../src/model/domain/models.js"; -import { addOneTenant, addOneAgreement, agreementService } from "./utils.js"; - -describe("get agreement consumers / producers", () => { - let tenant1: Tenant; - let tenant2: Tenant; - let tenant3: Tenant; - let tenant4: Tenant; - let tenant5: Tenant; - let tenant6: Tenant; - - const toCompactOrganization = (tenant: Tenant): CompactOrganization => ({ - id: tenant.id, - name: tenant.name, - }); - - beforeEach(async () => { - tenant1 = { ...getMockTenant(), name: "Tenant 1 Foo" }; - tenant2 = { ...getMockTenant(), name: "Tenant 2 Bar" }; - tenant3 = { ...getMockTenant(), name: "Tenant 3 FooBar" }; - tenant4 = { ...getMockTenant(), name: "Tenant 4 Baz" }; - tenant5 = { ...getMockTenant(), name: "Tenant 5 BazBar" }; - tenant6 = { ...getMockTenant(), name: "Tenant 6 BazFoo" }; - - await addOneTenant(tenant1); - await addOneTenant(tenant2); - await addOneTenant(tenant3); - await addOneTenant(tenant4); - await addOneTenant(tenant5); - await addOneTenant(tenant6); - - const agreement1 = { - ...getMockAgreement(), - producerId: tenant1.id, - consumerId: tenant2.id, - }; - - const agreement2 = { - ...getMockAgreement(), - producerId: tenant1.id, - consumerId: tenant3.id, - }; - - const agreement3 = { - ...getMockAgreement(), - producerId: tenant2.id, - consumerId: tenant4.id, - }; - - const agreement4 = { - ...getMockAgreement(), - producerId: tenant2.id, - consumerId: tenant5.id, - }; - - const agreement5 = { - ...getMockAgreement(), - producerId: tenant3.id, - consumerId: tenant6.id, - }; - - await addOneAgreement(agreement1); - await addOneAgreement(agreement2); - await addOneAgreement(agreement3); - await addOneAgreement(agreement4); - await addOneAgreement(agreement5); - }); - describe("get agreement consumers", () => { - it("should get all agreement consumers", async () => { - const consumers = await agreementService.getAgreementConsumers( - undefined, - 10, - 0, - genericLogger - ); - - expect(consumers).toEqual({ - totalCount: 5, - results: expect.arrayContaining( - [tenant2, tenant3, tenant4, tenant5, tenant6].map( - toCompactOrganization - ) - ), - }); - }); - it("should get agreement consumers filtered by name", async () => { - const consumers = await agreementService.getAgreementConsumers( - "Foo", - 10, - 0, - genericLogger - ); - - expect(consumers).toEqual({ - totalCount: 2, - results: expect.arrayContaining( - [tenant3, tenant6].map(toCompactOrganization) - ), - }); - }); - it("should get agreement consumers with limit", async () => { - const consumers = await agreementService.getAgreementConsumers( - undefined, - 2, - 0, - genericLogger - ); - - expect(consumers).toEqual({ - totalCount: 5, - results: expect.arrayContaining( - [tenant2, tenant3].map(toCompactOrganization) - ), - }); - }); - it("should get agreement consumers with offset and limit", async () => { - const consumers = await agreementService.getAgreementConsumers( - undefined, - 2, - 1, - genericLogger - ); - - expect(consumers).toEqual({ - totalCount: 5, - results: expect.arrayContaining( - [tenant3, tenant4].map(toCompactOrganization) - ), - }); - }); - it("should get agreement consumers with offset, limit, and name filter", async () => { - const consumers = await agreementService.getAgreementConsumers( - "Foo", - 1, - 1, - genericLogger - ); - - expect(consumers).toEqual({ - totalCount: 2, - results: expect.arrayContaining([tenant6].map(toCompactOrganization)), - }); - }); - it("should get no agreement consumers in case no filters match", async () => { - const producers = await agreementService.getAgreementConsumers( - "Not existing name", - 10, - 0, - genericLogger - ); - - expect(producers).toEqual({ - totalCount: 0, - results: [], - }); - }); - }); - describe("get agreement producers", () => { - it("should get all agreement producers", async () => { - const producers = await agreementService.getAgreementProducers( - undefined, - 10, - 0, - genericLogger - ); - - expect(producers).toEqual({ - totalCount: 3, - results: expect.arrayContaining( - [tenant1, tenant2, tenant3].map(toCompactOrganization) - ), - }); - }); - it("should get agreement producers filtered by name", async () => { - const producers = await agreementService.getAgreementProducers( - "Bar", - 10, - 0, - genericLogger - ); - - expect(producers).toEqual({ - totalCount: 2, - results: expect.arrayContaining( - [tenant2, tenant3].map(toCompactOrganization) - ), - }); - }); - it("should get agreement producers with limit", async () => { - const producers = await agreementService.getAgreementProducers( - undefined, - 2, - 0, - genericLogger - ); - - expect(producers).toEqual({ - totalCount: 3, - results: expect.arrayContaining( - [tenant1, tenant2].map(toCompactOrganization) - ), - }); - }); - it("should get agreement producers with offset and limit", async () => { - const producers = await agreementService.getAgreementProducers( - undefined, - 2, - 1, - genericLogger - ); - - expect(producers).toEqual({ - totalCount: 3, - results: expect.arrayContaining( - [tenant2, tenant3].map(toCompactOrganization) - ), - }); - }); - it("should get agreement producers with offset, limit, and name filter", async () => { - const producers = await agreementService.getAgreementProducers( - "Bar", - 1, - 1, - genericLogger - ); - - expect(producers).toEqual({ - totalCount: 2, - results: expect.arrayContaining([tenant3].map(toCompactOrganization)), - }); - }); - it("should get no agreement producers in case no filters match", async () => { - const producers = await agreementService.getAgreementProducers( - "Not existing name", - 10, - 0, - genericLogger - ); - - expect(producers).toEqual({ - totalCount: 0, - results: [], - }); - }); - }); -}); diff --git a/packages/agreement-process/test/getAgreementEservices.test.ts b/packages/agreement-process/test/getAgreementEservices.test.ts deleted file mode 100644 index 5208f1af06..0000000000 --- a/packages/agreement-process/test/getAgreementEservices.test.ts +++ /dev/null @@ -1,343 +0,0 @@ -/* eslint-disable functional/no-let */ -import { genericLogger } from "pagopa-interop-commons"; -import { - getMockTenant, - getMockEService, - getMockAgreement, -} from "pagopa-interop-commons-test/index.js"; -import { - EService, - Tenant, - generateId, - EServiceId, - agreementState, -} from "pagopa-interop-models"; -import { describe, beforeEach, it, expect } from "vitest"; -import { CompactEService } from "../src/model/domain/models.js"; -import { - addOneTenant, - addOneEService, - addOneAgreement, - agreementService, -} from "./utils.js"; - -describe("get agreement eservices", () => { - let eservice1: EService; - let eservice2: EService; - let eservice3: EService; - let eservice4: EService; - - let tenant1: Tenant; - let tenant2: Tenant; - let tenant3: Tenant; - - const toCompactEService = (eservice: EService): CompactEService => ({ - id: eservice.id, - name: eservice.name, - }); - - beforeEach(async () => { - tenant1 = getMockTenant(); - tenant2 = getMockTenant(); - tenant3 = getMockTenant(); - - eservice1 = { - ...getMockEService(generateId(), tenant1.id), - name: "EService 1 Foo", - }; - eservice2 = { - ...getMockEService(generateId(), tenant2.id), - name: "EService 2 Bar", - }; - eservice3 = { - ...getMockEService(generateId(), tenant3.id), - name: "EService 3 FooBar", - }; - eservice4 = { - ...getMockEService(generateId(), tenant3.id), - name: "EService 4 FooBar", - }; - - await addOneTenant(tenant1); - await addOneTenant(tenant2); - await addOneTenant(tenant3); - await addOneEService(eservice1); - await addOneEService(eservice2); - await addOneEService(eservice3); - await addOneEService(eservice4); - - const agreement1 = { - ...getMockAgreement(eservice1.id), - producerId: eservice1.producerId, - consumerId: tenant2.id, - state: agreementState.draft, - }; - const agreement2 = { - ...getMockAgreement(eservice2.id), - producerId: eservice2.producerId, - consumerId: tenant3.id, - state: agreementState.active, - }; - - const agreement3 = { - ...getMockAgreement(eservice3.id), - producerId: eservice3.producerId, - consumerId: tenant1.id, - state: agreementState.pending, - }; - const agreement4 = { - ...getMockAgreement(eservice4.id), - producerId: eservice4.producerId, - consumerId: tenant3.id, - state: agreementState.draft, - }; - - await addOneAgreement(agreement1); - await addOneAgreement(agreement2); - await addOneAgreement(agreement3); - await addOneAgreement(agreement4); - }); - - it("should get all agreement eservices", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: undefined, - consumerIds: [], - producerIds: [], - agreeementStates: [], - }, - 10, - 0, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 4, - results: expect.arrayContaining( - [eservice1, eservice2, eservice3, eservice4].map(toCompactEService) - ), - }); - }); - - it("should get agreement eservices filtered by name", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: "Foo", - consumerIds: [], - producerIds: [], - agreeementStates: [], - }, - 10, - 0, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 3, - results: expect.arrayContaining( - [eservice1, eservice3, eservice4].map(toCompactEService) - ), - }); - }); - - it("should get agreement eservices filtered by consumerId", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: undefined, - consumerIds: [tenant2.id, tenant3.id], - producerIds: [], - agreeementStates: [], - }, - 10, - 0, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 3, - results: expect.arrayContaining( - [eservice1, eservice2, eservice4].map(toCompactEService) - ), - }); - }); - - it("should get agreement eservices filtered by producerId", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: undefined, - consumerIds: [], - producerIds: [tenant1.id, tenant2.id], - agreeementStates: [], - }, - 10, - 0, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 2, - results: expect.arrayContaining( - [eservice1, eservice2].map(toCompactEService) - ), - }); - }); - - it("should get agreement eservices filtered by agreement state", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: undefined, - consumerIds: [], - producerIds: [], - agreeementStates: [agreementState.active, agreementState.pending], - }, - 10, - 0, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 2, - results: expect.arrayContaining( - [eservice2, eservice3].map(toCompactEService) - ), - }); - }); - - it("should get agreement eservices with filters: name, consumerId, producerId", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: "Foo", - consumerIds: [tenant2.id], - producerIds: [tenant1.id], - agreeementStates: [], - }, - 10, - 0, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 1, - results: expect.arrayContaining([eservice1].map(toCompactEService)), - }); - }); - - it("should get agreement eservices with filters: name, agreement state", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: "Bar", - consumerIds: [], - producerIds: [], - agreeementStates: [agreementState.pending, agreementState.draft], - }, - 10, - 0, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 2, - results: expect.arrayContaining([eservice3].map(toCompactEService)), - }); - }); - - it("should get agreement eservices with filters: name, consumerId, producerId, agreement state", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: "Bar", - consumerIds: [tenant1.id], - producerIds: [tenant3.id], - agreeementStates: [agreementState.pending], - }, - 10, - 0, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 1, - results: expect.arrayContaining([eservice3].map(toCompactEService)), - }); - }); - - it("should get agreement eservices with limit", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: undefined, - consumerIds: [], - producerIds: [], - agreeementStates: [], - }, - 2, - 0, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 4, - results: expect.arrayContaining( - [eservice1, eservice2].map(toCompactEService) - ), - }); - }); - - it("should get agreement eservices with offset and limit", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: undefined, - consumerIds: [], - producerIds: [], - agreeementStates: [], - }, - 2, - 1, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 4, - results: expect.arrayContaining( - [eservice2, eservice3].map(toCompactEService) - ), - }); - }); - - it("should get no agreement eservices in case no filters match", async () => { - const eservices = await agreementService.getAgreementEServices( - { - eserviceName: "Not existing name", - consumerIds: [], - producerIds: [], - agreeementStates: [], - }, - 10, - 0, - genericLogger - ); - - expect(eservices).toEqual({ - totalCount: 0, - results: [], - }); - }); - - it("should get agreement eservice for a delegated eservice with filters: producerId", async () => { - const agreements1 = await agreementService.getAgreementEServices( - { - producerIds: [eservice4.producerId], - eserviceName: undefined, - consumerIds: [], - agreeementStates: [], - }, - 10, - 0, - genericLogger - ); - expect(agreements1).toEqual({ - totalCount: 2, - results: expect.arrayContaining( - [eservice3, eservice4].map(toCompactEService) - ), - }); - }); -}); diff --git a/packages/agreement-process/test/getAgreements.test.ts b/packages/agreement-process/test/getAgreements.test.ts index 87c86b83f3..c493fa305b 100644 --- a/packages/agreement-process/test/getAgreements.test.ts +++ b/packages/agreement-process/test/getAgreements.test.ts @@ -20,7 +20,6 @@ import { agreementState, delegationKind, delegationState, - ListResult, TenantId, } from "pagopa-interop-models"; import { describe, beforeEach, it, expect } from "vitest"; @@ -30,19 +29,9 @@ import { addOneAgreement, agreementService, addOneDelegation, + expectSinglePageListResult, } from "./utils.js"; -function expectSinglePageListResult( - actual: ListResult, - expected: Agreement[] -): void { - expect(actual).toEqual({ - totalCount: expected.length, - results: expect.arrayContaining(expected), - }); - expect(actual.results).toHaveLength(expected.length); -} - describe("get agreements", () => { let tenant1: Tenant; let tenant2: Tenant; diff --git a/packages/agreement-process/test/getAgreementsEservices.test.ts b/packages/agreement-process/test/getAgreementsEservices.test.ts new file mode 100644 index 0000000000..48e108a4dc --- /dev/null +++ b/packages/agreement-process/test/getAgreementsEservices.test.ts @@ -0,0 +1,510 @@ +/* eslint-disable functional/no-let */ +import { genericLogger } from "pagopa-interop-commons"; +import { + getMockTenant, + getMockEService, + getMockAgreement, + getRandomAuthData, + getMockDelegation, +} from "pagopa-interop-commons-test/index.js"; +import { + EService, + Tenant, + generateId, + EServiceId, + delegationKind, + delegationState, +} from "pagopa-interop-models"; +import { describe, beforeEach, it, expect } from "vitest"; +import { CompactEService } from "../src/model/domain/models.js"; +import { + addOneTenant, + addOneEService, + addOneAgreement, + agreementService, + addOneDelegation, + expectSinglePageListResult, +} from "./utils.js"; + +describe("get agreement eservices", () => { + let eservice1: EService; + let eservice2: EService; + let eservice3: EService; + let eservice4: EService; + + let tenant1: Tenant; + let tenant2: Tenant; + let tenant3: Tenant; + let delegateProducer1: Tenant; + let delegateConsumer1: Tenant; + let delegateConsumer2: Tenant; + + const toCompactEService = (eservice: EService): CompactEService => ({ + id: eservice.id, + name: eservice.name, + }); + + beforeEach(async () => { + tenant1 = getMockTenant(); + tenant2 = getMockTenant(); + tenant3 = getMockTenant(); + delegateProducer1 = getMockTenant(); + delegateConsumer1 = getMockTenant(); + delegateConsumer2 = getMockTenant(); + + eservice1 = { + ...getMockEService(generateId(), tenant1.id), + name: "EService 1 Foo", + }; + eservice2 = { + ...getMockEService(generateId(), tenant2.id), + name: "EService 2 Bar", + }; + eservice3 = { + ...getMockEService(generateId(), tenant3.id), + name: "EService 3 FooBar", + }; + eservice4 = { + ...getMockEService(generateId(), tenant3.id), + name: "EService 4 FooBar", + }; + + await addOneTenant(tenant1); + await addOneTenant(tenant2); + await addOneTenant(tenant3); + await addOneTenant(delegateProducer1); + await addOneTenant(delegateConsumer1); + await addOneTenant(delegateConsumer2); + await addOneEService(eservice1); + await addOneEService(eservice2); + await addOneEService(eservice3); + await addOneEService(eservice4); + + const agreement1 = { + ...getMockAgreement(eservice1.id), + producerId: eservice1.producerId, + consumerId: tenant2.id, + }; + const agreement2 = { + ...getMockAgreement(eservice2.id), + producerId: eservice2.producerId, + consumerId: tenant3.id, + }; + + const agreement3 = { + ...getMockAgreement(eservice3.id), + producerId: eservice3.producerId, + consumerId: tenant1.id, + }; + const agreement4 = { + ...getMockAgreement(eservice4.id), + producerId: eservice4.producerId, + consumerId: tenant3.id, + }; + + const agreement5 = { + ...getMockAgreement(eservice4.id), + consumerId: delegateProducer1.id, + producerId: eservice4.producerId, + }; + + const agreement6 = { + ...getMockAgreement(eservice4.id), + producerId: eservice4.producerId, + consumerId: delegateConsumer1.id, + }; + + const agreement7 = { + ...getMockAgreement(eservice2.id), + producerId: eservice2.producerId, + consumerId: delegateConsumer2.id, + }; + + await addOneAgreement(agreement1); + await addOneAgreement(agreement2); + await addOneAgreement(agreement3); + await addOneAgreement(agreement4); + await addOneAgreement(agreement5); + await addOneAgreement(agreement6); + await addOneAgreement(agreement7); + + const producerDelegation1 = getMockDelegation({ + kind: delegationKind.delegatedProducer, + delegateId: delegateProducer1.id, + delegatorId: eservice1.producerId, + eserviceId: eservice1.id, + state: delegationState.active, + }); + const consumerDelegation1 = getMockDelegation({ + kind: delegationKind.delegatedConsumer, + delegateId: delegateConsumer1.id, + delegatorId: tenant1.id, + eserviceId: eservice3.id, + state: delegationState.active, + }); + const consumerDelegation2 = getMockDelegation({ + kind: delegationKind.delegatedConsumer, + delegateId: delegateConsumer2.id, + delegatorId: tenant2.id, + eserviceId: eservice1.id, + state: delegationState.active, + }); + + // These delegations are revoked: the delegates + // should not see the corresponding agreements + const revokedProducerDelegation = getMockDelegation({ + kind: delegationKind.delegatedProducer, + delegateId: delegateProducer1.id, + delegatorId: eservice2.producerId, + eserviceId: eservice2.id, + state: delegationState.revoked, + }); + const revokedConsumerDelegation = getMockDelegation({ + kind: delegationKind.delegatedConsumer, + delegateId: delegateConsumer1.id, + delegatorId: tenant2.id, + eserviceId: eservice3.id, + state: delegationState.revoked, + }); + + await addOneDelegation(producerDelegation1); + await addOneDelegation(consumerDelegation1); + await addOneDelegation(consumerDelegation2); + await addOneDelegation(revokedProducerDelegation); + await addOneDelegation(revokedConsumerDelegation); + }); + + it("should get all agreements eservices for agreements visible to consumer/producer requester if no filters are provided", async () => { + const resultsForTenant1 = await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + consumerIds: [], + producerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult( + resultsForTenant1, + [eservice1, eservice3].map(toCompactEService) + ); + + const resultsForTenant2 = await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + consumerIds: [], + producerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult( + resultsForTenant2, + [eservice1, eservice2].map(toCompactEService) + ); + + const resultsForTenant3 = await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + consumerIds: [], + producerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant3.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult( + resultsForTenant3, + [eservice2, eservice3, eservice4].map(toCompactEService) + ); + }); + + it("should get all agreements eservices for agreements visible to delegate producer requester if no filters are provided", async () => { + const resultsForDelegateProducer1 = + await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + consumerIds: [], + producerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(delegateProducer1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult( + resultsForDelegateProducer1, + [eservice1, eservice4].map(toCompactEService) + ); + }); + + it("should get all agreements eservices for agreements visible to delegate consumer requester if no filters are provided", async () => { + const resultsForDelegateConsumer1 = + await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + consumerIds: [], + producerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(delegateConsumer1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult( + resultsForDelegateConsumer1, + [eservice3, eservice4].map(toCompactEService) + ); + + const resultsForDelegateConsumer2 = + await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + consumerIds: [], + producerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(delegateConsumer2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + expectSinglePageListResult( + resultsForDelegateConsumer2, + [eservice1, eservice2].map(toCompactEService) + ); + }); + + it("should get agreements eservices filtered by name", async () => { + const eservices = await agreementService.getAgreementsEServices( + { + eserviceName: "Foo", + consumerIds: [], + producerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant3.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult( + eservices, + [eservice3, eservice4].map(toCompactEService) + ); + }); + + it("should get agreement eservices filtered by consumerId", async () => { + const eservices = await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + consumerIds: [delegateConsumer1.id, tenant2.id], + producerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant3.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult( + eservices, + [eservice3, eservice4].map(toCompactEService) + ); + }); + + it("should get agreement eservices filtered by producerId", async () => { + const eservices = await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + producerIds: [tenant1.id], + consumerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult(eservices, [eservice1].map(toCompactEService)); + }); + + it("should get agreement eservices with filters: name, consumerId, producerId", async () => { + const eservices = await agreementService.getAgreementsEServices( + { + eserviceName: "Foo", + consumerIds: [tenant2.id], + producerIds: [tenant1.id], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(eservices).toEqual({ + totalCount: 1, + results: expect.arrayContaining([eservice1].map(toCompactEService)), + }); + }); + + it("should get agreement eservices with limit", async () => { + const eservices = await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + consumerIds: [], + producerIds: [], + }, + 2, + 0, + { + authData: getRandomAuthData(tenant3.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(eservices).toEqual({ + totalCount: 3, + results: expect.arrayContaining( + [eservice2, eservice3].map(toCompactEService) + ), + }); + }); + + it("should get agreement eservices with offset and limit", async () => { + const eservices = await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + consumerIds: [], + producerIds: [], + }, + 2, + 1, + { + authData: getRandomAuthData(tenant3.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(eservices).toEqual({ + totalCount: 3, + results: expect.arrayContaining( + [eservice3, eservice4].map(toCompactEService) + ), + }); + }); + + it("should get no agreement eservices in case no filters match", async () => { + const eservices = await agreementService.getAgreementsEServices( + { + eserviceName: "Not existing name", + consumerIds: [], + producerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult(eservices, []); + }); + + it("should get agreement eservice for a delegated eservice with filters: producerId", async () => { + const eservices = await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + producerIds: [delegateProducer1.id], + consumerIds: [], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult(eservices, [eservice1].map(toCompactEService)); + }); + + it("should get agreement eservice for a delegated agreement with filters: consumerId", async () => { + const eservices = await agreementService.getAgreementsEServices( + { + eserviceName: undefined, + producerIds: [], + consumerIds: [delegateConsumer1.id], + }, + 10, + 0, + { + authData: getRandomAuthData(tenant3.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult( + eservices, + [eservice3, eservice4].map(toCompactEService) + ); + }); +}); diff --git a/packages/agreement-process/test/utils.ts b/packages/agreement-process/test/utils.ts index 8064c279eb..1053cf2490 100644 --- a/packages/agreement-process/test/utils.ts +++ b/packages/agreement-process/test/utils.ts @@ -36,6 +36,7 @@ import { UserId, delegationKind, delegationState, + ListResult, } from "pagopa-interop-models"; import { agreementApi } from "pagopa-interop-api-clients"; import { @@ -371,3 +372,14 @@ export async function addDelegationsAndDelegates({ await addOneTenant(delegateConsumer); } } + +export function expectSinglePageListResult( + actual: ListResult, + expected: T[] +): void { + expect(actual).toEqual({ + totalCount: expected.length, + results: expect.arrayContaining(expected), + }); + expect(actual.results).toHaveLength(expected.length); +} From 6fac181a0d244367aafb55456e68b9417b6c89fc Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Thu, 20 Feb 2025 16:16:39 +0100 Subject: [PATCH 09/11] Fixing tests --- .../test/getAgreements.test.ts | 2 +- .../test/getAgreementsEservices.test.ts | 24 ++++++++----------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/agreement-process/test/getAgreements.test.ts b/packages/agreement-process/test/getAgreements.test.ts index c493fa305b..a94440726c 100644 --- a/packages/agreement-process/test/getAgreements.test.ts +++ b/packages/agreement-process/test/getAgreements.test.ts @@ -720,7 +720,7 @@ describe("get agreements", () => { }); expect(agreements).toEqual({ totalCount: 5, - results: expect.arrayContaining([agreement3, agreement5]), + results: [agreement3, agreement5], }); }); diff --git a/packages/agreement-process/test/getAgreementsEservices.test.ts b/packages/agreement-process/test/getAgreementsEservices.test.ts index 48e108a4dc..5faf7e4923 100644 --- a/packages/agreement-process/test/getAgreementsEservices.test.ts +++ b/packages/agreement-process/test/getAgreementsEservices.test.ts @@ -26,7 +26,7 @@ import { expectSinglePageListResult, } from "./utils.js"; -describe("get agreement eservices", () => { +describe("get agreements eservices", () => { let eservice1: EService; let eservice2: EService; let eservice3: EService; @@ -329,7 +329,7 @@ describe("get agreement eservices", () => { ); }); - it("should get agreement eservices filtered by consumerId", async () => { + it("should get agreements eservices filtered by consumerId", async () => { const eservices = await agreementService.getAgreementsEServices( { eserviceName: undefined, @@ -352,7 +352,7 @@ describe("get agreement eservices", () => { ); }); - it("should get agreement eservices filtered by producerId", async () => { + it("should get agreements eservices filtered by producerId", async () => { const eservices = await agreementService.getAgreementsEServices( { eserviceName: undefined, @@ -372,7 +372,7 @@ describe("get agreement eservices", () => { expectSinglePageListResult(eservices, [eservice1].map(toCompactEService)); }); - it("should get agreement eservices with filters: name, consumerId, producerId", async () => { + it("should get agreements eservices with filters: name, consumerId, producerId", async () => { const eservices = await agreementService.getAgreementsEServices( { eserviceName: "Foo", @@ -391,11 +391,11 @@ describe("get agreement eservices", () => { expect(eservices).toEqual({ totalCount: 1, - results: expect.arrayContaining([eservice1].map(toCompactEService)), + results: [eservice1].map(toCompactEService), }); }); - it("should get agreement eservices with limit", async () => { + it("should get agreements eservices with limit", async () => { const eservices = await agreementService.getAgreementsEServices( { eserviceName: undefined, @@ -414,13 +414,11 @@ describe("get agreement eservices", () => { expect(eservices).toEqual({ totalCount: 3, - results: expect.arrayContaining( - [eservice2, eservice3].map(toCompactEService) - ), + results: [eservice2, eservice3].map(toCompactEService), }); }); - it("should get agreement eservices with offset and limit", async () => { + it("should get agreements eservices with offset and limit", async () => { const eservices = await agreementService.getAgreementsEServices( { eserviceName: undefined, @@ -439,13 +437,11 @@ describe("get agreement eservices", () => { expect(eservices).toEqual({ totalCount: 3, - results: expect.arrayContaining( - [eservice3, eservice4].map(toCompactEService) - ), + results: [eservice3, eservice4].map(toCompactEService), }); }); - it("should get no agreement eservices in case no filters match", async () => { + it("should get no agreements eservices in case no filters match", async () => { const eservices = await agreementService.getAgreementsEServices( { eserviceName: "Not existing name", From 72f86a2e246b87ddb9325b5a440814f5392a7b16 Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Thu, 20 Feb 2025 16:17:54 +0100 Subject: [PATCH 10/11] Adding missing file --- .../getAgreementsConsumersOrProducers.test.ts | 633 ++++++++++++++++++ 1 file changed, 633 insertions(+) create mode 100644 packages/agreement-process/test/getAgreementsConsumersOrProducers.test.ts diff --git a/packages/agreement-process/test/getAgreementsConsumersOrProducers.test.ts b/packages/agreement-process/test/getAgreementsConsumersOrProducers.test.ts new file mode 100644 index 0000000000..08b0f170e6 --- /dev/null +++ b/packages/agreement-process/test/getAgreementsConsumersOrProducers.test.ts @@ -0,0 +1,633 @@ +/* eslint-disable functional/no-let */ +import { genericLogger } from "pagopa-interop-commons"; +import { + getMockTenant, + getMockAgreement, + getRandomAuthData, + getMockDelegation, + getMockEService, +} from "pagopa-interop-commons-test/index.js"; +import { + EServiceId, + Tenant, + delegationKind, + delegationState, + generateId, +} from "pagopa-interop-models"; +import { describe, beforeEach, it, expect } from "vitest"; +import { CompactOrganization } from "../src/model/domain/models.js"; +import { + addOneTenant, + addOneAgreement, + agreementService, + addOneDelegation, + expectSinglePageListResult, +} from "./utils.js"; + +describe("get agreements consumers / producers", () => { + let tenant1: Tenant; + let tenant2: Tenant; + let tenant3: Tenant; + let tenant4: Tenant; + let tenant5: Tenant; + let tenant6: Tenant; + let delegateProducer1: Tenant; + let delegateConsumer1: Tenant; + let delegateConsumer2: Tenant; + + const toCompactOrganization = (tenant: Tenant): CompactOrganization => ({ + id: tenant.id, + name: tenant.name, + }); + + beforeEach(async () => { + tenant1 = { ...getMockTenant(), name: "Tenant 1 Foo" }; + tenant2 = { ...getMockTenant(), name: "Tenant 2 Bar" }; + tenant3 = { ...getMockTenant(), name: "Tenant 3 FooBar" }; + tenant4 = { ...getMockTenant(), name: "Tenant 4 Baz" }; + tenant5 = { ...getMockTenant(), name: "Tenant 5 BazBar" }; + tenant6 = { ...getMockTenant(), name: "Tenant 6 BazFoo" }; + delegateConsumer1 = { + ...getMockTenant(), + name: "Tenant Delegate Consumer 1 Bar", + }; + delegateConsumer2 = { + ...getMockTenant(), + name: "Tenant Delegate Consumer 2 Foo", + }; + delegateProducer1 = { + ...getMockTenant(), + name: "Tenant Delegate Producer 1", + }; + + await addOneTenant(tenant1); + await addOneTenant(tenant2); + await addOneTenant(tenant3); + await addOneTenant(tenant4); + await addOneTenant(tenant5); + await addOneTenant(tenant6); + await addOneTenant(delegateConsumer1); + await addOneTenant(delegateConsumer2); + await addOneTenant(delegateProducer1); + + const eservice1 = { + ...getMockEService(generateId(), tenant1.id), + name: "EService 1 Foo", + }; + const eservice2 = { + ...getMockEService(generateId(), tenant2.id), + name: "EService 2 Bar", + }; + const eservice3 = { + ...getMockEService(generateId(), tenant3.id), + name: "EService 3 FooBar", + }; + const eservice4 = { + ...getMockEService(generateId(), tenant4.id), + name: "EService 4 FooBar", + }; + + const agreement1 = { + ...getMockAgreement(eservice1.id), + producerId: eservice1.producerId, + consumerId: tenant2.id, + }; + + const agreement2 = { + ...getMockAgreement(eservice2.id), + producerId: eservice2.producerId, + consumerId: tenant3.id, + }; + + const agreement3 = { + ...getMockAgreement(eservice3.id), + producerId: eservice3.producerId, + consumerId: tenant4.id, + }; + + const agreement4 = { + ...getMockAgreement(eservice4.id), + producerId: eservice4.producerId, + consumerId: tenant5.id, + }; + + const agreement5 = { + ...getMockAgreement(eservice3.id), + producerId: eservice3.producerId, + consumerId: tenant6.id, + }; + + const agreement6 = { + ...getMockAgreement(eservice3.id), + producerId: eservice3.producerId, + consumerId: delegateProducer1.id, + }; + + const agreement7 = { + ...getMockAgreement(eservice4.id), + producerId: eservice4.producerId, + consumerId: delegateConsumer1.id, + }; + + const agreement8 = { + ...getMockAgreement(eservice4.id), + producerId: eservice4.producerId, + consumerId: delegateConsumer2.id, + }; + + await addOneAgreement(agreement1); + await addOneAgreement(agreement2); + await addOneAgreement(agreement3); + await addOneAgreement(agreement4); + await addOneAgreement(agreement5); + await addOneAgreement(agreement6); + await addOneAgreement(agreement7); + await addOneAgreement(agreement8); + + const producerDelegation1 = getMockDelegation({ + kind: delegationKind.delegatedProducer, + delegateId: delegateProducer1.id, + delegatorId: eservice1.producerId, + eserviceId: eservice1.id, + state: delegationState.active, + }); + const consumerDelegation1 = getMockDelegation({ + kind: delegationKind.delegatedConsumer, + delegateId: delegateConsumer1.id, + delegatorId: tenant3.id, + eserviceId: eservice2.id, + state: delegationState.active, + }); + const consumerDelegation2 = getMockDelegation({ + kind: delegationKind.delegatedConsumer, + delegateId: delegateConsumer2.id, + delegatorId: tenant4.id, + eserviceId: eservice3.id, + state: delegationState.active, + }); + + // These delegations are revoked: the delegates + // should not see the corresponding agreements + const revokedProducerDelegation = getMockDelegation({ + kind: delegationKind.delegatedProducer, + delegateId: delegateProducer1.id, + delegatorId: eservice2.producerId, + eserviceId: eservice2.id, + state: delegationState.revoked, + }); + const revokedConsumerDelegation = getMockDelegation({ + kind: delegationKind.delegatedConsumer, + delegateId: delegateConsumer1.id, + delegatorId: tenant2.id, + eserviceId: eservice3.id, + state: delegationState.revoked, + }); + + await addOneDelegation(producerDelegation1); + await addOneDelegation(consumerDelegation1); + await addOneDelegation(consumerDelegation2); + await addOneDelegation(revokedProducerDelegation); + await addOneDelegation(revokedConsumerDelegation); + }); + describe("get agreements consumers", () => { + it("should get all agreements consumers for agreements visible to consumer/producer requester if no filters are provided", async () => { + const consumersResultForTenant1 = + await agreementService.getAgreementsConsumers(undefined, 10, 0, { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + consumersResultForTenant1, + [tenant2].map(toCompactOrganization) + ); + + const consumersResultForTenant2 = + await agreementService.getAgreementsConsumers(undefined, 10, 0, { + authData: getRandomAuthData(tenant2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + consumersResultForTenant2, + [tenant2, tenant3].map(toCompactOrganization) + ); + + const consumersResultForTenant3 = + await agreementService.getAgreementsConsumers(undefined, 10, 0, { + authData: getRandomAuthData(tenant3.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + consumersResultForTenant3, + [tenant3, tenant4, tenant6, delegateProducer1].map( + toCompactOrganization + ) + ); + + const consumersResultForTenant4 = + await agreementService.getAgreementsConsumers(undefined, 10, 0, { + authData: getRandomAuthData(tenant4.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + consumersResultForTenant4, + [tenant4, tenant5, delegateConsumer1, delegateConsumer2].map( + toCompactOrganization + ) + ); + + const consumersResultForTenant5 = + await agreementService.getAgreementsConsumers(undefined, 10, 0, { + authData: getRandomAuthData(tenant5.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + consumersResultForTenant5, + [tenant5].map(toCompactOrganization) + ); + + const consumersResultForTenant6 = + await agreementService.getAgreementsConsumers(undefined, 10, 0, { + authData: getRandomAuthData(tenant6.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + consumersResultForTenant6, + [tenant6].map(toCompactOrganization) + ); + }); + + it("should get all agreements consumers for agreements visible to delegate producer requester if no filters are provided", async () => { + const consumersResultForDelegateProducer1 = + await agreementService.getAgreementsConsumers(undefined, 10, 0, { + authData: getRandomAuthData(delegateProducer1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + consumersResultForDelegateProducer1, + [tenant2, delegateProducer1].map(toCompactOrganization) + ); + }); + + it("should get all agreements consumers for agreements visible to delegate consumer requester if no filters are provided", async () => { + const consumersResultForDelegateConsumer1 = + await agreementService.getAgreementsConsumers(undefined, 10, 0, { + authData: getRandomAuthData(delegateConsumer1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + consumersResultForDelegateConsumer1, + [tenant3, delegateConsumer1].map(toCompactOrganization) + ); + + const consumersResultForDelegateConsumer2 = + await agreementService.getAgreementsConsumers(undefined, 10, 0, { + authData: getRandomAuthData(delegateConsumer2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + consumersResultForDelegateConsumer2, + [tenant4, delegateConsumer2].map(toCompactOrganization) + ); + }); + + it("should get agreements consumers filtered by name", async () => { + const consumers = await agreementService.getAgreementsConsumers( + "Bar", + 10, + 0, + { + authData: getRandomAuthData(tenant4.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult( + consumers, + [tenant5, delegateConsumer1].map(toCompactOrganization) + ); + }); + + it("should get agreements consumers with limit", async () => { + const consumers = await agreementService.getAgreementsConsumers( + undefined, + 2, + 0, + { + authData: getRandomAuthData(tenant4.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(consumers).toEqual({ + totalCount: 4, + results: [tenant4, tenant5].map(toCompactOrganization), + }); + }); + + it("should get agreements consumers with offset and limit", async () => { + const consumers = await agreementService.getAgreementsConsumers( + undefined, + 2, + 1, + { + authData: getRandomAuthData(tenant4.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(consumers).toEqual({ + totalCount: 4, + results: [tenant5, delegateConsumer1].map(toCompactOrganization), + }); + }); + + it("should get agreements consumers with offset, limit, and name filter", async () => { + const consumers = await agreementService.getAgreementsConsumers( + "B", + 1, + 1, + { + authData: getRandomAuthData(tenant4.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(consumers).toEqual({ + totalCount: 3, + results: [tenant5].map(toCompactOrganization), + }); + }); + + it("should get no agreements consumers in case no filters match", async () => { + const producers = await agreementService.getAgreementsConsumers( + "Not existing name", + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(producers).toEqual({ + totalCount: 0, + results: [], + }); + }); + }); + describe("get agreements producers", () => { + it("should get all agreements producers for agreements visible to consumer/producer requester if no filters are provided", async () => { + const producerResultsForTenant1 = + await agreementService.getAgreementsProducers(undefined, 10, 0, { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + producerResultsForTenant1, + [tenant1].map(toCompactOrganization) + ); + + const producerResultsForTenant2 = + await agreementService.getAgreementsProducers(undefined, 10, 0, { + authData: getRandomAuthData(tenant2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + producerResultsForTenant2, + [tenant1, tenant2].map(toCompactOrganization) + ); + + const producerResultsForTenant3 = + await agreementService.getAgreementsProducers(undefined, 10, 0, { + authData: getRandomAuthData(tenant3.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + producerResultsForTenant3, + [tenant2, tenant3].map(toCompactOrganization) + ); + + const producerResultsForTenant4 = + await agreementService.getAgreementsProducers(undefined, 10, 0, { + authData: getRandomAuthData(tenant4.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + producerResultsForTenant4, + [tenant3, tenant4].map(toCompactOrganization) + ); + + const producerResultsForTenant5 = + await agreementService.getAgreementsProducers(undefined, 10, 0, { + authData: getRandomAuthData(tenant5.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + producerResultsForTenant5, + [tenant4].map(toCompactOrganization) + ); + + const producerResultsForTenant6 = + await agreementService.getAgreementsProducers(undefined, 10, 0, { + authData: getRandomAuthData(tenant6.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + producerResultsForTenant6, + [tenant3].map(toCompactOrganization) + ); + }); + + it("should get all agreements producers for agreements visible to delegate producer requester if no filters are provided", async () => { + const producersResultForDelegateProducer1 = + await agreementService.getAgreementsProducers(undefined, 10, 0, { + authData: getRandomAuthData(delegateProducer1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + producersResultForDelegateProducer1, + [tenant3, tenant1].map(toCompactOrganization) + ); + }); + + it("should get all agreements producers for agreements visible to delegate consumer requester if no filters are provided", async () => { + const producersResultForDelegateConsumer1 = + await agreementService.getAgreementsProducers(undefined, 10, 0, { + authData: getRandomAuthData(delegateConsumer1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + producersResultForDelegateConsumer1, + [tenant2, tenant4].map(toCompactOrganization) + ); + + const producersResultForDelegateConsumer2 = + await agreementService.getAgreementsProducers(undefined, 10, 0, { + authData: getRandomAuthData(delegateConsumer2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + }); + + expectSinglePageListResult( + producersResultForDelegateConsumer2, + [tenant3, tenant4].map(toCompactOrganization) + ); + }); + + it("should get agreements producers filtered by name", async () => { + const producers = await agreementService.getAgreementsProducers( + "Bar", + 10, + 0, + { + authData: getRandomAuthData(tenant2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expectSinglePageListResult( + producers, + [tenant2].map(toCompactOrganization) + ); + }); + it("should get agreements producers with limit", async () => { + const producers = await agreementService.getAgreementsProducers( + undefined, + 1, + 0, + { + authData: getRandomAuthData(tenant2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(producers).toEqual({ + totalCount: 2, + results: [tenant1].map(toCompactOrganization), + }); + }); + + it("should get agreements producers with offset and limit", async () => { + const producers = await agreementService.getAgreementsProducers( + undefined, + 1, + 1, + { + authData: getRandomAuthData(tenant2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(producers).toEqual({ + totalCount: 2, + results: [tenant2].map(toCompactOrganization), + }); + }); + + it("should get agreements producers with offset, limit, and name filter", async () => { + const producers = await agreementService.getAgreementsProducers( + "Bar", + 1, + 0, + { + authData: getRandomAuthData(tenant2.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(producers).toEqual({ + totalCount: 1, + results: [tenant2].map(toCompactOrganization), + }); + }); + + it("should get no agreements producers in case no filters match", async () => { + const producers = await agreementService.getAgreementsProducers( + "Not existing name", + 10, + 0, + { + authData: getRandomAuthData(tenant1.id), + serviceName: "", + correlationId: generateId(), + logger: genericLogger, + } + ); + + expect(producers).toEqual({ + totalCount: 0, + results: [], + }); + }); + }); +}); From 80effcf4b2e799a98c9989ea000aabbea611a51e Mon Sep 17 00:00:00 2001 From: Eric Camellini Date: Fri, 21 Feb 2025 10:28:06 +0100 Subject: [PATCH 11/11] Applying suggestions --- .../src/services/agreementService.ts | 8 ++++-- .../test/getAgreement.test.ts | 28 ++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/packages/agreement-process/src/services/agreementService.ts b/packages/agreement-process/src/services/agreementService.ts index 61aee51fc9..d82b7d178f 100644 --- a/packages/agreement-process/src/services/agreementService.ts +++ b/packages/agreement-process/src/services/agreementService.ts @@ -235,7 +235,9 @@ export function agreementServiceBuilder( { authData, logger }: WithLogger ): Promise> { logger.info( - `Getting agreements with producerId = ${filters.producerId}, consumerId = ${filters.consumerId}, eserviceId = ${filters.eserviceId}, agreementStates = ${filters.agreementStates}, attributeId = ${filters.attributeId}, showOnlyUpgradeable = ${filters.showOnlyUpgradeable}, offset = ${offset}, limit = ${limit}` + `Getting agreements with filters: ${JSON.stringify( + filters + )}, offset = ${offset}, limit = ${limit}` ); // Permissions are checked in the readModelService @@ -978,7 +980,9 @@ export function agreementServiceBuilder( { authData, logger }: WithLogger ): Promise> { logger.info( - `Retrieving EServices from agreements with consumers ${filters.consumerIds}, producers ${filters.producerIds}, offset ${offset}, limit ${limit} and name matching ${filters.eserviceName}` + `Retrieving EServices from agreements with filters: ${JSON.stringify( + filters + )}, offset ${offset}, limit ${limit}` ); // Permissions are checked in the readModelService diff --git a/packages/agreement-process/test/getAgreement.test.ts b/packages/agreement-process/test/getAgreement.test.ts index d3b5fa3a8c..78e0f84b4b 100644 --- a/packages/agreement-process/test/getAgreement.test.ts +++ b/packages/agreement-process/test/getAgreement.test.ts @@ -70,45 +70,41 @@ describe("get agreement", () => { await addOneDelegation(consumerDelegation); await addSomeRandomDelegations(agreement, addOneDelegation); - const retrievedDocumentByConsumer = await agreementService.getAgreementById( - agreement.id, - { + const retrievedAgreementByConsumer = + await agreementService.getAgreementById(agreement.id, { authData: getRandomAuthData(consumer.id), serviceName: "", correlationId: generateId(), logger: genericLogger, - } - ); - expect(retrievedDocumentByConsumer).toEqual(agreement); + }); + expect(retrievedAgreementByConsumer).toEqual(agreement); - const retrievedDocumentByProducer = await agreementService.getAgreementById( - agreement.id, - { + const retrievedAgreementByProducer = + await agreementService.getAgreementById(agreement.id, { authData: getRandomAuthData(producer.id), serviceName: "", correlationId: generateId(), logger: genericLogger, - } - ); - expect(retrievedDocumentByProducer).toEqual(agreement); + }); + expect(retrievedAgreementByProducer).toEqual(agreement); - const retrievedDocumentByProducerDelegate = + const retrievedAgreementByProducerDelegate = await agreementService.getAgreementById(agreement.id, { authData: getRandomAuthData(producerDelegate.id), serviceName: "", correlationId: generateId(), logger: genericLogger, }); - expect(retrievedDocumentByProducerDelegate).toEqual(agreement); + expect(retrievedAgreementByProducerDelegate).toEqual(agreement); - const retrievedDocumentByConsumerDelegate = + const retrievedAgreementByConsumerDelegate = await agreementService.getAgreementById(agreement.id, { authData: getRandomAuthData(consumerDelegate.id), serviceName: "", correlationId: generateId(), logger: genericLogger, }); - expect(retrievedDocumentByConsumerDelegate).toEqual(agreement); + expect(retrievedAgreementByConsumerDelegate).toEqual(agreement); }); it(`should throw an organizationNotAllowed error when the requester is