From 604355c74bec3858531461385e09548dba908b8e Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Tue, 5 Mar 2024 16:09:28 +0100 Subject: [PATCH 01/41] Update Logger Message --- .../src/routers/TenantRouter.ts | 12 +-- .../src/services/tenantService.ts | 74 ++++++++++++++++++- 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/packages/tenant-process/src/routers/TenantRouter.ts b/packages/tenant-process/src/routers/TenantRouter.ts index 28c13c24f1..424ece7224 100644 --- a/packages/tenant-process/src/routers/TenantRouter.ts +++ b/packages/tenant-process/src/routers/TenantRouter.ts @@ -54,7 +54,7 @@ const tenantsRouter = ( async (req, res) => { try { const { name, offset, limit } = req.query; - const consumers = await readModelService.getConsumers({ + const consumers = await tenantService.getConsumers({ name, producerId: req.ctx.authData.organizationId, offset, @@ -81,7 +81,7 @@ const tenantsRouter = ( async (req, res) => { try { const { name, offset, limit } = req.query; - const producers = await readModelService.getProducers({ + const producers = await tenantService.getProducers({ name, offset, limit, @@ -107,7 +107,7 @@ const tenantsRouter = ( async (req, res) => { try { const { name, offset, limit } = req.query; - const tenants = await readModelService.getTenantsByName({ + const tenants = await tenantService.getTenantsByName({ name, offset, limit, @@ -135,7 +135,7 @@ const tenantsRouter = ( ]), async (req, res) => { try { - const tenant = await readModelService.getTenantById( + const tenant = await tenantService.getTenantById( unsafeBrandId(req.params.id) ); @@ -171,7 +171,7 @@ const tenantsRouter = ( try { const { origin, code } = req.params; - const tenant = await readModelService.getTenantByExternalId({ + const tenant = await tenantService.getTenantByExternalId({ value: code, origin, }); @@ -206,7 +206,7 @@ const tenantsRouter = ( ]), async (req, res) => { try { - const tenant = await readModelService.getTenantBySelfcareId( + const tenant = await tenantService.getTenantBySelfcareId( req.params.selfcareId ); diff --git a/packages/tenant-process/src/services/tenantService.ts b/packages/tenant-process/src/services/tenantService.ts index 4eec6c814d..2dd4160d27 100644 --- a/packages/tenant-process/src/services/tenantService.ts +++ b/packages/tenant-process/src/services/tenantService.ts @@ -3,11 +3,13 @@ import { CreateEvent, eventRepository, initDB, + logger, } from "pagopa-interop-commons"; import { Attribute, AttributeId, ExternalId, + ListResult, Tenant, TenantAttribute, TenantEvent, @@ -158,6 +160,9 @@ export function tenantServiceBuilder( updatedAt: new Date(), }; + logger.info( + `Creating tenant with external id ${tenantSeed.externalId} via SelfCare request"` + ); return await repository.createEvent( toCreateEventTenantUpdated( existingTenant.data.id, @@ -182,6 +187,70 @@ export function tenantServiceBuilder( ); } }, + async getProducers({ + name, + offset, + limit, + }: { + name: string | undefined; + offset: number; + limit: number; + }): Promise> { + logger.info( + `Retrieving Producers with name = ${name}, limit = ${limit}, offset = ${offset}` + ); + return readModelService.getProducers({ name, offset, limit }); + }, + async getConsumers({ + name, + producerId, + offset, + limit, + }: { + name: string | undefined; + producerId: TenantId; + offset: number; + limit: number; + }): Promise> { + logger.info( + `Retrieving Consumers with name = ${name}, limit = ${limit}, offset = ${offset}` + ); + return readModelService.getConsumers({ name, producerId, offset, limit }); + }, + async getTenantsByName({ + name, + offset, + limit, + }: { + name: string | undefined; + offset: number; + limit: number; + }): Promise> { + logger.info( + `Retrieving Tenants with name = ${name}, limit = ${limit}, offset = ${offset}` + ); + return readModelService.getTenantsByName({ name, offset, limit }); + }, + async getTenantById( + id: TenantId + ): Promise | undefined> { + logger.info(`Retrieving tenant ${id}`); + return readModelService.getTenantById(id); + }, + async getTenantByExternalId( + externalId: ExternalId + ): Promise | undefined> { + logger.info( + `Retrieving tenant by External Id Origin ${externalId.origin} Code ${externalId.value}` + ); + return readModelService.getTenantByExternalId(externalId); + }, + async getTenantBySelfcareId( + selfcareId: string + ): Promise | undefined> { + logger.info(`Retrieving Tenant by Selfcare Id ${selfcareId}`); + return readModelService.getTenantBySelfcareId(selfcareId); + }, }; } @@ -262,7 +331,7 @@ export async function updateTenantLogic({ kind, updatedAt: new Date(), }; - + logger.info(`Updating Tenant ${tenant.data.id}`); return toCreateEventTenantUpdated( tenant.data.id, tenant.metadata.version, @@ -376,6 +445,9 @@ export async function updateVerifiedAttributeExtensionDateLogic({ updatedAt: new Date(), }; + logger.info( + `Update extension date of attribute ${attributeId} for tenant ${tenantId}` + ); return toCreateEventTenantUpdated( tenant.data.id, tenant.metadata.version, From f578e520b653f7918c693426b515f7444bcf555b Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Fri, 8 Mar 2024 10:01:55 +0100 Subject: [PATCH 02/41] Updated logger message --- packages/tenant-process/src/services/tenantService.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/tenant-process/src/services/tenantService.ts b/packages/tenant-process/src/services/tenantService.ts index 2dd4160d27..8b50106b16 100644 --- a/packages/tenant-process/src/services/tenantService.ts +++ b/packages/tenant-process/src/services/tenantService.ts @@ -241,14 +241,14 @@ export function tenantServiceBuilder( externalId: ExternalId ): Promise | undefined> { logger.info( - `Retrieving tenant by External Id Origin ${externalId.origin} Code ${externalId.value}` + `Retrieving tenant with origin ${externalId.origin} and code ${externalId.value}` ); return readModelService.getTenantByExternalId(externalId); }, async getTenantBySelfcareId( selfcareId: string ): Promise | undefined> { - logger.info(`Retrieving Tenant by Selfcare Id ${selfcareId}`); + logger.info(`Retrieving Tenant with Selfcare Id ${selfcareId}`); return readModelService.getTenantBySelfcareId(selfcareId); }, }; From 92c4dfa8e11a58ce5b93df2b61d4ef503c9fcff5 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Mon, 11 Mar 2024 09:39:10 +0100 Subject: [PATCH 03/41] Deleted unused function --- .../src/services/tenantService.ts | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/packages/tenant-process/src/services/tenantService.ts b/packages/tenant-process/src/services/tenantService.ts index 8b50106b16..740f5feea0 100644 --- a/packages/tenant-process/src/services/tenantService.ts +++ b/packages/tenant-process/src/services/tenantService.ts @@ -13,10 +13,8 @@ import { Tenant, TenantAttribute, TenantEvent, - TenantFeature, TenantId, TenantKind, - TenantMail, WithMetadata, generateId, tenantAttributeType, @@ -310,35 +308,6 @@ async function updateTenantVerifiedAttributeLogic({ ); } -export async function updateTenantLogic({ - tenant, - selfcareId, - features, - mails, - kind, -}: { - tenant: WithMetadata; - selfcareId: string | undefined; - features: TenantFeature[]; - mails: TenantMail[]; - kind: TenantKind; -}): Promise> { - const newTenant: Tenant = { - ...tenant.data, - selfcareId, - features, - mails, - kind, - updatedAt: new Date(), - }; - logger.info(`Updating Tenant ${tenant.data.id}`); - return toCreateEventTenantUpdated( - tenant.data.id, - tenant.metadata.version, - newTenant - ); -} - export function createTenantLogic({ tenant, apiTenantSeed, From bbaa84c9cecbbd93ee5d44a6820c550bfd9408df Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Fri, 15 Mar 2024 11:48:30 +0100 Subject: [PATCH 04/41] refactor logic function --- .../src/services/tenantService.ts | 342 ++++++------------ 1 file changed, 120 insertions(+), 222 deletions(-) diff --git a/packages/tenant-process/src/services/tenantService.ts b/packages/tenant-process/src/services/tenantService.ts index 740f5feea0..6933ccdd4c 100644 --- a/packages/tenant-process/src/services/tenantService.ts +++ b/packages/tenant-process/src/services/tenantService.ts @@ -1,23 +1,18 @@ import { AuthData, - CreateEvent, eventRepository, initDB, logger, } from "pagopa-interop-commons"; import { - Attribute, AttributeId, ExternalId, ListResult, Tenant, TenantAttribute, - TenantEvent, TenantId, - TenantKind, WithMetadata, generateId, - tenantAttributeType, tenantEventToBinaryData, } from "pagopa-interop-models"; import { TenantProcessConfig } from "../utilities/config.js"; @@ -26,15 +21,10 @@ import { toCreateEventTenantUpdated, } from "../model/domain/toEvent.js"; import { UpdateVerifiedTenantAttributeSeed } from "../model/domain/models.js"; -import { - ApiInternalTenantSeed, - ApiM2MTenantSeed, - ApiSelfcareTenantSeed, -} from "../model/types.js"; -import { tenantDuplicate } from "../model/domain/errors.js"; +import { ApiSelfcareTenantSeed } from "../model/types.js"; +import { tenantNotFound } from "../model/domain/errors.js"; import { assertOrganizationIsInAttributeVerifiers, - assertTenantExists, assertValidExpirationDate, assertVerifiedAttributeExistsInTenant, assertResourceAllowed, @@ -46,6 +36,17 @@ import { } from "./validators.js"; import { ReadModelService } from "./readModelService.js"; +const retrieveTenant = async ( + tenantId: TenantId, + readModelService: ReadModelService +): Promise> => { + const tenant = await readModelService.getTenantById(tenantId); + if (tenant === undefined) { + throw tenantNotFound(tenantId); + } + return tenant; +}; + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function tenantServiceBuilder( config: TenantProcessConfig, @@ -69,38 +70,71 @@ export function tenantServiceBuilder( attributeId: AttributeId, verifierId: string ): Promise { - const tenant = await readModelService.getTenantById(tenantId); + const tenant = await retrieveTenant(tenantId, readModelService); - return await repository.createEvent( - await updateVerifiedAttributeExtensionDateLogic({ - tenantId, - attributeId, - verifierId, - tenant, - }) + const attribute = tenant?.data.attributes.find( + (att) => att.id === attributeId + ); + + assertVerifiedAttributeExistsInTenant(attributeId, attribute, tenant); + + const oldVerifier = attribute.verifiedBy.find( + (verifier) => verifier.id === verifierId ); - }, - async createTenant( - apiTenantSeed: - | ApiSelfcareTenantSeed - | ApiM2MTenantSeed - | ApiInternalTenantSeed, - attributesExternalIds: ExternalId[], - kind: TenantKind - ): Promise { - const [attributes, tenant] = await Promise.all([ - readModelService.getAttributesByExternalIds(attributesExternalIds), - readModelService.getTenantByName(apiTenantSeed.name), - ]); - return repository.createEvent( - createTenantLogic({ - tenant, - apiTenantSeed, - kind, - attributes, - }) + assertOrganizationVerifierExist( + verifierId, + tenantId, + attributeId, + oldVerifier + ); + + assertExpirationDateExist( + tenantId, + attributeId, + verifierId, + oldVerifier.expirationDate + ); + + const oldExtensionDate = + oldVerifier.extensionDate ?? oldVerifier.expirationDate; + + const extensionDate = new Date( + oldExtensionDate.getTime() + + (oldVerifier.expirationDate.getTime() - + oldVerifier.verificationDate.getTime()) + ); + + const updatedAttribute: TenantAttribute = { + ...attribute, + verifiedBy: attribute.verifiedBy.map((v) => + v.id === verifierId + ? { + ...v, + extensionDate, + } + : v + ), + }; + + const updatedTenant: Tenant = { + ...tenant.data, + attributes: [ + updatedAttribute, + ...tenant.data.attributes.filter((a) => a.id !== updatedAttribute.id), + ], + updatedAt: new Date(), + }; + + const event = toCreateEventTenantUpdated( + tenant.data.id, + tenant.metadata.version, + updatedTenant + ); + logger.info( + `Update extension date of attribute ${attributeId} for tenant ${tenantId}` ); + return await repository.createEvent(event); }, async updateTenantVerifiedAttribute({ @@ -113,18 +147,50 @@ export function tenantServiceBuilder( tenantId: TenantId; attributeId: AttributeId; updateVerifiedTenantAttributeSeed: UpdateVerifiedTenantAttributeSeed; - }): Promise { - const tenant = await readModelService.getTenantById(tenantId); + }): Promise { + const tenant = await retrieveTenant(tenantId, readModelService); + + const expirationDate = updateVerifiedTenantAttributeSeed.expirationDate + ? new Date(updateVerifiedTenantAttributeSeed.expirationDate) + : undefined; + + assertValidExpirationDate(expirationDate); + + const attribute = tenant?.data.attributes.find( + (att) => att.id === attributeId + ); - await repository.createEvent( - await updateTenantVerifiedAttributeLogic({ - verifierId, - tenant, - tenantId, - attributeId, - updateVerifiedTenantAttributeSeed, - }) + assertVerifiedAttributeExistsInTenant(attributeId, attribute, tenant); + assertOrganizationIsInAttributeVerifiers(verifierId, tenantId, attribute); + + const updatedAttribute: TenantAttribute = { + ...attribute, + verifiedBy: attribute.verifiedBy.map((v) => + v.id === verifierId + ? { + ...v, + expirationDate, + } + : v + ), + }; + + const updatedTenant: Tenant = { + ...tenant.data, + attributes: [ + updatedAttribute, + ...tenant.data.attributes.filter((a) => a.id !== updatedAttribute.id), + ], + updatedAt: new Date(), + }; + const event = toCreateEventTenantUpdated( + tenant.data.id, + tenant.metadata.version, + updatedTenant ); + logger.info(`Update attribute ${attributeId} to tenant ${tenantId}`); + + return await repository.createEvent(event); }, async selfcareUpsertTenant({ @@ -159,7 +225,7 @@ export function tenantServiceBuilder( }; logger.info( - `Creating tenant with external id ${tenantSeed.externalId} via SelfCare request"` + `Updating tenant with external id ${tenantSeed.externalId} via SelfCare request"` ); return await repository.createEvent( toCreateEventTenantUpdated( @@ -180,6 +246,9 @@ export function tenantServiceBuilder( kind: getTenantKind([], tenantSeed.externalId), createdAt: new Date(), }; + logger.info( + `Creating tenant with external id ${tenantSeed.externalId} via SelfCare request"` + ); return await repository.createEvent( toCreateEventTenantAdded(newTenant) ); @@ -251,175 +320,4 @@ export function tenantServiceBuilder( }, }; } - -async function updateTenantVerifiedAttributeLogic({ - verifierId, - tenant, - tenantId, - attributeId, - updateVerifiedTenantAttributeSeed, -}: { - verifierId: string; - tenant: WithMetadata | undefined; - tenantId: TenantId; - attributeId: AttributeId; - updateVerifiedTenantAttributeSeed: UpdateVerifiedTenantAttributeSeed; -}): Promise> { - assertTenantExists(tenantId, tenant); - - const expirationDate = updateVerifiedTenantAttributeSeed.expirationDate - ? new Date(updateVerifiedTenantAttributeSeed.expirationDate) - : undefined; - - assertValidExpirationDate(expirationDate); - - const attribute = tenant?.data.attributes.find( - (att) => att.id === attributeId - ); - - assertVerifiedAttributeExistsInTenant(attributeId, attribute, tenant); - assertOrganizationIsInAttributeVerifiers(verifierId, tenantId, attribute); - - const updatedAttribute: TenantAttribute = { - ...attribute, - verifiedBy: attribute.verifiedBy.map((v) => - v.id === verifierId - ? { - ...v, - expirationDate, - } - : v - ), - }; - - const updatedTenant: Tenant = { - ...tenant.data, - attributes: [ - updatedAttribute, - ...tenant.data.attributes.filter((a) => a.id !== updatedAttribute.id), - ], - updatedAt: new Date(), - }; - - return toCreateEventTenantUpdated( - tenant.data.id, - tenant.metadata.version, - updatedTenant - ); -} - -export function createTenantLogic({ - tenant, - apiTenantSeed, - kind, - attributes, -}: { - tenant: WithMetadata | undefined; - apiTenantSeed: - | ApiSelfcareTenantSeed - | ApiM2MTenantSeed - | ApiInternalTenantSeed; - kind: TenantKind; - attributes: Array>; -}): CreateEvent { - if (tenant) { - throw tenantDuplicate(apiTenantSeed.name); - } - - const tenantAttributes: TenantAttribute[] = attributes.map((attribute) => ({ - type: tenantAttributeType.CERTIFIED, // All attributes here are certified - id: attribute.data.id, - assignmentTimestamp: new Date(), - })); - - const newTenant: Tenant = { - id: generateId(), - name: apiTenantSeed.name, - attributes: tenantAttributes, - externalId: apiTenantSeed.externalId, - features: [], - mails: [], - createdAt: new Date(), - kind, - }; - - return toCreateEventTenantAdded(newTenant); -} export type TenantService = ReturnType; - -export async function updateVerifiedAttributeExtensionDateLogic({ - tenantId, - attributeId, - verifierId, - tenant, -}: { - tenantId: TenantId; - attributeId: AttributeId; - verifierId: string; - tenant: WithMetadata | undefined; -}): Promise> { - assertTenantExists(tenantId, tenant); - - const attribute = tenant?.data.attributes.find( - (att) => att.id === attributeId - ); - - assertVerifiedAttributeExistsInTenant(attributeId, attribute, tenant); - - const oldVerifier = attribute.verifiedBy.find( - (verifier) => verifier.id === verifierId - ); - - assertOrganizationVerifierExist( - verifierId, - tenantId, - attributeId, - oldVerifier - ); - - assertExpirationDateExist( - tenantId, - attributeId, - verifierId, - oldVerifier.expirationDate - ); - - const oldExtensionDate = - oldVerifier.extensionDate ?? oldVerifier.expirationDate; - - const extensionDate = new Date( - oldExtensionDate.getTime() + - (oldVerifier.expirationDate.getTime() - - oldVerifier.verificationDate.getTime()) - ); - - const updatedAttribute: TenantAttribute = { - ...attribute, - verifiedBy: attribute.verifiedBy.map((v) => - v.id === verifierId - ? { - ...v, - extensionDate, - } - : v - ), - }; - - const updatedTenant: Tenant = { - ...tenant.data, - attributes: [ - updatedAttribute, - ...tenant.data.attributes.filter((a) => a.id !== updatedAttribute.id), - ], - updatedAt: new Date(), - }; - - logger.info( - `Update extension date of attribute ${attributeId} for tenant ${tenantId}` - ); - return toCreateEventTenantUpdated( - tenant.data.id, - tenant.metadata.version, - updatedTenant - ); -} From 77ad263da080f6479d1abf566685dc083e636005 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Fri, 15 Mar 2024 15:05:02 +0100 Subject: [PATCH 05/41] changed log position --- .../src/services/tenantService.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/tenant-process/src/services/tenantService.ts b/packages/tenant-process/src/services/tenantService.ts index 6933ccdd4c..1d8a62ac20 100644 --- a/packages/tenant-process/src/services/tenantService.ts +++ b/packages/tenant-process/src/services/tenantService.ts @@ -70,6 +70,10 @@ export function tenantServiceBuilder( attributeId: AttributeId, verifierId: string ): Promise { + logger.info( + `Update extension date of attribute ${attributeId} for tenant ${tenantId}` + ); + const tenant = await retrieveTenant(tenantId, readModelService); const attribute = tenant?.data.attributes.find( @@ -131,9 +135,6 @@ export function tenantServiceBuilder( tenant.metadata.version, updatedTenant ); - logger.info( - `Update extension date of attribute ${attributeId} for tenant ${tenantId}` - ); return await repository.createEvent(event); }, @@ -148,6 +149,8 @@ export function tenantServiceBuilder( attributeId: AttributeId; updateVerifiedTenantAttributeSeed: UpdateVerifiedTenantAttributeSeed; }): Promise { + logger.info(`Update attribute ${attributeId} to tenant ${tenantId}`); + const tenant = await retrieveTenant(tenantId, readModelService); const expirationDate = updateVerifiedTenantAttributeSeed.expirationDate @@ -188,8 +191,6 @@ export function tenantServiceBuilder( tenant.metadata.version, updatedTenant ); - logger.info(`Update attribute ${attributeId} to tenant ${tenantId}`); - return await repository.createEvent(event); }, @@ -204,6 +205,9 @@ export function tenantServiceBuilder( tenantSeed.externalId ); if (existingTenant) { + logger.info( + `Updating tenant with external id ${tenantSeed.externalId} via SelfCare request"` + ); await assertResourceAllowed(existingTenant.data.id, authData); evaluateNewSelfcareId({ @@ -223,10 +227,6 @@ export function tenantServiceBuilder( selfcareId: tenantSeed.selfcareId, updatedAt: new Date(), }; - - logger.info( - `Updating tenant with external id ${tenantSeed.externalId} via SelfCare request"` - ); return await repository.createEvent( toCreateEventTenantUpdated( existingTenant.data.id, @@ -235,6 +235,9 @@ export function tenantServiceBuilder( ) ); } else { + logger.info( + `Creating tenant with external id ${tenantSeed.externalId} via SelfCare request"` + ); const newTenant: Tenant = { id: generateId(), name: tenantSeed.name, @@ -246,9 +249,6 @@ export function tenantServiceBuilder( kind: getTenantKind([], tenantSeed.externalId), createdAt: new Date(), }; - logger.info( - `Creating tenant with external id ${tenantSeed.externalId} via SelfCare request"` - ); return await repository.createEvent( toCreateEventTenantAdded(newTenant) ); From 6d27473d147779bf4c1892d1c84a852b7e7ce29e Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Fri, 15 Mar 2024 15:39:51 +0100 Subject: [PATCH 06/41] changed return type --- .../tenant-process/src/routers/TenantRouter.ts | 17 +++++++++-------- .../src/services/tenantService.ts | 10 ++++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/tenant-process/src/routers/TenantRouter.ts b/packages/tenant-process/src/routers/TenantRouter.ts index 424ece7224..a7ae4a201e 100644 --- a/packages/tenant-process/src/routers/TenantRouter.ts +++ b/packages/tenant-process/src/routers/TenantRouter.ts @@ -287,13 +287,13 @@ const tenantsRouter = ( async (req, res) => { try { const { tenantId, attributeId } = req.params; - await tenantService.updateTenantVerifiedAttribute({ + const tenant = await tenantService.updateTenantVerifiedAttribute({ verifierId: req.ctx.authData.organizationId, tenantId: unsafeBrandId(tenantId), attributeId: unsafeBrandId(attributeId), updateVerifiedTenantAttributeSeed: req.body, }); - return res.status(200).end(); + return res.status(200).json(toApiTenant(tenant)).end(); } catch (error) { const errorRes = makeApiProblem( error, @@ -309,12 +309,13 @@ const tenantsRouter = ( async (req, res) => { try { const { tenantId, attributeId, verifierId } = req.params; - await tenantService.updateVerifiedAttributeExtensionDate( - unsafeBrandId(tenantId), - unsafeBrandId(attributeId), - verifierId - ); - return res.status(200).end(); + const tenant = + await tenantService.updateVerifiedAttributeExtensionDate( + unsafeBrandId(tenantId), + unsafeBrandId(attributeId), + verifierId + ); + return res.status(200).json(toApiTenant(tenant)).end(); } catch (error) { const errorRes = makeApiProblem( error, diff --git a/packages/tenant-process/src/services/tenantService.ts b/packages/tenant-process/src/services/tenantService.ts index 6933ccdd4c..a7a93eefbe 100644 --- a/packages/tenant-process/src/services/tenantService.ts +++ b/packages/tenant-process/src/services/tenantService.ts @@ -69,7 +69,7 @@ export function tenantServiceBuilder( tenantId: TenantId, attributeId: AttributeId, verifierId: string - ): Promise { + ): Promise { const tenant = await retrieveTenant(tenantId, readModelService); const attribute = tenant?.data.attributes.find( @@ -134,7 +134,8 @@ export function tenantServiceBuilder( logger.info( `Update extension date of attribute ${attributeId} for tenant ${tenantId}` ); - return await repository.createEvent(event); + await repository.createEvent(event); + return updatedTenant; }, async updateTenantVerifiedAttribute({ @@ -147,7 +148,7 @@ export function tenantServiceBuilder( tenantId: TenantId; attributeId: AttributeId; updateVerifiedTenantAttributeSeed: UpdateVerifiedTenantAttributeSeed; - }): Promise { + }): Promise { const tenant = await retrieveTenant(tenantId, readModelService); const expirationDate = updateVerifiedTenantAttributeSeed.expirationDate @@ -190,7 +191,8 @@ export function tenantServiceBuilder( ); logger.info(`Update attribute ${attributeId} to tenant ${tenantId}`); - return await repository.createEvent(event); + await repository.createEvent(event); + return updatedTenant; }, async selfcareUpsertTenant({ From 3eebf11ad300d9696c23feb524038edb715fe02d Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Fri, 15 Mar 2024 17:05:01 +0100 Subject: [PATCH 07/41] deleted updateTenant from open-api --- .../open-api/tenant-service-spec.yml | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/packages/tenant-process/open-api/tenant-service-spec.yml b/packages/tenant-process/open-api/tenant-service-spec.yml index dbe591b26c..ca96dc5922 100644 --- a/packages/tenant-process/open-api/tenant-service-spec.yml +++ b/packages/tenant-process/open-api/tenant-service-spec.yml @@ -410,30 +410,6 @@ paths: application/json: schema: $ref: '#/components/schemas/Problem' - post: - tags: - - tenant - operationId: updateTenant - description: Updates the tenant - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/TenantDelta' - responses: - '200': - description: Tenant updated - content: - application/json: - schema: - $ref: '#/components/schemas/ResourceId' - '404': - description: Tenant Not Found - content: - application/json: - schema: - $ref: '#/components/schemas/Problem' /tenants/origin/{origin}/code/{code}: parameters: - $ref: '#/components/parameters/CorrelationIdHeader' From c89a5ebec1a908e5321c7e55b76ca63f49e05589 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Fri, 15 Mar 2024 17:10:39 +0100 Subject: [PATCH 08/41] Fix --- packages/tenant-process/src/routers/TenantRouter.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/tenant-process/src/routers/TenantRouter.ts b/packages/tenant-process/src/routers/TenantRouter.ts index a7ae4a201e..1bbf0af7cd 100644 --- a/packages/tenant-process/src/routers/TenantRouter.ts +++ b/packages/tenant-process/src/routers/TenantRouter.ts @@ -237,11 +237,6 @@ const tenantsRouter = ( authorizationMiddleware([INTERNAL_ROLE]), async (_req, res) => res.status(501).send() ) - .post( - "/tenants/:id", - authorizationMiddleware([ADMIN_ROLE]), - async (_req, res) => res.status(501).send() - ) .post( "/internal/origin/:tOrigin/externalId/:tExternalId/attributes/origin/:aOrigin/externalId/:aExternalId", authorizationMiddleware([INTERNAL_ROLE]), From a922d6699f17878cd3073b177825d6d5a8f9ef9f Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Wed, 27 Mar 2024 08:54:18 +0100 Subject: [PATCH 09/41] Added logger before the retrive --- packages/tenant-process/src/services/tenantService.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/tenant-process/src/services/tenantService.ts b/packages/tenant-process/src/services/tenantService.ts index 1d8a62ac20..242b1a1e47 100644 --- a/packages/tenant-process/src/services/tenantService.ts +++ b/packages/tenant-process/src/services/tenantService.ts @@ -76,7 +76,7 @@ export function tenantServiceBuilder( const tenant = await retrieveTenant(tenantId, readModelService); - const attribute = tenant?.data.attributes.find( + const attribute = tenant.data.attributes.find( (att) => att.id === attributeId ); @@ -159,7 +159,7 @@ export function tenantServiceBuilder( assertValidExpirationDate(expirationDate); - const attribute = tenant?.data.attributes.find( + const attribute = tenant.data.attributes.find( (att) => att.id === attributeId ); @@ -201,6 +201,9 @@ export function tenantServiceBuilder( tenantSeed: ApiSelfcareTenantSeed; authData: AuthData; }): Promise { + logger.info( + `Upsert tenant by selfcare with externalId: ${tenantSeed.externalId}` + ); const existingTenant = await readModelService.getTenantByExternalId( tenantSeed.externalId ); From d9cbe14dd101e9c1ab99e566b13c0c638d8d05d5 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 3 Apr 2024 12:37:40 +0200 Subject: [PATCH 10/41] Add protobuf definitions --- packages/models/proto/v2/tenant/events.proto | 58 +++++++++++ packages/models/proto/v2/tenant/tenant.proto | 102 +++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 packages/models/proto/v2/tenant/events.proto create mode 100644 packages/models/proto/v2/tenant/tenant.proto diff --git a/packages/models/proto/v2/tenant/events.proto b/packages/models/proto/v2/tenant/events.proto new file mode 100644 index 0000000000..a26f02e9f7 --- /dev/null +++ b/packages/models/proto/v2/tenant/events.proto @@ -0,0 +1,58 @@ +syntax = "proto2"; + +package tenant.v2; + +import "v2/tenant/tenant.proto"; + +message TenantOnboardedV2 { + required TenantV2 tenant = 1; +} + +message TenantOnboardDetailsUpdatedV2 { + required TenantV2 tenant = 1; +} + +message TenantCertifiedAttributeAssignedV2 { + required string attributeId = 1; + required TenantV2 tenant = 2; +} + +message TenantCertifiedAttributeRevokedV2 { + required string attributeId = 1; + required TenantV2 tenant = 2; +} + +message TenantDeclaredAttributeAssignedV2 { + required string attributeId = 1; + required TenantV2 tenant = 2; +} + +message TenantDeclaredAttributeRevokedV2 { + required string attributeId = 1; + required TenantV2 tenant = 2; +} + +message TenantVerifiedAttributeAssignedV2 { + required string attributeId = 1; + required TenantV2 tenant = 2; +} + +message TenantVerifiedAttributeRevokedV2 { + required string attributeId = 1; + required TenantV2 tenant = 2; +} + +message TenantVerifiedAttributeExpirationUpdatedV2 { + required string attributeId = 1; + required TenantV2 tenant = 2; +} + +message MaintenanceTenantDeletedV2 { + required string tenantId = 1; + required TenantV2 tenant = 2; +} + +message TenantMailAddedV2 { + required string mailId = 1; + required TenantV2 tenant = 2; +} \ No newline at end of file diff --git a/packages/models/proto/v2/tenant/tenant.proto b/packages/models/proto/v2/tenant/tenant.proto new file mode 100644 index 0000000000..fc8a6c4b82 --- /dev/null +++ b/packages/models/proto/v2/tenant/tenant.proto @@ -0,0 +1,102 @@ +syntax = "proto2"; + +package tenant.v2; + +message TenantV2 { + required string id = 1; + optional string selfcareId = 2; + required ExternalIdV2 externalId = 3; + repeated TenantFeatureV2 features = 4; + repeated TenantAttributeV2 attributes = 5; + required int64 createdAt = 6; + optional int64 updatedAt = 7; + repeated TenantMailV2 mails = 8; + optional string name = 9; + optional TenantKindV2 kind = 10; + optional int64 onboardedAt = 11; + optional TenantUnitTypeV2 subUnitType = 12; + +} + +enum TenantKindV2 { + PA = 1; + GSP = 2; + PRIVATE = 3; +} + +message TenantMailV2 { + required TenantMailKindV2 kind = 1; + required string address = 2; + required int64 createdAt = 3; + optional string description = 4; + optional string id = 5; +} + +enum TenantMailKindV2 { + CONTACT_EMAIL = 1; + DIGITAL_ADDRESS = 2; +} + +enum TenantUnitTypeV2 { + AOO = 1; + UO = 2; +} + +message TenantFeatureV2 { + oneof sealed_value { + CertifierV2 certifier = 1; + } +} + +message CertifierV2 { + required string certifierId = 1; +} + +message TenantVerifierV2 { + reserved 3; + required string id = 1; + required int64 verificationDate = 2; + optional int64 expirationDate = 4; + optional int64 extensionDate = 5; +} + +message TenantRevokerV2 { + reserved 3; + required string id = 1; + required int64 verificationDate = 2; + optional int64 expirationDate = 4; + optional int64 extensionDate = 5; + required int64 revocationDate = 6; +} + +message ExternalIdV2 { + required string origin = 1; + required string value = 2; +} + +message TenantCertifiedAttributeV2 { + required string id = 1; + required int64 assignmentTimestamp = 2; + optional int64 revocationTimestamp = 3; +} + +message TenantDeclaredAttributeV2 { + required string id = 1; + required int64 assignmentTimestamp = 2; + optional int64 revocationTimestamp = 3; +} + +message TenantVerifiedAttributeV2 { + required string id = 1; + required int64 assignmentTimestamp = 2; + repeated TenantVerifierV2 verifiedBy = 3; + repeated TenantRevokerV2 revokedBy = 4; +} + +message TenantAttributeV2 { + oneof sealed_value { + TenantCertifiedAttributeV2 certifiedAttribute = 1; + TenantDeclaredAttributeV2 declaredAttribute = 2; + TenantVerifiedAttributeV2 verifiedAttribute = 3; + } +} \ No newline at end of file From 0403d893c171e8fa32ec9f8828b69775077d25cf Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 3 Apr 2024 12:37:55 +0200 Subject: [PATCH 11/41] Add converters --- ...onverter.ts => protobufConverterFromV1.ts} | 0 .../src/tenant/protobufConverterFromV2.ts | 192 ++++++++++++++++++ .../src/tenant/protobufConverterToV2.ts | 151 ++++++++++++++ 3 files changed, 343 insertions(+) rename packages/models/src/tenant/{protobufConverter.ts => protobufConverterFromV1.ts} (100%) create mode 100644 packages/models/src/tenant/protobufConverterFromV2.ts create mode 100644 packages/models/src/tenant/protobufConverterToV2.ts diff --git a/packages/models/src/tenant/protobufConverter.ts b/packages/models/src/tenant/protobufConverterFromV1.ts similarity index 100% rename from packages/models/src/tenant/protobufConverter.ts rename to packages/models/src/tenant/protobufConverterFromV1.ts diff --git a/packages/models/src/tenant/protobufConverterFromV2.ts b/packages/models/src/tenant/protobufConverterFromV2.ts new file mode 100644 index 0000000000..3867112969 --- /dev/null +++ b/packages/models/src/tenant/protobufConverterFromV2.ts @@ -0,0 +1,192 @@ +import { createHash } from "crypto"; +import { match } from "ts-pattern"; +import { unsafeBrandId } from "../brandedIds.js"; +import { genericError } from "../errors.js"; +import { + TenantKindV2, + TenantMailKindV2, + TenantMailV2, + TenantFeatureV2, + TenantVerifierV2, + TenantRevokerV2, + TenantAttributeV2, + TenantV2, + TenantUnitTypeV2, +} from "../gen/v2/tenant/tenant.js"; +import { + TenantKind, + tenantKind, + TenantMailKind, + tenantMailKind, + TenantMail, + TenantFeatureCertifier, + TenantVerifier, + TenantRevoker, + TenantAttribute, + Tenant, + ExternalId, + tenantAttributeType, + TenantUnitType, + tenantUnitType, +} from "./tenant.js"; + +export const fromTenantKindV2 = (input: TenantKindV2): TenantKind => { + switch (input) { + case TenantKindV2.GSP: + return tenantKind.GSP; + case TenantKindV2.PA: + return tenantKind.PA; + case TenantKindV2.PRIVATE: + return tenantKind.PRIVATE; + case TenantKindV2.UNSPECIFIED$: + throw new Error("Unspecified tenant kind"); + } +}; + +export const fromTenantMailKindV2 = ( + input: TenantMailKindV2 +): TenantMailKind => { + switch (input) { + case TenantMailKindV2.CONTACT_EMAIL: + return tenantMailKind.ContactEmail; + case TenantMailKindV2.DIGITAL_ADDRESS: + return tenantMailKind.DigitalAddress; + case TenantMailKindV2.UNSPECIFIED$: + throw new Error("Unspecified tenant mail kind"); + } +}; + +export const fromTenantMailV2 = (input: TenantMailV2): TenantMail => ({ + ...input, + id: input.id + ? input.id + : createHash("sha256").update(input.address).digest("hex"), + createdAt: new Date(Number(input.createdAt)), + kind: fromTenantMailKindV2(input.kind), +}); + +export const fromTenantFeatureV2 = ( + input: TenantFeatureV2 +): TenantFeatureCertifier => + match( + input.sealedValue + ) + .with({ oneofKind: "certifier" }, ({ certifier }) => ({ + type: "PersistentCertifier", + certifierId: certifier.certifierId, + })) + .with({ oneofKind: undefined }, () => { + throw new Error("Unable to deserialize TenantFeature"); + }) + .exhaustive(); + +export const fromTenantVerifierV2 = ( + input: TenantVerifierV2 +): TenantVerifier => ({ + ...input, + verificationDate: new Date(Number(input.verificationDate)), + expirationDate: input.expirationDate + ? new Date(Number(input.expirationDate)) + : undefined, + extensionDate: input.extensionDate + ? new Date(Number(input.extensionDate)) + : undefined, +}); + +export const fromTenantRevokerV2 = (input: TenantRevokerV2): TenantRevoker => ({ + ...input, + expirationDate: input.expirationDate + ? new Date(Number(input.expirationDate)) + : undefined, + extensionDate: input.extensionDate + ? new Date(Number(input.extensionDate)) + : undefined, + revocationDate: new Date(Number(input.revocationDate)), + verificationDate: new Date(Number(input.verificationDate)), +}); + +export const fromTenantAttributesV2 = ( + input: TenantAttributeV2 +): TenantAttribute => { + const { sealedValue } = input; + + switch (sealedValue.oneofKind) { + case "certifiedAttribute": + const { certifiedAttribute } = sealedValue; + return { + id: unsafeBrandId(certifiedAttribute.id), + assignmentTimestamp: new Date( + Number(certifiedAttribute.assignmentTimestamp) + ), + type: tenantAttributeType.CERTIFIED, + }; + case "verifiedAttribute": + const { verifiedAttribute } = sealedValue; + return { + id: unsafeBrandId(verifiedAttribute.id), + assignmentTimestamp: new Date( + Number(verifiedAttribute.assignmentTimestamp) + ), + verifiedBy: verifiedAttribute.verifiedBy.map(fromTenantVerifierV2), + revokedBy: verifiedAttribute.revokedBy.map(fromTenantRevokerV2), + type: tenantAttributeType.VERIFIED, + }; + case "declaredAttribute": + const { declaredAttribute } = sealedValue; + return { + id: unsafeBrandId(declaredAttribute.id), + assignmentTimestamp: new Date( + Number(declaredAttribute.assignmentTimestamp) + ), + type: tenantAttributeType.DECLARED, + }; + case undefined: + throw genericError("Undefined attribute kind"); + } +}; + +export const fromTenantUnitTypeV2 = ( + input: TenantUnitTypeV2 +): TenantUnitType => { + switch (input) { + case TenantUnitTypeV2.AOO: + return tenantUnitType.AOO; + case TenantUnitTypeV2.UO: + return tenantUnitType.UO; + case TenantUnitTypeV2.UNSPECIFIED$: + throw new Error("Unspecified tenant unit type"); + } +}; + +export const fromTenantV2 = (input: TenantV2): Tenant => { + /** + * The `externalId` field is required in the TenantV2 protobuf model but + * for some reasons the @protobuf-ts/protoc library generates it as optional. + * This issue has been reported here: https://github.com/timostamm/protobuf-ts/issues/340 + */ + const externalId = ExternalId.safeParse(input.externalId); + if (!externalId.success) { + throw genericError( + `Error while deserializing TenantV2 (${input.id}): missing externalId` + ); + } + + return { + ...input, + id: unsafeBrandId(input.id), + name: input.name ?? "", + createdAt: new Date(Number(input.createdAt)), + attributes: input.attributes.map(fromTenantAttributesV2), + externalId: externalId.data, + features: input.features.map(fromTenantFeatureV2), + mails: input.mails.map(fromTenantMailV2), + kind: input.kind ? fromTenantKindV2(input.kind) : undefined, + updatedAt: input.updatedAt ? new Date(Number(input.updatedAt)) : undefined, + onboardedAt: input.onboardedAt + ? new Date(Number(input.onboardedAt)) + : undefined, + subUnitType: input.subUnitType + ? fromTenantUnitTypeV2(input.subUnitType) + : undefined, + }; +}; diff --git a/packages/models/src/tenant/protobufConverterToV2.ts b/packages/models/src/tenant/protobufConverterToV2.ts new file mode 100644 index 0000000000..129dc096f7 --- /dev/null +++ b/packages/models/src/tenant/protobufConverterToV2.ts @@ -0,0 +1,151 @@ +import { match } from "ts-pattern"; +import { + TenantAttributeV2, + TenantFeatureV2, + TenantKindV2, + TenantMailKindV2, + TenantMailV2, + TenantRevokerV2, + TenantUnitTypeV2, + TenantV2, + TenantVerifierV2, +} from "../index.js"; +import { + Tenant, + TenantAttribute, + TenantFeature, + TenantKind, + TenantMail, + TenantMailKind, + TenantRevoker, + TenantUnitType, + TenantVerifier, + tenantAttributeType, + tenantKind, + tenantMailKind, + tenantUnitType, +} from "./tenant.js"; + +export function toFeatureV2(feature: TenantFeature): TenantFeatureV2 { + return match(feature) + .with({ type: "PersistentCertifier" }, (feature) => ({ + sealedValue: { + oneofKind: "certifier", + certifier: { + certifierId: feature.certifierId, + }, + }, + })) + .exhaustive(); +} + +export function toTenantVerifierV2(verifier: TenantVerifier): TenantVerifierV2 { + return { + id: verifier.id, + verificationDate: BigInt(verifier.verificationDate.getTime()), + expirationDate: verifier.expirationDate + ? BigInt(verifier.expirationDate?.getTime()) + : undefined, + extensionDate: verifier.extensionDate + ? BigInt(verifier.extensionDate?.getTime()) + : undefined, + }; +} + +export function toTenantRevokerV2(revoker: TenantRevoker): TenantRevokerV2 { + return { + id: revoker.id, + verificationDate: BigInt(revoker.verificationDate.getTime()), + expirationDate: revoker.expirationDate + ? BigInt(revoker.expirationDate?.getTime()) + : undefined, + extensionDate: revoker.extensionDate + ? BigInt(revoker.extensionDate?.getTime()) + : undefined, + revocationDate: BigInt(revoker.revocationDate.getTime()), + }; +} + +export function toAttributeV2(input: TenantAttribute): TenantAttributeV2 { + return match(input) + .with({ type: tenantAttributeType.CERTIFIED }, (attribute) => ({ + sealedValue: { + oneofKind: "certifiedAttribute", + certifiedAttribute: { + id: attribute.id, + assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), + revocationTimestamp: attribute.revocationTimestamp + ? BigInt(attribute.revocationTimestamp?.getTime()) + : undefined, + }, + }, + })) + .with({ type: tenantAttributeType.VERIFIED }, (attribute) => ({ + sealedValue: { + oneofKind: "verifiedAttribute", + verifiedAttribute: { + id: attribute.id, + assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), + verifiedBy: attribute.verifiedBy.map(toTenantVerifierV2), + revokedBy: attribute.revokedBy.map(toTenantRevokerV2), + }, + }, + })) + .with({ type: tenantAttributeType.DECLARED }, (attribute) => ({ + sealedValue: { + oneofKind: "declaredAttribute", + declaredAttribute: { + id: attribute.id, + assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), + }, + }, + })) + .exhaustive(); +} + +export function toTenantMailV2(mail: TenantMail): TenantMailV2 { + return { + kind: toTenantMailKindV2(mail.kind), + address: mail.address, + createdAt: BigInt(mail.createdAt.getTime()), + description: mail.description ?? undefined, + }; +} + +export function toTenantMailKindV2(kind: TenantMailKind): TenantMailKindV2 { + return match(kind) + .with(tenantMailKind.ContactEmail, () => TenantMailKindV2.CONTACT_EMAIL) + .with(tenantMailKind.DigitalAddress, () => TenantMailKindV2.DIGITAL_ADDRESS) + .exhaustive(); +} + +export function toTenantKindV2(input: TenantKind): TenantKindV2 { + return match(input) + .with(tenantKind.GSP, () => TenantKindV2.GSP) + .with(tenantKind.PA, () => TenantKindV2.PA) + .with(tenantKind.PRIVATE, () => TenantKindV2.PRIVATE) + .exhaustive(); +} + +export function toTenantUnitTypeV2(input: TenantUnitType): TenantUnitTypeV2 { + return match(input) + .with(tenantUnitType.AOO, () => TenantUnitTypeV2.AOO) + .with(tenantUnitType.UO, () => TenantUnitTypeV2.UO) + .exhaustive(); +} + +export const toTenantV2 = (tenant: Tenant): TenantV2 => ({ + ...tenant, + features: tenant.features.map(toFeatureV2), + attributes: tenant.attributes.map(toAttributeV2), + createdAt: BigInt(tenant.createdAt.getTime()), + updatedAt: tenant.updatedAt ? BigInt(tenant.updatedAt.getTime()) : undefined, + mails: tenant.mails.map(toTenantMailV2), + kind: tenant.kind ? toTenantKindV2(tenant.kind) : undefined, + onboardedAt: tenant.createdAt + ? BigInt(tenant.createdAt.getTime()) + : undefined, + subUnitType: tenant.subUnitType + ? toTenantUnitTypeV2(tenant.subUnitType) + : undefined, +}); From b2af17eca0e3e59b25a11e8de7aa9ba6aa9b6579 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 3 Apr 2024 12:38:07 +0200 Subject: [PATCH 12/41] Update index.ts --- packages/models/src/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/models/src/index.ts b/packages/models/src/index.ts index d72e52180d..3d2cb6cc70 100644 --- a/packages/models/src/index.ts +++ b/packages/models/src/index.ts @@ -25,7 +25,8 @@ export * from "./risk-analysis/riskAnalysis.js"; export * from "./tenant/tenant.js"; export * from "./tenant/tenantEvents.js"; -export * from "./tenant/protobufConverter.js"; +export * from "./tenant/protobufConverterFromV1.js"; +export * from "./tenant/protobufConverterFromV2.js"; export * from "./user/user.js"; @@ -51,5 +52,7 @@ export * from "./gen/v1/agreement/events.js"; export * from "./gen/v1/agreement/state.js"; export * from "./gen/v1/tenant/tenant.js"; export * from "./gen/v1/tenant/events.js"; +export * from "./gen/v2/tenant/tenant.js"; +export * from "./gen/v2/tenant/events.js"; export * from "./gen/v1/attribute/attribute.js"; export * from "./gen/v1/attribute/events.js"; From 09c8f5793cf3ee548455733de09c6d58ea18adb8 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Wed, 3 Apr 2024 15:32:15 +0200 Subject: [PATCH 13/41] Fix end of file --- packages/models/proto/v2/tenant/events.proto | 2 +- packages/models/proto/v2/tenant/tenant.proto | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/models/proto/v2/tenant/events.proto b/packages/models/proto/v2/tenant/events.proto index a26f02e9f7..2b3f9e68b3 100644 --- a/packages/models/proto/v2/tenant/events.proto +++ b/packages/models/proto/v2/tenant/events.proto @@ -55,4 +55,4 @@ message MaintenanceTenantDeletedV2 { message TenantMailAddedV2 { required string mailId = 1; required TenantV2 tenant = 2; -} \ No newline at end of file +} diff --git a/packages/models/proto/v2/tenant/tenant.proto b/packages/models/proto/v2/tenant/tenant.proto index fc8a6c4b82..d0cf80f712 100644 --- a/packages/models/proto/v2/tenant/tenant.proto +++ b/packages/models/proto/v2/tenant/tenant.proto @@ -99,4 +99,4 @@ message TenantAttributeV2 { TenantDeclaredAttributeV2 declaredAttribute = 2; TenantVerifiedAttributeV2 verifiedAttribute = 3; } -} \ No newline at end of file +} From 836e08ae22b0e0f46b264c5946fcf109f0e29c77 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Wed, 3 Apr 2024 16:08:41 +0200 Subject: [PATCH 14/41] Add event definition --- packages/models/src/tenant/tenantEvents.ts | 154 ++++++++++++++++++++- 1 file changed, 153 insertions(+), 1 deletion(-) diff --git a/packages/models/src/tenant/tenantEvents.ts b/packages/models/src/tenant/tenantEvents.ts index 2773a69b30..d6a65bd725 100644 --- a/packages/models/src/tenant/tenantEvents.ts +++ b/packages/models/src/tenant/tenantEvents.ts @@ -7,10 +7,30 @@ import { SelfcareMappingCreatedV1, SelfcareMappingDeletedV1, } from "../gen/v1/tenant/events.js"; +import { + TenantOnboardedV2, + TenantOnboardDetailsUpdatedV2, + TenantCertifiedAttributeAssignedV2, + TenantCertifiedAttributeRevokedV2, + TenantDeclaredAttributeAssignedV2, + TenantDeclaredAttributeRevokedV2, + TenantVerifiedAttributeAssignedV2, + TenantVerifiedAttributeRevokedV2, + TenantVerifiedAttributeExpirationUpdatedV2, + MaintenanceTenantDeletedV2, + TenantMailAddedV2, +} from "../gen/v2/tenant/events.js"; import { protobufDecoder } from "../protobuf/protobuf.js"; import { EventEnvelope } from "../events/events.js"; export function tenantEventToBinaryData(event: TenantEvent): Uint8Array { + return match(event) + .with({ event_version: 1 }, tenantEventToBinaryDataV1) + .with({ event_version: 2 }, tenantEventToBinaryDataV2) + .exhaustive(); +} + +export function tenantEventToBinaryDataV1(event: TenantEventV1): Uint8Array { return match(event) .with({ type: "TenantCreated" }, ({ data }) => TenantCreatedV1.toBinary(data) @@ -30,7 +50,45 @@ export function tenantEventToBinaryData(event: TenantEvent): Uint8Array { .exhaustive(); } -export const TenantEvent = z.discriminatedUnion("type", [ +export function tenantEventToBinaryDataV2(event: TenantEventV2): Uint8Array { + return match(event) + .with({ type: "TenantOnboarded" }, ({ data }) => + TenantOnboardedV2.toBinary(data) + ) + .with({ type: "TenantOnboardDetailsUpdated" }, ({ data }) => + TenantOnboardDetailsUpdatedV2.toBinary(data) + ) + .with({ type: "TenantCertifiedAttributeAssigned" }, ({ data }) => + TenantCertifiedAttributeAssignedV2.toBinary(data) + ) + .with({ type: "TenantCertifiedAttributeRevoked" }, ({ data }) => + TenantCertifiedAttributeRevokedV2.toBinary(data) + ) + .with({ type: "TenantDeclaredAttributeAssigned" }, ({ data }) => + TenantDeclaredAttributeAssignedV2.toBinary(data) + ) + .with({ type: "TenantDeclaredAttributeRevoked" }, ({ data }) => + TenantDeclaredAttributeRevokedV2.toBinary(data) + ) + .with({ type: "TenantVerifiedAttributeAssigned" }, ({ data }) => + TenantVerifiedAttributeAssignedV2.toBinary(data) + ) + .with({ type: "TenantVerifiedAttributeRevoked" }, ({ data }) => + TenantVerifiedAttributeRevokedV2.toBinary(data) + ) + .with({ type: "TenantVerifiedAttributeExpirationUpdated" }, ({ data }) => + TenantVerifiedAttributeExpirationUpdatedV2.toBinary(data) + ) + .with({ type: "MaintenanceTenantDeleted" }, ({ data }) => + MaintenanceTenantDeletedV2.toBinary(data) + ) + .with({ type: "TenantMailAdded" }, ({ data }) => + TenantMailAddedV2.toBinary(data) + ) + .exhaustive(); +} + +export const TenantEventV1 = z.discriminatedUnion("type", [ z.object({ event_version: z.literal(1), type: z.literal("TenantCreated"), @@ -58,7 +116,101 @@ export const TenantEvent = z.discriminatedUnion("type", [ }), ]); +export type TenantEventV1 = z.infer; + +export const TenantEventV2 = z.discriminatedUnion("type", [ + z.object({ + event_version: z.literal(2), + type: z.literal("TenantOnboarded"), + data: protobufDecoder(TenantOnboardedV2), + }), + z.object({ + event_version: z.literal(2), + type: z.literal("TenantOnboardDetailsUpdated"), + data: protobufDecoder(TenantOnboardDetailsUpdatedV2), + }), + z.object({ + event_version: z.literal(2), + type: z.literal("TenantCertifiedAttributeAssigned"), + data: protobufDecoder(TenantCertifiedAttributeAssignedV2), + }), + z.object({ + event_version: z.literal(2), + type: z.literal("TenantCertifiedAttributeRevoked"), + data: protobufDecoder(TenantCertifiedAttributeRevokedV2), + }), + z.object({ + event_version: z.literal(2), + type: z.literal("TenantDeclaredAttributeAssigned"), + data: protobufDecoder(TenantDeclaredAttributeAssignedV2), + }), + z.object({ + event_version: z.literal(2), + type: z.literal("TenantDeclaredAttributeRevoked"), + data: protobufDecoder(TenantDeclaredAttributeRevokedV2), + }), + z.object({ + event_version: z.literal(2), + type: z.literal("TenantVerifiedAttributeAssigned"), + data: protobufDecoder(TenantVerifiedAttributeAssignedV2), + }), + z.object({ + event_version: z.literal(2), + type: z.literal("TenantVerifiedAttributeRevoked"), + data: protobufDecoder(TenantVerifiedAttributeRevokedV2), + }), + z.object({ + event_version: z.literal(2), + type: z.literal("TenantVerifiedAttributeExpirationUpdated"), + data: protobufDecoder(TenantVerifiedAttributeExpirationUpdatedV2), + }), + z.object({ + event_version: z.literal(2), + type: z.literal("MaintenanceTenantDeleted"), + data: protobufDecoder(MaintenanceTenantDeletedV2), + }), + z.object({ + event_version: z.literal(2), + type: z.literal("TenantMailAdded"), + data: protobufDecoder(TenantMailAddedV2), + }), +]); + +export type TenantEventV2 = z.infer; + +const eventV1 = z + .object({ + event_version: z.literal(1), + }) + .passthrough(); +const eventV2 = z + .object({ + event_version: z.literal(2), + }) + .passthrough(); + +export const TenantEvent = z + .discriminatedUnion("event_version", [eventV1, eventV2]) + .transform((obj, ctx) => { + const res = match(obj) + .with({ event_version: 1 }, () => TenantEventV1.safeParse(obj)) + .with({ event_version: 2 }, () => TenantEventV2.safeParse(obj)) + .exhaustive(); + + if (!res.success) { + res.error.issues.forEach(ctx.addIssue); + return z.NEVER; + } + return res.data; + }); + export type TenantEvent = z.infer; +export const TenantEventEnvelopeV1 = EventEnvelope(TenantEventV1); +export type TenantEventEnvelopeV1 = z.infer; + +export const TenantEventEnvelopeV2 = EventEnvelope(TenantEventV2); +export type TenantEventEnvelopeV2 = z.infer; + export const TenantEventEnvelope = EventEnvelope(TenantEvent); export type TenantEventEnvelope = z.infer; From 3fe36df3edd5211042ad260e37754ea791194d0d Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Wed, 3 Apr 2024 16:39:39 +0200 Subject: [PATCH 15/41] refactor --- packages/models/src/index.ts | 1 + packages/tenant-process/src/model/domain/toEvent.ts | 13 +++++++------ packages/tenant-readmodel-writer/src/index.ts | 4 ++-- .../src/tenantConsumerService.ts | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/models/src/index.ts b/packages/models/src/index.ts index 3d2cb6cc70..9db2f794c6 100644 --- a/packages/models/src/index.ts +++ b/packages/models/src/index.ts @@ -27,6 +27,7 @@ export * from "./tenant/tenant.js"; export * from "./tenant/tenantEvents.js"; export * from "./tenant/protobufConverterFromV1.js"; export * from "./tenant/protobufConverterFromV2.js"; +export * from "./tenant/protobufConverterToV2.js"; export * from "./user/user.js"; diff --git a/packages/tenant-process/src/model/domain/toEvent.ts b/packages/tenant-process/src/model/domain/toEvent.ts index 12712bcbf1..0914ea4ea0 100644 --- a/packages/tenant-process/src/model/domain/toEvent.ts +++ b/packages/tenant-process/src/model/domain/toEvent.ts @@ -23,6 +23,7 @@ import { TenantUnitTypeV1, tenantUnitType, TenantUnitType, + toTenantV2, } from "pagopa-interop-models"; import { match } from "ts-pattern"; @@ -157,9 +158,9 @@ export const toCreateEventTenantAdded = ( streamId: tenant.id, version: 0, event: { - event_version: 1, - type: "TenantCreated", - data: { tenant: toTenantV1(tenant) }, + event_version: 2, + type: "TenantOnboarded", + data: { tenant: toTenantV2(tenant) }, }, correlationId, }); @@ -173,10 +174,10 @@ export const toCreateEventTenantUpdated = ( streamId, version, event: { - event_version: 1, - type: "TenantUpdated", + event_version: 2, + type: "TenantOnboardDetailsUpdated", data: { - tenant: toTenantV1(updatedTenant), + tenant: toTenantV2(updatedTenant), }, }, correlationId, diff --git a/packages/tenant-readmodel-writer/src/index.ts b/packages/tenant-readmodel-writer/src/index.ts index 206862a64a..715f628a15 100644 --- a/packages/tenant-readmodel-writer/src/index.ts +++ b/packages/tenant-readmodel-writer/src/index.ts @@ -6,7 +6,7 @@ import { decodeKafkaMessage, } from "pagopa-interop-commons"; import { runConsumer } from "kafka-iam-auth"; -import { TenantEvent } from "pagopa-interop-models"; +import { TenantEventV1 } from "pagopa-interop-models"; import { handleMessage } from "./tenantConsumerService.js"; async function processMessage({ @@ -14,7 +14,7 @@ async function processMessage({ partition, }: EachMessagePayload): Promise { try { - await handleMessage(decodeKafkaMessage(message, TenantEvent)); + await handleMessage(decodeKafkaMessage(message, TenantEventV1)); logger.info( `Read model was updated. Partition number: ${partition}. Offset: ${message.offset}` ); diff --git a/packages/tenant-readmodel-writer/src/tenantConsumerService.ts b/packages/tenant-readmodel-writer/src/tenantConsumerService.ts index 25d98d9ca7..e4fb932bf8 100644 --- a/packages/tenant-readmodel-writer/src/tenantConsumerService.ts +++ b/packages/tenant-readmodel-writer/src/tenantConsumerService.ts @@ -4,12 +4,12 @@ import { readModelWriterConfig, logger, } from "pagopa-interop-commons"; -import { TenantEventEnvelope, fromTenantV1 } from "pagopa-interop-models"; +import { TenantEventEnvelopeV1, fromTenantV1 } from "pagopa-interop-models"; const { tenants } = ReadModelRepository.init(readModelWriterConfig()); export async function handleMessage( - message: TenantEventEnvelope + message: TenantEventEnvelopeV1 ): Promise { logger.info(message); await match(message) From eb4bdd08c9e2cc32c3eb2f9304d8545616653579 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Wed, 3 Apr 2024 17:00:35 +0200 Subject: [PATCH 16/41] Added extensionDate event --- packages/models/proto/v2/tenant/events.proto | 5 +++++ packages/models/src/tenant/tenantEvents.ts | 9 +++++++++ packages/tenant-readmodel-writer/src/index.ts | 4 ++-- .../tenant-readmodel-writer/src/tenantConsumerService.ts | 4 ++-- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/models/proto/v2/tenant/events.proto b/packages/models/proto/v2/tenant/events.proto index 2b3f9e68b3..152f55b210 100644 --- a/packages/models/proto/v2/tenant/events.proto +++ b/packages/models/proto/v2/tenant/events.proto @@ -47,6 +47,11 @@ message TenantVerifiedAttributeExpirationUpdatedV2 { required TenantV2 tenant = 2; } +message TenantVerifiedAttributeExtensionUpdatedV2 { + required string attributeId = 1; + required TenantV2 tenant = 2; +} + message MaintenanceTenantDeletedV2 { required string tenantId = 1; required TenantV2 tenant = 2; diff --git a/packages/models/src/tenant/tenantEvents.ts b/packages/models/src/tenant/tenantEvents.ts index d6a65bd725..e3bba39881 100644 --- a/packages/models/src/tenant/tenantEvents.ts +++ b/packages/models/src/tenant/tenantEvents.ts @@ -19,6 +19,7 @@ import { TenantVerifiedAttributeExpirationUpdatedV2, MaintenanceTenantDeletedV2, TenantMailAddedV2, + TenantVerifiedAttributeExtensionUpdatedV2, } from "../gen/v2/tenant/events.js"; import { protobufDecoder } from "../protobuf/protobuf.js"; import { EventEnvelope } from "../events/events.js"; @@ -79,6 +80,9 @@ export function tenantEventToBinaryDataV2(event: TenantEventV2): Uint8Array { .with({ type: "TenantVerifiedAttributeExpirationUpdated" }, ({ data }) => TenantVerifiedAttributeExpirationUpdatedV2.toBinary(data) ) + .with({ type: "TenantVerifiedAttributeExtensionUpdated" }, ({ data }) => + TenantVerifiedAttributeExtensionUpdatedV2.toBinary(data) + ) .with({ type: "MaintenanceTenantDeleted" }, ({ data }) => MaintenanceTenantDeletedV2.toBinary(data) ) @@ -164,6 +168,11 @@ export const TenantEventV2 = z.discriminatedUnion("type", [ type: z.literal("TenantVerifiedAttributeExpirationUpdated"), data: protobufDecoder(TenantVerifiedAttributeExpirationUpdatedV2), }), + z.object({ + event_version: z.literal(2), + type: z.literal("TenantVerifiedAttributeExtensionUpdated"), + data: protobufDecoder(TenantVerifiedAttributeExtensionUpdatedV2), + }), z.object({ event_version: z.literal(2), type: z.literal("MaintenanceTenantDeleted"), diff --git a/packages/tenant-readmodel-writer/src/index.ts b/packages/tenant-readmodel-writer/src/index.ts index 206862a64a..715f628a15 100644 --- a/packages/tenant-readmodel-writer/src/index.ts +++ b/packages/tenant-readmodel-writer/src/index.ts @@ -6,7 +6,7 @@ import { decodeKafkaMessage, } from "pagopa-interop-commons"; import { runConsumer } from "kafka-iam-auth"; -import { TenantEvent } from "pagopa-interop-models"; +import { TenantEventV1 } from "pagopa-interop-models"; import { handleMessage } from "./tenantConsumerService.js"; async function processMessage({ @@ -14,7 +14,7 @@ async function processMessage({ partition, }: EachMessagePayload): Promise { try { - await handleMessage(decodeKafkaMessage(message, TenantEvent)); + await handleMessage(decodeKafkaMessage(message, TenantEventV1)); logger.info( `Read model was updated. Partition number: ${partition}. Offset: ${message.offset}` ); diff --git a/packages/tenant-readmodel-writer/src/tenantConsumerService.ts b/packages/tenant-readmodel-writer/src/tenantConsumerService.ts index 25d98d9ca7..e4fb932bf8 100644 --- a/packages/tenant-readmodel-writer/src/tenantConsumerService.ts +++ b/packages/tenant-readmodel-writer/src/tenantConsumerService.ts @@ -4,12 +4,12 @@ import { readModelWriterConfig, logger, } from "pagopa-interop-commons"; -import { TenantEventEnvelope, fromTenantV1 } from "pagopa-interop-models"; +import { TenantEventEnvelopeV1, fromTenantV1 } from "pagopa-interop-models"; const { tenants } = ReadModelRepository.init(readModelWriterConfig()); export async function handleMessage( - message: TenantEventEnvelope + message: TenantEventEnvelopeV1 ): Promise { logger.info(message); await match(message) From a7b31ddca0a318da9c48cc581d889d03289b28a9 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Wed, 3 Apr 2024 17:11:03 +0200 Subject: [PATCH 17/41] refactor and use new events --- .../src/model/domain/toEvent.ts | 45 ++++++++++++++++++- .../src/services/tenantService.ts | 20 +++++---- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/packages/tenant-process/src/model/domain/toEvent.ts b/packages/tenant-process/src/model/domain/toEvent.ts index 0914ea4ea0..fc00bf6d90 100644 --- a/packages/tenant-process/src/model/domain/toEvent.ts +++ b/packages/tenant-process/src/model/domain/toEvent.ts @@ -23,6 +23,7 @@ import { TenantUnitTypeV1, tenantUnitType, TenantUnitType, + AttributeId, toTenantV2, } from "pagopa-interop-models"; import { match } from "ts-pattern"; @@ -151,7 +152,7 @@ export const toTenantV1 = (tenant: Tenant): TenantV1 => ({ : undefined, }); -export const toCreateEventTenantAdded = ( +export const toCreateEventTenantOnboarded = ( tenant: Tenant, correlationId: string ): CreateEvent => ({ @@ -165,7 +166,7 @@ export const toCreateEventTenantAdded = ( correlationId, }); -export const toCreateEventTenantUpdated = ( +export const toCreateEventTenantOnboardDetailsUpdated = ( streamId: string, version: number, updatedTenant: Tenant, @@ -182,3 +183,43 @@ export const toCreateEventTenantUpdated = ( }, correlationId, }); + +export const toCreateEventTenantVerifiedAttributeExtensionUpdated = ( + streamId: string, + version: number, + updatedTenant: Tenant, + attributeId: AttributeId, + correlationId: string +): CreateEvent => ({ + streamId, + version, + event: { + event_version: 2, + type: "TenantVerifiedAttributeExtensionUpdated", + data: { + attributeId, + tenant: toTenantV2(updatedTenant), + }, + }, + correlationId, +}); + +export const toCreateEventTenantVerifiedAttributeExpirationUpdated = ( + streamId: string, + version: number, + updatedTenant: Tenant, + attributeId: AttributeId, + correlationId: string +): CreateEvent => ({ + streamId, + version, + event: { + event_version: 2, + type: "TenantVerifiedAttributeExpirationUpdated", + data: { + attributeId, + tenant: toTenantV2(updatedTenant), + }, + }, + correlationId, +}); diff --git a/packages/tenant-process/src/services/tenantService.ts b/packages/tenant-process/src/services/tenantService.ts index c3c0fb545f..ec3d784905 100644 --- a/packages/tenant-process/src/services/tenantService.ts +++ b/packages/tenant-process/src/services/tenantService.ts @@ -10,13 +10,15 @@ import { generateId, tenantEventToBinaryData, } from "pagopa-interop-models"; -import { - toCreateEventTenantAdded, - toCreateEventTenantUpdated, -} from "../model/domain/toEvent.js"; import { UpdateVerifiedTenantAttributeSeed } from "../model/domain/models.js"; import { ApiSelfcareTenantSeed } from "../model/types.js"; import { tenantNotFound } from "../model/domain/errors.js"; +import { + toCreateEventTenantVerifiedAttributeExpirationUpdated, + toCreateEventTenantVerifiedAttributeExtensionUpdated, + toCreateEventTenantOnboardDetailsUpdated, + toCreateEventTenantOnboarded, +} from "../model/domain/toEvent.js"; import { assertOrganizationIsInAttributeVerifiers, assertValidExpirationDate, @@ -114,10 +116,11 @@ export function tenantServiceBuilder( updatedAt: new Date(), }; - const event = toCreateEventTenantUpdated( + const event = toCreateEventTenantVerifiedAttributeExtensionUpdated( tenant.data.id, tenant.metadata.version, updatedTenant, + attributeId, correlationId ); await repository.createEvent(event); @@ -173,10 +176,11 @@ export function tenantServiceBuilder( ], updatedAt: new Date(), }; - const event = toCreateEventTenantUpdated( + const event = toCreateEventTenantVerifiedAttributeExpirationUpdated( tenant.data.id, tenant.metadata.version, updatedTenant, + attributeId, correlationId ); await repository.createEvent(event); @@ -226,7 +230,7 @@ export function tenantServiceBuilder( `Creating tenant with external id ${tenantSeed.externalId} via SelfCare request"` ); return await repository.createEvent( - toCreateEventTenantUpdated( + toCreateEventTenantOnboardDetailsUpdated( existingTenant.data.id, existingTenant.metadata.version, updatedTenant, @@ -249,7 +253,7 @@ export function tenantServiceBuilder( createdAt: new Date(), }; return await repository.createEvent( - toCreateEventTenantAdded(newTenant, correlationId) + toCreateEventTenantOnboarded(newTenant, correlationId) ); } }, From 7ee4a3e5d5c2e71d6edeb9c7ee283c931c964ede Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Wed, 3 Apr 2024 17:50:54 +0200 Subject: [PATCH 18/41] updated events in utils.ts --- packages/tenant-process/test/utils.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/tenant-process/test/utils.ts b/packages/tenant-process/test/utils.ts index dbea127ce6..cd4dea5b28 100644 --- a/packages/tenant-process/test/utils.ts +++ b/packages/tenant-process/test/utils.ts @@ -9,15 +9,15 @@ import { Descriptor, EService, Tenant, - TenantEvent, + TenantEventV2, agreementState, descriptorState, technology, - tenantEventToBinaryData, + tenantEventToBinaryDataV2, + toTenantV2, } from "pagopa-interop-models"; import { IDatabase } from "pg-promise"; import { v4 as uuidv4 } from "uuid"; -import { toTenantV1 } from "../src/model/domain/toEvent.js"; export const writeTenantInReadmodel = async ( tenant: Tenant, @@ -35,16 +35,17 @@ export const writeTenantInEventstore = async ( tenant: Tenant, postgresDB: IDatabase ): Promise => { - const tenantEvent: TenantEvent = { - type: "TenantCreated", - data: { tenant: toTenantV1(tenant) }, + const tenantEvent: TenantEventV2 = { + type: "TenantOnboarded", + event_version: 2, + data: { tenant: toTenantV2(tenant) }, }; const eventToWrite = { stream_id: tenantEvent.data.tenant?.id, version: 0, type: tenantEvent.type, - event_version: 1, - data: Buffer.from(tenantEventToBinaryData(tenantEvent)), + event_version: tenantEvent.event_version, + data: Buffer.from(tenantEventToBinaryDataV2(tenantEvent)), }; await postgresDB.none( "INSERT INTO tenant.events(stream_id, version, type, event_version, data) VALUES ($1, $2, $3, $4, $5)", From 1d942f94f2c0de64a0a6577989d9af8a64fb5f60 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Wed, 3 Apr 2024 18:11:26 +0200 Subject: [PATCH 19/41] added converterV1 file --- .../src/model/domain/toEvent.ts | 147 ----------------- .../test/tenant.integration.test.ts | 2 + .../test/converterV1.ts | 150 ++++++++++++++++++ .../test/tsconfig.json | 5 + 4 files changed, 157 insertions(+), 147 deletions(-) create mode 100644 packages/tenant-readmodel-writer/test/converterV1.ts create mode 100644 packages/tenant-readmodel-writer/test/tsconfig.json diff --git a/packages/tenant-process/src/model/domain/toEvent.ts b/packages/tenant-process/src/model/domain/toEvent.ts index fc00bf6d90..9dd0e67845 100644 --- a/packages/tenant-process/src/model/domain/toEvent.ts +++ b/packages/tenant-process/src/model/domain/toEvent.ts @@ -1,157 +1,10 @@ import { CreateEvent } from "pagopa-interop-commons"; import { - TenantMail, - TenantMailKind, Tenant, - TenantAttribute, - TenantAttributeV1, - TenantFeature, - TenantFeatureV1, - TenantKind, - TenantKindV1, - TenantMailKindV1, - TenantMailV1, - TenantRevoker, - TenantRevokerV1, - TenantV1, - TenantVerifier, - TenantVerifierV1, - tenantMailKind, - tenantKind, TenantEvent, - tenantAttributeType, - TenantUnitTypeV1, - tenantUnitType, - TenantUnitType, AttributeId, toTenantV2, } from "pagopa-interop-models"; -import { match } from "ts-pattern"; - -export function toFeatureV1(feature: TenantFeature): TenantFeatureV1 { - return match(feature) - .with({ type: "PersistentCertifier" }, (feature) => ({ - sealedValue: { - oneofKind: "certifier", - certifier: { - certifierId: feature.certifierId, - }, - }, - })) - .exhaustive(); -} - -export function toTenantVerifierV1(verifier: TenantVerifier): TenantVerifierV1 { - return { - id: verifier.id, - verificationDate: BigInt(verifier.verificationDate.getTime()), - expirationDate: verifier.expirationDate - ? BigInt(verifier.expirationDate?.getTime()) - : undefined, - extensionDate: verifier.extensionDate - ? BigInt(verifier.extensionDate?.getTime()) - : undefined, - }; -} - -export function toTenantRevokerV1(revoker: TenantRevoker): TenantRevokerV1 { - return { - id: revoker.id, - verificationDate: BigInt(revoker.verificationDate.getTime()), - expirationDate: revoker.expirationDate - ? BigInt(revoker.expirationDate?.getTime()) - : undefined, - extensionDate: revoker.extensionDate - ? BigInt(revoker.extensionDate?.getTime()) - : undefined, - revocationDate: BigInt(revoker.revocationDate.getTime()), - }; -} - -export function toAttributeV1(input: TenantAttribute): TenantAttributeV1 { - return match(input) - .with({ type: tenantAttributeType.CERTIFIED }, (attribute) => ({ - sealedValue: { - oneofKind: "certifiedAttribute", - certifiedAttribute: { - id: attribute.id, - assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), - revocationTimestamp: attribute.revocationTimestamp - ? BigInt(attribute.revocationTimestamp?.getTime()) - : undefined, - }, - }, - })) - .with({ type: tenantAttributeType.VERIFIED }, (attribute) => ({ - sealedValue: { - oneofKind: "verifiedAttribute", - verifiedAttribute: { - id: attribute.id, - assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), - verifiedBy: attribute.verifiedBy.map(toTenantVerifierV1), - revokedBy: attribute.revokedBy.map(toTenantRevokerV1), - }, - }, - })) - .with({ type: tenantAttributeType.DECLARED }, (attribute) => ({ - sealedValue: { - oneofKind: "declaredAttribute", - declaredAttribute: { - id: attribute.id, - assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), - }, - }, - })) - .exhaustive(); -} - -export function toTenantMailV1(mail: TenantMail): TenantMailV1 { - return { - kind: toTenantMailKindV1(mail.kind), - address: mail.address, - createdAt: BigInt(mail.createdAt.getTime()), - description: mail.description ?? undefined, - }; -} - -export function toTenantMailKindV1(kind: TenantMailKind): TenantMailKindV1 { - return match(kind) - .with(tenantMailKind.ContactEmail, () => TenantMailKindV1.CONTACT_EMAIL) - .with(tenantMailKind.DigitalAddress, () => TenantMailKindV1.DIGITAL_ADDRESS) - .exhaustive(); -} - -export function toTenantKindV1(input: TenantKind): TenantKindV1 { - return match(input) - .with(tenantKind.GSP, () => TenantKindV1.GSP) - .with(tenantKind.PA, () => TenantKindV1.PA) - .with(tenantKind.PRIVATE, () => TenantKindV1.PRIVATE) - .exhaustive(); -} - -export function toTenantUnitTypeV1(input: TenantUnitType): TenantUnitTypeV1 { - return match(input) - .with(tenantUnitType.AOO, () => TenantUnitTypeV1.AOO) - .with(tenantUnitType.UO, () => TenantUnitTypeV1.UO) - .exhaustive(); -} - -export const toTenantV1 = (tenant: Tenant): TenantV1 => ({ - ...tenant, - features: tenant.features.map(toFeatureV1), - attributes: tenant.attributes.map(toAttributeV1), - createdAt: BigInt(tenant.createdAt.getTime()), - updatedAt: tenant.updatedAt ? BigInt(tenant.updatedAt.getTime()) : undefined, - mails: tenant.mails.map(toTenantMailV1), - kind: tenant.kind ? toTenantKindV1(tenant.kind) : undefined, - onboardedAt: tenant.createdAt - ? BigInt(tenant.createdAt.getTime()) - : undefined, - subUnitType: tenant.subUnitType - ? toTenantUnitTypeV1(tenant.subUnitType) - : undefined, -}); - export const toCreateEventTenantOnboarded = ( tenant: Tenant, correlationId: string diff --git a/packages/tenant-process/test/tenant.integration.test.ts b/packages/tenant-process/test/tenant.integration.test.ts index 1a4687e962..eabb511012 100644 --- a/packages/tenant-process/test/tenant.integration.test.ts +++ b/packages/tenant-process/test/tenant.integration.test.ts @@ -949,12 +949,14 @@ describe("Integration tests", () => { await addOneTenant(tenant2, postgresDB, tenants); await addOneTenant(tenant3, postgresDB, tenants); const tenantBySelfcareId = await readModelService.getTenantBySelfcareId( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion tenant1.selfcareId! ); expect(tenantBySelfcareId?.data).toEqual(tenant1); }); it("should not get the tenant by selfcareId if it isn't in DB", async () => { const tenantBySelfcareId = await readModelService.getTenantBySelfcareId( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion tenant1.selfcareId! ); expect(tenantBySelfcareId?.data.selfcareId).toBeUndefined(); diff --git a/packages/tenant-readmodel-writer/test/converterV1.ts b/packages/tenant-readmodel-writer/test/converterV1.ts new file mode 100644 index 0000000000..89978b03c0 --- /dev/null +++ b/packages/tenant-readmodel-writer/test/converterV1.ts @@ -0,0 +1,150 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { + TenantMail, + TenantMailKind, + Tenant, + TenantAttribute, + TenantAttributeV1, + TenantFeature, + TenantFeatureV1, + TenantKind, + TenantKindV1, + TenantMailKindV1, + TenantMailV1, + TenantRevoker, + TenantRevokerV1, + TenantV1, + TenantVerifier, + TenantVerifierV1, + tenantMailKind, + tenantKind, + tenantAttributeType, + TenantUnitTypeV1, + tenantUnitType, + TenantUnitType, +} from "pagopa-interop-models"; +import { match } from "ts-pattern"; + +export function toFeatureV1(feature: TenantFeature): TenantFeatureV1 { + return match(feature) + .with({ type: "PersistentCertifier" }, (feature) => ({ + sealedValue: { + oneofKind: "certifier", + certifier: { + certifierId: feature.certifierId, + }, + }, + })) + .exhaustive(); +} + +export function toTenantVerifierV1(verifier: TenantVerifier): TenantVerifierV1 { + return { + id: verifier.id, + verificationDate: BigInt(verifier.verificationDate.getTime()), + expirationDate: verifier.expirationDate + ? BigInt(verifier.expirationDate?.getTime()) + : undefined, + extensionDate: verifier.extensionDate + ? BigInt(verifier.extensionDate?.getTime()) + : undefined, + }; +} + +export function toTenantRevokerV1(revoker: TenantRevoker): TenantRevokerV1 { + return { + id: revoker.id, + verificationDate: BigInt(revoker.verificationDate.getTime()), + expirationDate: revoker.expirationDate + ? BigInt(revoker.expirationDate?.getTime()) + : undefined, + extensionDate: revoker.extensionDate + ? BigInt(revoker.extensionDate?.getTime()) + : undefined, + revocationDate: BigInt(revoker.revocationDate.getTime()), + }; +} + +export function toAttributeV1(input: TenantAttribute): TenantAttributeV1 { + return match(input) + .with({ type: tenantAttributeType.CERTIFIED }, (attribute) => ({ + sealedValue: { + oneofKind: "certifiedAttribute", + certifiedAttribute: { + id: attribute.id, + assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), + revocationTimestamp: attribute.revocationTimestamp + ? BigInt(attribute.revocationTimestamp?.getTime()) + : undefined, + }, + }, + })) + .with({ type: tenantAttributeType.VERIFIED }, (attribute) => ({ + sealedValue: { + oneofKind: "verifiedAttribute", + verifiedAttribute: { + id: attribute.id, + assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), + verifiedBy: attribute.verifiedBy.map(toTenantVerifierV1), + revokedBy: attribute.revokedBy.map(toTenantRevokerV1), + }, + }, + })) + .with({ type: tenantAttributeType.DECLARED }, (attribute) => ({ + sealedValue: { + oneofKind: "declaredAttribute", + declaredAttribute: { + id: attribute.id, + assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), + }, + }, + })) + .exhaustive(); +} + +export function toTenantMailV1(mail: TenantMail): TenantMailV1 { + return { + kind: toTenantMailKindV1(mail.kind), + address: mail.address, + createdAt: BigInt(mail.createdAt.getTime()), + description: mail.description ?? undefined, + }; +} + +export function toTenantMailKindV1(kind: TenantMailKind): TenantMailKindV1 { + return match(kind) + .with(tenantMailKind.ContactEmail, () => TenantMailKindV1.CONTACT_EMAIL) + .with(tenantMailKind.DigitalAddress, () => TenantMailKindV1.DIGITAL_ADDRESS) + .exhaustive(); +} + +export function toTenantKindV1(input: TenantKind): TenantKindV1 { + return match(input) + .with(tenantKind.GSP, () => TenantKindV1.GSP) + .with(tenantKind.PA, () => TenantKindV1.PA) + .with(tenantKind.PRIVATE, () => TenantKindV1.PRIVATE) + .exhaustive(); +} + +export function toTenantUnitTypeV1(input: TenantUnitType): TenantUnitTypeV1 { + return match(input) + .with(tenantUnitType.AOO, () => TenantUnitTypeV1.AOO) + .with(tenantUnitType.UO, () => TenantUnitTypeV1.UO) + .exhaustive(); +} + +export const toTenantV1 = (tenant: Tenant): TenantV1 => ({ + ...tenant, + features: tenant.features.map(toFeatureV1), + attributes: tenant.attributes.map(toAttributeV1), + createdAt: BigInt(tenant.createdAt.getTime()), + updatedAt: tenant.updatedAt ? BigInt(tenant.updatedAt.getTime()) : undefined, + mails: tenant.mails.map(toTenantMailV1), + kind: tenant.kind ? toTenantKindV1(tenant.kind) : undefined, + onboardedAt: tenant.createdAt + ? BigInt(tenant.createdAt.getTime()) + : undefined, + subUnitType: tenant.subUnitType + ? toTenantUnitTypeV1(tenant.subUnitType) + : undefined, +}); diff --git a/packages/tenant-readmodel-writer/test/tsconfig.json b/packages/tenant-readmodel-writer/test/tsconfig.json new file mode 100644 index 0000000000..c54db5e9f2 --- /dev/null +++ b/packages/tenant-readmodel-writer/test/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../tsconfig.json", + "include": ["."] + } + \ No newline at end of file From 6eee4d224e83ea8a0b5f22e39d0b6212ada972ba Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Wed, 3 Apr 2024 18:18:26 +0200 Subject: [PATCH 20/41] Removed not needed line --- packages/tenant-readmodel-writer/test/converterV1.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/tenant-readmodel-writer/test/converterV1.ts b/packages/tenant-readmodel-writer/test/converterV1.ts index 89978b03c0..32b619aa21 100644 --- a/packages/tenant-readmodel-writer/test/converterV1.ts +++ b/packages/tenant-readmodel-writer/test/converterV1.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ import { TenantMail, TenantMailKind, From 5fc0a6d2fd9a4a5bfb2abfa9fbd9a473f3c2523f Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Wed, 3 Apr 2024 18:51:36 +0200 Subject: [PATCH 21/41] added handleMessageV2 --- packages/tenant-readmodel-writer/src/index.ts | 19 +++++-- ...rService.ts => tenantConsumerServiceV1.ts} | 2 +- .../src/tenantConsumerServiceV2.ts | 50 +++++++++++++++++++ 3 files changed, 66 insertions(+), 5 deletions(-) rename packages/tenant-readmodel-writer/src/{tenantConsumerService.ts => tenantConsumerServiceV1.ts} (97%) create mode 100644 packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts diff --git a/packages/tenant-readmodel-writer/src/index.ts b/packages/tenant-readmodel-writer/src/index.ts index 715f628a15..0828d8878a 100644 --- a/packages/tenant-readmodel-writer/src/index.ts +++ b/packages/tenant-readmodel-writer/src/index.ts @@ -4,17 +4,29 @@ import { readModelWriterConfig, tenantTopicConfig, decodeKafkaMessage, + ReadModelRepository, } from "pagopa-interop-commons"; import { runConsumer } from "kafka-iam-auth"; -import { TenantEventV1 } from "pagopa-interop-models"; -import { handleMessage } from "./tenantConsumerService.js"; +import { TenantEvent } from "pagopa-interop-models"; +import { match } from "ts-pattern"; +import { handleMessageV2 } from "./tenantConsumerServiceV2.js"; +import { handleMessageV1 } from "./tenantConsumerServiceV1.js"; + +const config = readModelWriterConfig(); +const { tenants } = ReadModelRepository.init(config); async function processMessage({ message, partition, }: EachMessagePayload): Promise { try { - await handleMessage(decodeKafkaMessage(message, TenantEventV1)); + // await handleMessage(decodeKafkaMessage(message, TenantEventV1)); + const decodedMesssage = decodeKafkaMessage(message, TenantEvent); + + await match(decodedMesssage) + .with({ event_version: 1 }, (msg) => handleMessageV1(msg)) + .with({ event_version: 2 }, (msg) => handleMessageV2(msg, tenants)) + .exhaustive(); logger.info( `Read model was updated. Partition number: ${partition}. Offset: ${message.offset}` ); @@ -25,6 +37,5 @@ async function processMessage({ } } -const config = readModelWriterConfig(); const { tenantTopic } = tenantTopicConfig(); await runConsumer(config, [tenantTopic], processMessage).catch(logger.error); diff --git a/packages/tenant-readmodel-writer/src/tenantConsumerService.ts b/packages/tenant-readmodel-writer/src/tenantConsumerServiceV1.ts similarity index 97% rename from packages/tenant-readmodel-writer/src/tenantConsumerService.ts rename to packages/tenant-readmodel-writer/src/tenantConsumerServiceV1.ts index e4fb932bf8..37a0c641b7 100644 --- a/packages/tenant-readmodel-writer/src/tenantConsumerService.ts +++ b/packages/tenant-readmodel-writer/src/tenantConsumerServiceV1.ts @@ -8,7 +8,7 @@ import { TenantEventEnvelopeV1, fromTenantV1 } from "pagopa-interop-models"; const { tenants } = ReadModelRepository.init(readModelWriterConfig()); -export async function handleMessage( +export async function handleMessageV1( message: TenantEventEnvelopeV1 ): Promise { logger.info(message); diff --git a/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts b/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts new file mode 100644 index 0000000000..2a553623b6 --- /dev/null +++ b/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts @@ -0,0 +1,50 @@ +import { TenantCollection, logger } from "pagopa-interop-commons"; +import { TenantEventEnvelopeV2, fromTenantV2 } from "pagopa-interop-models"; +import { match } from "ts-pattern"; + +export async function handleMessageV2( + message: TenantEventEnvelopeV2, + tenants: TenantCollection +): Promise { + logger.info(message); + + const tenant = message.data.tenant; + + await match(message) + .with({ type: "MaintenanceTenantDeleted" }, async (message) => { + await tenants.deleteOne({ + "data.id": message.stream_id, + "metadata.version": { $lt: message.version }, + }); + }) + .with( + { type: "TenantOnboarded" }, + { type: "TenantOnboardDetailsUpdated" }, + { type: "TenantCertifiedAttributeAssigned" }, + { type: "TenantCertifiedAttributeRevoked" }, + { type: "TenantDeclaredAttributeAssigned" }, + { type: "TenantDeclaredAttributeRevoked" }, + { type: "TenantVerifiedAttributeAssigned" }, + { type: "TenantVerifiedAttributeRevoked" }, + { type: "TenantVerifiedAttributeExpirationUpdated" }, + { type: "TenantVerifiedAttributeExtensionUpdated" }, + { type: "TenantMailAdded" }, + async (message) => + await tenants.updateOne( + { + "data.id": message.stream_id, + "metadata.version": { $lt: message.version }, + }, + { + $set: { + data: tenant ? fromTenantV2(tenant) : undefined, + metadata: { + version: message.version, + }, + }, + }, + { upsert: true } + ) + ) + .exhaustive(); +} From 3804536cd701339f99ac6b02b97a57dae3014a52 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Thu, 4 Apr 2024 11:36:00 +0200 Subject: [PATCH 22/41] updated test with eventV2 --- .../src/services/tenantService.ts | 2 - .../test/tenant.integration.test.ts | 187 +++--------------- 2 files changed, 30 insertions(+), 159 deletions(-) diff --git a/packages/tenant-process/src/services/tenantService.ts b/packages/tenant-process/src/services/tenantService.ts index 43d44bb3bb..65fe47b3be 100644 --- a/packages/tenant-process/src/services/tenantService.ts +++ b/packages/tenant-process/src/services/tenantService.ts @@ -125,7 +125,6 @@ export function tenantServiceBuilder( await repository.createEvent(event); return updatedTenant; }, - async updateTenantVerifiedAttribute({ verifierId, tenantId, @@ -185,7 +184,6 @@ export function tenantServiceBuilder( await repository.createEvent(event); return updatedTenant; }, - async selfcareUpsertTenant({ tenantSeed, authData, diff --git a/packages/tenant-process/test/tenant.integration.test.ts b/packages/tenant-process/test/tenant.integration.test.ts index ab3cdd6267..1501dd6c46 100644 --- a/packages/tenant-process/test/tenant.integration.test.ts +++ b/packages/tenant-process/test/tenant.integration.test.ts @@ -29,12 +29,16 @@ import { Tenant, TenantCreatedV1, TenantId, + TenantOnboardDetailsUpdatedV2, TenantUpdatedV1, + TenantVerifiedAttributeExpirationUpdatedV2, + TenantVerifiedAttributeExtensionUpdatedV2, descriptorState, generateId, operationForbidden, protobufDecoder, tenantKind, + toTenantV2, unsafeBrandId, } from "pagopa-interop-models"; import { StartedTestContainer } from "testcontainers"; @@ -173,11 +177,12 @@ describe("Integration tests", () => { expect(writtenEvent).toMatchObject({ stream_id: tenant.id, version: "1", - type: "TenantUpdated", + type: "TenantOnboardDetailsUpdated", }); - const writtenPayload: TenantUpdatedV1 | undefined = protobufDecoder( - TenantUpdatedV1 - ).parse(writtenEvent?.data); + const writtenPayload: TenantOnboardDetailsUpdatedV2 | undefined = + protobufDecoder(TenantOnboardDetailsUpdatedV2).parse( + writtenEvent?.data + ); const updatedTenant: Tenant = { ...tenant, @@ -186,7 +191,7 @@ describe("Integration tests", () => { updatedAt: new Date(Number(writtenPayload.tenant?.updatedAt)), }; - expect(writtenPayload.tenant).toEqual(toTenantV1(updatedTenant)); + expect(writtenPayload.tenant).toEqual(toTenantV2(updatedTenant)); }); it("Should create a tenant by the upsert if it does not exist", async () => { const mockAuthData = getMockAuthData(); @@ -216,7 +221,7 @@ describe("Integration tests", () => { expect(writtenEvent).toMatchObject({ stream_id: id, version: "0", - type: "TenantCreated", + type: "TenantOnboarded", }); const writtenPayload: TenantCreatedV1 | undefined = protobufDecoder( TenantCreatedV1 @@ -320,13 +325,19 @@ describe("Integration tests", () => { expect(writtenEvent).toBeDefined(); expect(writtenEvent.stream_id).toBe(tenant.id); expect(writtenEvent.version).toBe("1"); - expect(writtenEvent.type).toBe("TenantUpdated"); - const writtenPayload: TenantUpdatedV1 | undefined = protobufDecoder( - TenantUpdatedV1 + expect(writtenEvent.type).toBe( + "TenantVerifiedAttributeExpirationUpdated" + ); + const writtenPayload: + | TenantVerifiedAttributeExpirationUpdatedV2 + | undefined = protobufDecoder( + TenantVerifiedAttributeExpirationUpdatedV2 ).parse(writtenEvent.data); if (!writtenPayload) { - fail("impossible to decode TenantUpdatedV1 data"); + fail( + "impossible to decode TenantVerifiedAttributeExpirationUpdatedV2 data" + ); } const updatedTenant: Tenant = { @@ -334,7 +345,7 @@ describe("Integration tests", () => { updatedAt: new Date(Number(writtenPayload.tenant?.updatedAt)), }; - expect(writtenPayload.tenant).toEqual(toTenantV1(updatedTenant)); + expect(writtenPayload.tenant).toEqual(toTenantV2(updatedTenant)); }); it("Should throw tenantNotFound when tenant doesn't exist", async () => { expect( @@ -413,148 +424,6 @@ describe("Integration tests", () => { ); }); }); - describe("updateTenantVerifiedAttribute", async () => { - const expirationDate = new Date( - currentDate.setDate(currentDate.getDate() + 1) - ); - - const updateVerifiedTenantAttributeSeed: UpdateVerifiedTenantAttributeSeed = - { - expirationDate: expirationDate.toISOString(), - }; - - const tenant: Tenant = { - ...mockTenant, - attributes: [ - { - ...mockVerifiedTenantAttribute, - verifiedBy: [ - { - ...mockVerifiedBy, - expirationDate, - }, - ], - }, - ], - updatedAt: currentDate, - name: "A tenant", - }; - const attributeId = tenant.attributes.map((a) => a.id)[0]; - const verifierId = mockVerifiedBy.id; - it("Should update the expirationDate", async () => { - await addOneTenant(tenant, postgresDB, tenants); - await tenantService.updateTenantVerifiedAttribute({ - verifierId, - tenantId: tenant.id, - attributeId, - updateVerifiedTenantAttributeSeed, - correlationId: generateId(), - }); - const writtenEvent: StoredEvent | undefined = - await readLastEventByStreamId( - tenant.id, - eventStoreSchema.tenant, - postgresDB - ); - if (!writtenEvent) { - fail("Creation fails: tenant not found in event-store"); - } - expect(writtenEvent).toBeDefined(); - expect(writtenEvent.stream_id).toBe(tenant.id); - expect(writtenEvent.version).toBe("1"); - expect(writtenEvent.type).toBe("TenantUpdated"); - const writtenPayload: TenantUpdatedV1 | undefined = protobufDecoder( - TenantUpdatedV1 - ).parse(writtenEvent.data); - - if (!writtenPayload) { - fail("impossible to decode TenantUpdatedV1 data"); - } - - const updatedTenant: Tenant = { - ...tenant, - updatedAt: new Date(Number(writtenPayload.tenant?.updatedAt)), - }; - - expect(writtenPayload.tenant).toEqual(toTenantV1(updatedTenant)); - }); - it("Should throw tenantNotFound when tenant doesn't exist", async () => { - expect( - tenantService.updateTenantVerifiedAttribute({ - verifierId, - tenantId: tenant.id, - attributeId, - updateVerifiedTenantAttributeSeed, - correlationId: generateId(), - }) - ).rejects.toThrowError(tenantNotFound(tenant.id)); - }); - - it("Should throw expirationDateCannotBeInThePast when expiration date is in the past", async () => { - const expirationDateinPast = new Date( - currentDate.setDate(currentDate.getDate() - 3) - ); - - const updateVerifiedTenantAttributeSeed: UpdateVerifiedTenantAttributeSeed = - { - expirationDate: expirationDateinPast.toISOString(), - }; - - await addOneTenant(tenant, postgresDB, tenants); - expect( - tenantService.updateTenantVerifiedAttribute({ - verifierId, - tenantId: tenant.id, - attributeId, - updateVerifiedTenantAttributeSeed, - correlationId: generateId(), - }) - ).rejects.toThrowError( - expirationDateCannotBeInThePast(expirationDateinPast) - ); - }); - it("Should throw verifiedAttributeNotFoundInTenant when the attribute is not verified", async () => { - const updatedCertifiedTenant: Tenant = { - ...mockTenant, - attributes: [{ ...getMockCertifiedTenantAttribute() }], - updatedAt: currentDate, - name: "A updatedCertifiedTenant", - }; - const attributeId = updatedCertifiedTenant.attributes.map( - (a) => a.id - )[0]; - await addOneTenant(updatedCertifiedTenant, postgresDB, tenants); - expect( - tenantService.updateTenantVerifiedAttribute({ - verifierId: generateId(), - tenantId: updatedCertifiedTenant.id, - attributeId, - updateVerifiedTenantAttributeSeed, - correlationId: generateId(), - }) - ).rejects.toThrowError( - verifiedAttributeNotFoundInTenant( - updatedCertifiedTenant.id, - attributeId - ) - ); - }); - it("Should throw organizationNotFoundInVerifiers when the organization is not verified", async () => { - await addOneTenant(tenant, postgresDB, tenants); - const verifierId = generateId(); - expect( - tenantService.updateTenantVerifiedAttribute({ - verifierId, - tenantId: tenant.id, - attributeId, - updateVerifiedTenantAttributeSeed, - correlationId: generateId(), - }) - ).rejects.toThrowError( - organizationNotFoundInVerifiers(verifierId, tenant.id, attributeId) - ); - }); - }); describe("updateVerifiedAttributeExtensionDate", async () => { const correlationId = generateId(); const expirationDate = new Date( @@ -604,9 +473,13 @@ describe("Integration tests", () => { } expect(writtenEvent.stream_id).toBe(tenant.id); expect(writtenEvent.version).toBe("1"); - expect(writtenEvent.type).toBe("TenantUpdated"); - const writtenPayload: TenantUpdatedV1 | undefined = protobufDecoder( - TenantUpdatedV1 + expect(writtenEvent.type).toBe( + "TenantVerifiedAttributeExtensionUpdated" + ); + const writtenPayload: + | TenantVerifiedAttributeExtensionUpdatedV2 + | undefined = protobufDecoder( + TenantVerifiedAttributeExtensionUpdatedV2 ).parse(writtenEvent.data); const updatedTenant: Tenant = { @@ -625,7 +498,7 @@ describe("Integration tests", () => { ], updatedAt: new Date(Number(writtenPayload.tenant?.updatedAt)), }; - expect(writtenPayload.tenant).toEqual(toTenantV1(updatedTenant)); + expect(writtenPayload.tenant).toEqual(toTenantV2(updatedTenant)); }); it("Should throw tenantNotFound when tenant doesn't exist", async () => { const correlationId = generateId(); From 1b6d2fb5fc09c045af69ad29c7adf50cb57cc6da Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Thu, 4 Apr 2024 11:50:58 +0200 Subject: [PATCH 23/41] Fix test --- packages/tenant-process/test/tenant.integration.test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/tenant-process/test/tenant.integration.test.ts b/packages/tenant-process/test/tenant.integration.test.ts index 1501dd6c46..573347db4e 100644 --- a/packages/tenant-process/test/tenant.integration.test.ts +++ b/packages/tenant-process/test/tenant.integration.test.ts @@ -30,6 +30,7 @@ import { TenantCreatedV1, TenantId, TenantOnboardDetailsUpdatedV2, + TenantOnboardedV2, TenantUpdatedV1, TenantVerifiedAttributeExpirationUpdatedV2, TenantVerifiedAttributeExtensionUpdatedV2, @@ -223,8 +224,8 @@ describe("Integration tests", () => { version: "0", type: "TenantOnboarded", }); - const writtenPayload: TenantCreatedV1 | undefined = protobufDecoder( - TenantCreatedV1 + const writtenPayload: TenantOnboardedV2 | undefined = protobufDecoder( + TenantOnboardedV2 ).parse(writtenEvent.data); const expectedTenant: Tenant = { ...mockTenant, @@ -235,7 +236,7 @@ describe("Integration tests", () => { createdAt: new Date(Number(writtenPayload.tenant?.createdAt)), }; - expect(writtenPayload.tenant).toEqual(toTenantV1(expectedTenant)); + expect(writtenPayload.tenant).toEqual(toTenantV2(expectedTenant)); }); it("Should throw operation forbidden if role isn't internal", async () => { await addOneTenant(tenant, postgresDB, tenants); From e9a7b94f5ae704dd87d559bf61bdfb52ba5cf835 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Apr 2024 11:02:39 +0200 Subject: [PATCH 24/41] Minor fixes --- packages/models/src/tenant/protobufConverterFromV2.ts | 8 +++----- packages/models/src/tenant/protobufConverterToV2.ts | 8 ++++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/models/src/tenant/protobufConverterFromV2.ts b/packages/models/src/tenant/protobufConverterFromV2.ts index 3867112969..4d31f05621 100644 --- a/packages/models/src/tenant/protobufConverterFromV2.ts +++ b/packages/models/src/tenant/protobufConverterFromV2.ts @@ -58,9 +58,7 @@ export const fromTenantMailKindV2 = ( export const fromTenantMailV2 = (input: TenantMailV2): TenantMail => ({ ...input, - id: input.id - ? input.id - : createHash("sha256").update(input.address).digest("hex"), + id: input.id ?? createHash("sha256").update(input.address).digest("hex"), createdAt: new Date(Number(input.createdAt)), kind: fromTenantMailKindV2(input.kind), }); @@ -140,8 +138,8 @@ export const fromTenantAttributesV2 = ( ), type: tenantAttributeType.DECLARED, }; - case undefined: - throw genericError("Undefined attribute kind"); + default: + throw genericError(`Invalid attribute kind: ${sealedValue.oneofKind}`); } }; diff --git a/packages/models/src/tenant/protobufConverterToV2.ts b/packages/models/src/tenant/protobufConverterToV2.ts index 129dc096f7..694656ba51 100644 --- a/packages/models/src/tenant/protobufConverterToV2.ts +++ b/packages/models/src/tenant/protobufConverterToV2.ts @@ -44,10 +44,10 @@ export function toTenantVerifierV2(verifier: TenantVerifier): TenantVerifierV2 { id: verifier.id, verificationDate: BigInt(verifier.verificationDate.getTime()), expirationDate: verifier.expirationDate - ? BigInt(verifier.expirationDate?.getTime()) + ? BigInt(verifier.expirationDate.getTime()) : undefined, extensionDate: verifier.extensionDate - ? BigInt(verifier.extensionDate?.getTime()) + ? BigInt(verifier.extensionDate.getTime()) : undefined, }; } @@ -57,10 +57,10 @@ export function toTenantRevokerV2(revoker: TenantRevoker): TenantRevokerV2 { id: revoker.id, verificationDate: BigInt(revoker.verificationDate.getTime()), expirationDate: revoker.expirationDate - ? BigInt(revoker.expirationDate?.getTime()) + ? BigInt(revoker.expirationDate.getTime()) : undefined, extensionDate: revoker.extensionDate - ? BigInt(revoker.extensionDate?.getTime()) + ? BigInt(revoker.extensionDate.getTime()) : undefined, revocationDate: BigInt(revoker.revocationDate.getTime()), }; From 4ec3698bb456e68758bf292e0fb0dc5538c1456b Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Apr 2024 19:32:42 +0200 Subject: [PATCH 25/41] Upgrade proto version --- packages/models/proto/v2/tenant/events.proto | 42 ++++++++++---------- packages/models/proto/v2/tenant/tenant.proto | 42 ++++++++++---------- 2 files changed, 42 insertions(+), 42 deletions(-) diff --git a/packages/models/proto/v2/tenant/events.proto b/packages/models/proto/v2/tenant/events.proto index 152f55b210..3ad7c86768 100644 --- a/packages/models/proto/v2/tenant/events.proto +++ b/packages/models/proto/v2/tenant/events.proto @@ -1,25 +1,25 @@ -syntax = "proto2"; +syntax = "proto3"; package tenant.v2; import "v2/tenant/tenant.proto"; message TenantOnboardedV2 { - required TenantV2 tenant = 1; + TenantV2 tenant = 1; } message TenantOnboardDetailsUpdatedV2 { - required TenantV2 tenant = 1; + TenantV2 tenant = 1; } message TenantCertifiedAttributeAssignedV2 { - required string attributeId = 1; - required TenantV2 tenant = 2; + string attributeId = 1; + TenantV2 tenant = 2; } message TenantCertifiedAttributeRevokedV2 { - required string attributeId = 1; - required TenantV2 tenant = 2; + string attributeId = 1; + TenantV2 tenant = 2; } message TenantDeclaredAttributeAssignedV2 { @@ -28,36 +28,36 @@ message TenantDeclaredAttributeAssignedV2 { } message TenantDeclaredAttributeRevokedV2 { - required string attributeId = 1; - required TenantV2 tenant = 2; + string attributeId = 1; + TenantV2 tenant = 2; } message TenantVerifiedAttributeAssignedV2 { - required string attributeId = 1; - required TenantV2 tenant = 2; + string attributeId = 1; + TenantV2 tenant = 2; } message TenantVerifiedAttributeRevokedV2 { - required string attributeId = 1; - required TenantV2 tenant = 2; + string attributeId = 1; + TenantV2 tenant = 2; } message TenantVerifiedAttributeExpirationUpdatedV2 { - required string attributeId = 1; - required TenantV2 tenant = 2; + string attributeId = 1; + TenantV2 tenant = 2; } message TenantVerifiedAttributeExtensionUpdatedV2 { - required string attributeId = 1; - required TenantV2 tenant = 2; + string attributeId = 1; + TenantV2 tenant = 2; } message MaintenanceTenantDeletedV2 { - required string tenantId = 1; - required TenantV2 tenant = 2; + string tenantId = 1; + TenantV2 tenant = 2; } message TenantMailAddedV2 { - required string mailId = 1; - required TenantV2 tenant = 2; + string mailId = 1; + TenantV2 tenant = 2; } diff --git a/packages/models/proto/v2/tenant/tenant.proto b/packages/models/proto/v2/tenant/tenant.proto index d0cf80f712..2ee44be481 100644 --- a/packages/models/proto/v2/tenant/tenant.proto +++ b/packages/models/proto/v2/tenant/tenant.proto @@ -1,14 +1,14 @@ -syntax = "proto2"; +syntax = "proto3"; package tenant.v2; message TenantV2 { - required string id = 1; + string id = 1; optional string selfcareId = 2; - required ExternalIdV2 externalId = 3; + ExternalIdV2 externalId = 3; repeated TenantFeatureV2 features = 4; repeated TenantAttributeV2 attributes = 5; - required int64 createdAt = 6; + int64 createdAt = 6; optional int64 updatedAt = 7; repeated TenantMailV2 mails = 8; optional string name = 9; @@ -25,9 +25,9 @@ enum TenantKindV2 { } message TenantMailV2 { - required TenantMailKindV2 kind = 1; - required string address = 2; - required int64 createdAt = 3; + TenantMailKindV2 kind = 1; + string address = 2; + int64 createdAt = 3; optional string description = 4; optional string id = 5; } @@ -49,46 +49,46 @@ message TenantFeatureV2 { } message CertifierV2 { - required string certifierId = 1; + string certifierId = 1; } message TenantVerifierV2 { reserved 3; - required string id = 1; - required int64 verificationDate = 2; + string id = 1; + int64 verificationDate = 2; optional int64 expirationDate = 4; optional int64 extensionDate = 5; } message TenantRevokerV2 { reserved 3; - required string id = 1; - required int64 verificationDate = 2; + string id = 1; + int64 verificationDate = 2; optional int64 expirationDate = 4; optional int64 extensionDate = 5; - required int64 revocationDate = 6; + int64 revocationDate = 6; } message ExternalIdV2 { - required string origin = 1; - required string value = 2; + string origin = 1; + string value = 2; } message TenantCertifiedAttributeV2 { - required string id = 1; - required int64 assignmentTimestamp = 2; + string id = 1; + int64 assignmentTimestamp = 2; optional int64 revocationTimestamp = 3; } message TenantDeclaredAttributeV2 { - required string id = 1; - required int64 assignmentTimestamp = 2; + string id = 1; + int64 assignmentTimestamp = 2; optional int64 revocationTimestamp = 3; } message TenantVerifiedAttributeV2 { - required string id = 1; - required int64 assignmentTimestamp = 2; + string id = 1; + int64 assignmentTimestamp = 2; repeated TenantVerifierV2 verifiedBy = 3; repeated TenantRevokerV2 revokedBy = 4; } From 1bf8c2078da297859d20db31d98cca45f2562584 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Apr 2024 19:34:04 +0200 Subject: [PATCH 26/41] Fix numbers in proto enums --- packages/models/proto/v2/tenant/tenant.proto | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/models/proto/v2/tenant/tenant.proto b/packages/models/proto/v2/tenant/tenant.proto index 2ee44be481..a80971b0ef 100644 --- a/packages/models/proto/v2/tenant/tenant.proto +++ b/packages/models/proto/v2/tenant/tenant.proto @@ -19,9 +19,9 @@ message TenantV2 { } enum TenantKindV2 { - PA = 1; - GSP = 2; - PRIVATE = 3; + PA = 0; + GSP = 1; + PRIVATE = 2; } message TenantMailV2 { @@ -33,13 +33,13 @@ message TenantMailV2 { } enum TenantMailKindV2 { - CONTACT_EMAIL = 1; - DIGITAL_ADDRESS = 2; + CONTACT_EMAIL = 0; + DIGITAL_ADDRESS = 1; } enum TenantUnitTypeV2 { - AOO = 1; - UO = 2; + AOO = 0; + UO = 1; } message TenantFeatureV2 { From 7ea6695283bedb20535e66d11907ca122c561e58 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Apr 2024 19:36:30 +0200 Subject: [PATCH 27/41] Remove required --- packages/models/proto/v2/tenant/events.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/models/proto/v2/tenant/events.proto b/packages/models/proto/v2/tenant/events.proto index 3ad7c86768..596ca894a1 100644 --- a/packages/models/proto/v2/tenant/events.proto +++ b/packages/models/proto/v2/tenant/events.proto @@ -23,8 +23,8 @@ message TenantCertifiedAttributeRevokedV2 { } message TenantDeclaredAttributeAssignedV2 { - required string attributeId = 1; - required TenantV2 tenant = 2; + string attributeId = 1; + TenantV2 tenant = 2; } message TenantDeclaredAttributeRevokedV2 { From 892ed53eba771c644804ac02bf592338cd4ffb04 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Mon, 8 Apr 2024 19:42:10 +0200 Subject: [PATCH 28/41] Fix after upgrade to proto3 --- packages/models/src/tenant/protobufConverterFromV2.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/models/src/tenant/protobufConverterFromV2.ts b/packages/models/src/tenant/protobufConverterFromV2.ts index 4d31f05621..98fbb7b657 100644 --- a/packages/models/src/tenant/protobufConverterFromV2.ts +++ b/packages/models/src/tenant/protobufConverterFromV2.ts @@ -38,8 +38,6 @@ export const fromTenantKindV2 = (input: TenantKindV2): TenantKind => { return tenantKind.PA; case TenantKindV2.PRIVATE: return tenantKind.PRIVATE; - case TenantKindV2.UNSPECIFIED$: - throw new Error("Unspecified tenant kind"); } }; @@ -51,8 +49,6 @@ export const fromTenantMailKindV2 = ( return tenantMailKind.ContactEmail; case TenantMailKindV2.DIGITAL_ADDRESS: return tenantMailKind.DigitalAddress; - case TenantMailKindV2.UNSPECIFIED$: - throw new Error("Unspecified tenant mail kind"); } }; @@ -151,8 +147,6 @@ export const fromTenantUnitTypeV2 = ( return tenantUnitType.AOO; case TenantUnitTypeV2.UO: return tenantUnitType.UO; - case TenantUnitTypeV2.UNSPECIFIED$: - throw new Error("Unspecified tenant unit type"); } }; From 57b0f627fd5fe2347f4297baf811bb59ff6c1b0d Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Tue, 9 Apr 2024 12:07:25 +0200 Subject: [PATCH 29/41] removed try catch in index.ts --- packages/tenant-readmodel-writer/src/index.ts | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/packages/tenant-readmodel-writer/src/index.ts b/packages/tenant-readmodel-writer/src/index.ts index 30c579e916..d7691850e2 100644 --- a/packages/tenant-readmodel-writer/src/index.ts +++ b/packages/tenant-readmodel-writer/src/index.ts @@ -31,19 +31,13 @@ async function processMessage({ }; ctx.correlationId = decodedMessage.correlation_id; - try { - await match(decodedMessage) - .with({ event_version: 1 }, (msg) => handleMessageV1(msg)) - .with({ event_version: 2 }, (msg) => handleMessageV2(msg, tenants)) - .exhaustive(); - logger.info( - `Read model was updated. Partition number: ${partition}. Offset: ${message.offset}` - ); - } catch (e) { - logger.error( - `Error during message handling. Partition number: ${partition}. Offset: ${message.offset}, ${e}` - ); - } + await match(decodedMessage) + .with({ event_version: 1 }, (msg) => handleMessageV1(msg)) + .with({ event_version: 2 }, (msg) => handleMessageV2(msg, tenants)) + .exhaustive(); + logger.info( + `Read model was updated. Partition number: ${partition}. Offset: ${message.offset}` + ); } await runConsumer(config, [tenantTopic], processMessage); From 50c0a1e99c3050da289399cd17574f97bc14c61b Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 9 Apr 2024 16:29:40 +0200 Subject: [PATCH 30/41] Remove reserved --- packages/models/proto/v2/tenant/tenant.proto | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/models/proto/v2/tenant/tenant.proto b/packages/models/proto/v2/tenant/tenant.proto index a80971b0ef..270f686249 100644 --- a/packages/models/proto/v2/tenant/tenant.proto +++ b/packages/models/proto/v2/tenant/tenant.proto @@ -53,20 +53,18 @@ message CertifierV2 { } message TenantVerifierV2 { - reserved 3; string id = 1; int64 verificationDate = 2; - optional int64 expirationDate = 4; - optional int64 extensionDate = 5; + optional int64 expirationDate = 3; + optional int64 extensionDate = 4; } message TenantRevokerV2 { - reserved 3; string id = 1; int64 verificationDate = 2; - optional int64 expirationDate = 4; - optional int64 extensionDate = 5; - int64 revocationDate = 6; + optional int64 expirationDate = 3; + optional int64 extensionDate = 4; + int64 revocationDate = 5; } message ExternalIdV2 { From 03f73a9777c39db63777af1bb600ca481ca4bfde Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 9 Apr 2024 16:35:51 +0200 Subject: [PATCH 31/41] Fix definition --- packages/models/proto/v2/tenant/tenant.proto | 8 ++++---- packages/models/src/tenant/protobufConverterToV2.ts | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/models/proto/v2/tenant/tenant.proto b/packages/models/proto/v2/tenant/tenant.proto index 270f686249..8edafa1011 100644 --- a/packages/models/proto/v2/tenant/tenant.proto +++ b/packages/models/proto/v2/tenant/tenant.proto @@ -4,16 +4,16 @@ package tenant.v2; message TenantV2 { string id = 1; - optional string selfcareId = 2; + string selfcareId = 2; ExternalIdV2 externalId = 3; repeated TenantFeatureV2 features = 4; repeated TenantAttributeV2 attributes = 5; int64 createdAt = 6; optional int64 updatedAt = 7; repeated TenantMailV2 mails = 8; - optional string name = 9; + string name = 9; optional TenantKindV2 kind = 10; - optional int64 onboardedAt = 11; + int64 onboardedAt = 11; optional TenantUnitTypeV2 subUnitType = 12; } @@ -29,7 +29,7 @@ message TenantMailV2 { string address = 2; int64 createdAt = 3; optional string description = 4; - optional string id = 5; + string id = 5; } enum TenantMailKindV2 { diff --git a/packages/models/src/tenant/protobufConverterToV2.ts b/packages/models/src/tenant/protobufConverterToV2.ts index 694656ba51..91724260a3 100644 --- a/packages/models/src/tenant/protobufConverterToV2.ts +++ b/packages/models/src/tenant/protobufConverterToV2.ts @@ -105,8 +105,8 @@ export function toAttributeV2(input: TenantAttribute): TenantAttributeV2 { export function toTenantMailV2(mail: TenantMail): TenantMailV2 { return { + ...mail, kind: toTenantMailKindV2(mail.kind), - address: mail.address, createdAt: BigInt(mail.createdAt.getTime()), description: mail.description ?? undefined, }; @@ -136,15 +136,14 @@ export function toTenantUnitTypeV2(input: TenantUnitType): TenantUnitTypeV2 { export const toTenantV2 = (tenant: Tenant): TenantV2 => ({ ...tenant, + selfcareId: tenant.selfcareId || "default", features: tenant.features.map(toFeatureV2), attributes: tenant.attributes.map(toAttributeV2), createdAt: BigInt(tenant.createdAt.getTime()), updatedAt: tenant.updatedAt ? BigInt(tenant.updatedAt.getTime()) : undefined, mails: tenant.mails.map(toTenantMailV2), kind: tenant.kind ? toTenantKindV2(tenant.kind) : undefined, - onboardedAt: tenant.createdAt - ? BigInt(tenant.createdAt.getTime()) - : undefined, + onboardedAt: BigInt(tenant.createdAt.getTime()), subUnitType: tenant.subUnitType ? toTenantUnitTypeV2(tenant.subUnitType) : undefined, From 10de6ab3245aa00916737be31267389cf8ea88ab Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 9 Apr 2024 16:46:37 +0200 Subject: [PATCH 32/41] Remove default --- packages/models/src/tenant/protobufConverterToV2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/models/src/tenant/protobufConverterToV2.ts b/packages/models/src/tenant/protobufConverterToV2.ts index 91724260a3..4d68e8cdee 100644 --- a/packages/models/src/tenant/protobufConverterToV2.ts +++ b/packages/models/src/tenant/protobufConverterToV2.ts @@ -136,7 +136,7 @@ export function toTenantUnitTypeV2(input: TenantUnitType): TenantUnitTypeV2 { export const toTenantV2 = (tenant: Tenant): TenantV2 => ({ ...tenant, - selfcareId: tenant.selfcareId || "default", + selfcareId: tenant.selfcareId, features: tenant.features.map(toFeatureV2), attributes: tenant.attributes.map(toAttributeV2), createdAt: BigInt(tenant.createdAt.getTime()), From 3c58b075e2458eb9c9d1970d19e9632b28033ab7 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 9 Apr 2024 17:47:36 +0200 Subject: [PATCH 33/41] Fix missing selfcareId --- packages/models/src/tenant/protobufConverterToV2.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/models/src/tenant/protobufConverterToV2.ts b/packages/models/src/tenant/protobufConverterToV2.ts index 4d68e8cdee..3e369404f4 100644 --- a/packages/models/src/tenant/protobufConverterToV2.ts +++ b/packages/models/src/tenant/protobufConverterToV2.ts @@ -134,9 +134,16 @@ export function toTenantUnitTypeV2(input: TenantUnitType): TenantUnitTypeV2 { .exhaustive(); } +function checkSelfcareId(selfcareId: string | undefined): string { + if (selfcareId === undefined) { + throw new Error("SelfcareId can't be undefined"); + } + return selfcareId; +} + export const toTenantV2 = (tenant: Tenant): TenantV2 => ({ ...tenant, - selfcareId: tenant.selfcareId, + selfcareId: checkSelfcareId(tenant.selfcareId), features: tenant.features.map(toFeatureV2), attributes: tenant.attributes.map(toAttributeV2), createdAt: BigInt(tenant.createdAt.getTime()), From 4f960360365d20a2a8bf53dae5d3971157874674 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Wed, 10 Apr 2024 15:07:51 +0200 Subject: [PATCH 34/41] Fix tests --- .../test/tenant.integration.test.ts | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/tenant-process/test/tenant.integration.test.ts b/packages/tenant-process/test/tenant.integration.test.ts index 573347db4e..ba184b47d7 100644 --- a/packages/tenant-process/test/tenant.integration.test.ts +++ b/packages/tenant-process/test/tenant.integration.test.ts @@ -27,11 +27,9 @@ import { Descriptor, EService, Tenant, - TenantCreatedV1, TenantId, TenantOnboardDetailsUpdatedV2, TenantOnboardedV2, - TenantUpdatedV1, TenantVerifiedAttributeExpirationUpdatedV2, TenantVerifiedAttributeExtensionUpdatedV2, descriptorState, @@ -52,7 +50,6 @@ import { TenantService, tenantServiceBuilder, } from "../src/services/tenantService.js"; -import { toTenantV1 } from "../src/model/domain/toEvent.js"; import { UpdateVerifiedTenantAttributeSeed } from "../src/model/domain/models.js"; import { expirationDateCannotBeInThePast, @@ -143,23 +140,20 @@ describe("Integration tests", () => { name: "A tenant", selfcareId: generateId(), }; - const tenant: Tenant = { - ...mockTenant, - selfcareId: undefined, - }; + it("Should update the tenant if it exists", async () => { - await addOneTenant(tenant, postgresDB, tenants); + await addOneTenant(mockTenant, postgresDB, tenants); const kind = tenantKind.PA; - const selfcareId = generateId(); + const selfcareId = mockTenant.selfcareId!; const tenantSeed: ApiSelfcareTenantSeed = { externalId: { - origin: tenant.externalId.origin, - value: tenant.externalId.value, + origin: mockTenant.externalId.origin, + value: mockTenant.externalId.value, }, name: "A tenant", selfcareId, }; - const mockAuthData = getMockAuthData(tenant.id); + const mockAuthData = getMockAuthData(mockTenant.id); await tenantService.selfcareUpsertTenant({ tenantSeed, authData: mockAuthData, @@ -168,7 +162,7 @@ describe("Integration tests", () => { const writtenEvent: StoredEvent | undefined = await readLastEventByStreamId( - tenant.id, + mockTenant.id, eventStoreSchema.tenant, postgresDB ); @@ -176,7 +170,7 @@ describe("Integration tests", () => { fail("Update failed: tenant not found in event-store"); } expect(writtenEvent).toMatchObject({ - stream_id: tenant.id, + stream_id: mockTenant.id, version: "1", type: "TenantOnboardDetailsUpdated", }); @@ -186,7 +180,7 @@ describe("Integration tests", () => { ); const updatedTenant: Tenant = { - ...tenant, + ...mockTenant, selfcareId, kind, updatedAt: new Date(Number(writtenPayload.tenant?.updatedAt)), @@ -239,7 +233,7 @@ describe("Integration tests", () => { expect(writtenPayload.tenant).toEqual(toTenantV2(expectedTenant)); }); it("Should throw operation forbidden if role isn't internal", async () => { - await addOneTenant(tenant, postgresDB, tenants); + await addOneTenant(mockTenant, postgresDB, tenants); const mockAuthData = getMockAuthData(generateId()); expect( From b0946de1830f4adfa83ce314a1bd7e71f62d57e9 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 9 May 2024 16:46:01 +0200 Subject: [PATCH 35/41] Fix --- packages/tenant-readmodel-writer/src/tenantConsumerService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tenant-readmodel-writer/src/tenantConsumerService.ts b/packages/tenant-readmodel-writer/src/tenantConsumerService.ts index d665d791ea..7501595299 100644 --- a/packages/tenant-readmodel-writer/src/tenantConsumerService.ts +++ b/packages/tenant-readmodel-writer/src/tenantConsumerService.ts @@ -9,7 +9,7 @@ import { TenantEventEnvelopeV1, fromTenantV1 } from "pagopa-interop-models"; const { tenants } = ReadModelRepository.init(readModelWriterConfig()); export async function handleMessage( - message: TenantEventEnvelopeV1 + message: TenantEventEnvelopeV1, logger: Logger ): Promise { await match(message) From df29f5583a4cb2c03ec030eca71a9de07e6dddae Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Thu, 9 May 2024 17:38:30 +0200 Subject: [PATCH 36/41] refactor --- .../tenant-readmodel-writer/src/tenantConsumerServiceV2.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts b/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts index 2a553623b6..c780d02bbf 100644 --- a/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts +++ b/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts @@ -1,4 +1,4 @@ -import { TenantCollection, logger } from "pagopa-interop-commons"; +import { TenantCollection } from "pagopa-interop-commons"; import { TenantEventEnvelopeV2, fromTenantV2 } from "pagopa-interop-models"; import { match } from "ts-pattern"; @@ -6,8 +6,6 @@ export async function handleMessageV2( message: TenantEventEnvelopeV2, tenants: TenantCollection ): Promise { - logger.info(message); - const tenant = message.data.tenant; await match(message) From 316f8e659eff8ec2eb64221f771a542109780411 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Tue, 14 May 2024 17:35:14 +0200 Subject: [PATCH 37/41] Refactor --- .../src/tenant/protobufConverterFromV2.ts | 45 ++++++++----------- .../src/tenant/protobufConverterToV2.ts | 42 +++++++---------- 2 files changed, 35 insertions(+), 52 deletions(-) diff --git a/packages/models/src/tenant/protobufConverterFromV2.ts b/packages/models/src/tenant/protobufConverterFromV2.ts index 98fbb7b657..2f35f32eca 100644 --- a/packages/models/src/tenant/protobufConverterFromV2.ts +++ b/packages/models/src/tenant/protobufConverterFromV2.ts @@ -13,6 +13,7 @@ import { TenantV2, TenantUnitTypeV2, } from "../gen/v2/tenant/tenant.js"; +import { bigIntToDate } from "../utils.js"; import { TenantKind, tenantKind, @@ -55,7 +56,7 @@ export const fromTenantMailKindV2 = ( export const fromTenantMailV2 = (input: TenantMailV2): TenantMail => ({ ...input, id: input.id ?? createHash("sha256").update(input.address).digest("hex"), - createdAt: new Date(Number(input.createdAt)), + createdAt: bigIntToDate(input.createdAt), kind: fromTenantMailKindV2(input.kind), }); @@ -78,25 +79,17 @@ export const fromTenantVerifierV2 = ( input: TenantVerifierV2 ): TenantVerifier => ({ ...input, - verificationDate: new Date(Number(input.verificationDate)), - expirationDate: input.expirationDate - ? new Date(Number(input.expirationDate)) - : undefined, - extensionDate: input.extensionDate - ? new Date(Number(input.extensionDate)) - : undefined, + verificationDate: bigIntToDate(input.verificationDate), + expirationDate: bigIntToDate(input.expirationDate), + extensionDate: bigIntToDate(input.extensionDate), }); export const fromTenantRevokerV2 = (input: TenantRevokerV2): TenantRevoker => ({ ...input, - expirationDate: input.expirationDate - ? new Date(Number(input.expirationDate)) - : undefined, - extensionDate: input.extensionDate - ? new Date(Number(input.extensionDate)) - : undefined, - revocationDate: new Date(Number(input.revocationDate)), - verificationDate: new Date(Number(input.verificationDate)), + expirationDate: bigIntToDate(input.expirationDate), + extensionDate: bigIntToDate(input.extensionDate), + revocationDate: bigIntToDate(input.revocationDate), + verificationDate: bigIntToDate(input.verificationDate), }); export const fromTenantAttributesV2 = ( @@ -109,8 +102,8 @@ export const fromTenantAttributesV2 = ( const { certifiedAttribute } = sealedValue; return { id: unsafeBrandId(certifiedAttribute.id), - assignmentTimestamp: new Date( - Number(certifiedAttribute.assignmentTimestamp) + assignmentTimestamp: bigIntToDate( + certifiedAttribute.assignmentTimestamp ), type: tenantAttributeType.CERTIFIED, }; @@ -118,8 +111,8 @@ export const fromTenantAttributesV2 = ( const { verifiedAttribute } = sealedValue; return { id: unsafeBrandId(verifiedAttribute.id), - assignmentTimestamp: new Date( - Number(verifiedAttribute.assignmentTimestamp) + assignmentTimestamp: bigIntToDate( + verifiedAttribute.assignmentTimestamp ), verifiedBy: verifiedAttribute.verifiedBy.map(fromTenantVerifierV2), revokedBy: verifiedAttribute.revokedBy.map(fromTenantRevokerV2), @@ -129,8 +122,8 @@ export const fromTenantAttributesV2 = ( const { declaredAttribute } = sealedValue; return { id: unsafeBrandId(declaredAttribute.id), - assignmentTimestamp: new Date( - Number(declaredAttribute.assignmentTimestamp) + assignmentTimestamp: bigIntToDate( + declaredAttribute.assignmentTimestamp ), type: tenantAttributeType.DECLARED, }; @@ -167,16 +160,14 @@ export const fromTenantV2 = (input: TenantV2): Tenant => { ...input, id: unsafeBrandId(input.id), name: input.name ?? "", - createdAt: new Date(Number(input.createdAt)), + createdAt: bigIntToDate(input.createdAt), attributes: input.attributes.map(fromTenantAttributesV2), externalId: externalId.data, features: input.features.map(fromTenantFeatureV2), mails: input.mails.map(fromTenantMailV2), kind: input.kind ? fromTenantKindV2(input.kind) : undefined, - updatedAt: input.updatedAt ? new Date(Number(input.updatedAt)) : undefined, - onboardedAt: input.onboardedAt - ? new Date(Number(input.onboardedAt)) - : undefined, + updatedAt: bigIntToDate(input.updatedAt), + onboardedAt: bigIntToDate(input.onboardedAt), subUnitType: input.subUnitType ? fromTenantUnitTypeV2(input.subUnitType) : undefined, diff --git a/packages/models/src/tenant/protobufConverterToV2.ts b/packages/models/src/tenant/protobufConverterToV2.ts index 3e369404f4..63bde4cf39 100644 --- a/packages/models/src/tenant/protobufConverterToV2.ts +++ b/packages/models/src/tenant/protobufConverterToV2.ts @@ -9,6 +9,7 @@ import { TenantUnitTypeV2, TenantV2, TenantVerifierV2, + dateToBigInt, } from "../index.js"; import { Tenant, @@ -42,27 +43,19 @@ export function toFeatureV2(feature: TenantFeature): TenantFeatureV2 { export function toTenantVerifierV2(verifier: TenantVerifier): TenantVerifierV2 { return { id: verifier.id, - verificationDate: BigInt(verifier.verificationDate.getTime()), - expirationDate: verifier.expirationDate - ? BigInt(verifier.expirationDate.getTime()) - : undefined, - extensionDate: verifier.extensionDate - ? BigInt(verifier.extensionDate.getTime()) - : undefined, + verificationDate: dateToBigInt(verifier.verificationDate), + expirationDate: dateToBigInt(verifier.expirationDate), + extensionDate: dateToBigInt(verifier.extensionDate), }; } export function toTenantRevokerV2(revoker: TenantRevoker): TenantRevokerV2 { return { id: revoker.id, - verificationDate: BigInt(revoker.verificationDate.getTime()), - expirationDate: revoker.expirationDate - ? BigInt(revoker.expirationDate.getTime()) - : undefined, - extensionDate: revoker.extensionDate - ? BigInt(revoker.extensionDate.getTime()) - : undefined, - revocationDate: BigInt(revoker.revocationDate.getTime()), + verificationDate: dateToBigInt(revoker.verificationDate), + expirationDate: dateToBigInt(revoker.expirationDate), + extensionDate: dateToBigInt(revoker.extensionDate), + revocationDate: dateToBigInt(revoker.revocationDate), }; } @@ -73,10 +66,8 @@ export function toAttributeV2(input: TenantAttribute): TenantAttributeV2 { oneofKind: "certifiedAttribute", certifiedAttribute: { id: attribute.id, - assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), - revocationTimestamp: attribute.revocationTimestamp - ? BigInt(attribute.revocationTimestamp?.getTime()) - : undefined, + assignmentTimestamp: dateToBigInt(attribute.assignmentTimestamp), + revocationTimestamp: dateToBigInt(attribute.revocationTimestamp), }, }, })) @@ -85,7 +76,7 @@ export function toAttributeV2(input: TenantAttribute): TenantAttributeV2 { oneofKind: "verifiedAttribute", verifiedAttribute: { id: attribute.id, - assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), + assignmentTimestamp: dateToBigInt(attribute.assignmentTimestamp), verifiedBy: attribute.verifiedBy.map(toTenantVerifierV2), revokedBy: attribute.revokedBy.map(toTenantRevokerV2), }, @@ -96,7 +87,7 @@ export function toAttributeV2(input: TenantAttribute): TenantAttributeV2 { oneofKind: "declaredAttribute", declaredAttribute: { id: attribute.id, - assignmentTimestamp: BigInt(attribute.assignmentTimestamp.getTime()), + assignmentTimestamp: dateToBigInt(attribute.assignmentTimestamp), }, }, })) @@ -107,7 +98,7 @@ export function toTenantMailV2(mail: TenantMail): TenantMailV2 { return { ...mail, kind: toTenantMailKindV2(mail.kind), - createdAt: BigInt(mail.createdAt.getTime()), + createdAt: dateToBigInt(mail.createdAt), description: mail.description ?? undefined, }; } @@ -146,11 +137,12 @@ export const toTenantV2 = (tenant: Tenant): TenantV2 => ({ selfcareId: checkSelfcareId(tenant.selfcareId), features: tenant.features.map(toFeatureV2), attributes: tenant.attributes.map(toAttributeV2), - createdAt: BigInt(tenant.createdAt.getTime()), - updatedAt: tenant.updatedAt ? BigInt(tenant.updatedAt.getTime()) : undefined, + createdAt: dateToBigInt(tenant.createdAt), + updatedAt: dateToBigInt(tenant.updatedAt), mails: tenant.mails.map(toTenantMailV2), kind: tenant.kind ? toTenantKindV2(tenant.kind) : undefined, - onboardedAt: BigInt(tenant.createdAt.getTime()), + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + onboardedAt: dateToBigInt(tenant.onboardedAt!), subUnitType: tenant.subUnitType ? toTenantUnitTypeV2(tenant.subUnitType) : undefined, From 6c04ecab122629008a0e7fd4ecbed6352be33257 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Fri, 14 Jun 2024 16:27:51 +0200 Subject: [PATCH 38/41] fix test --- packages/tenant-process/src/services/tenantService.ts | 1 + packages/tenant-process/test/tenant.integration.test.ts | 9 +++++++-- packages/tenant-process/test/utils.ts | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/tenant-process/src/services/tenantService.ts b/packages/tenant-process/src/services/tenantService.ts index 2a4c94da7b..c585658bc8 100644 --- a/packages/tenant-process/src/services/tenantService.ts +++ b/packages/tenant-process/src/services/tenantService.ts @@ -256,6 +256,7 @@ export function tenantServiceBuilder( mails: [], selfcareId: tenantSeed.selfcareId, kind: getTenantKind([], tenantSeed.externalId), + onboardedAt: new Date(), createdAt: new Date(), }; return await repository.createEvent( diff --git a/packages/tenant-process/test/tenant.integration.test.ts b/packages/tenant-process/test/tenant.integration.test.ts index 773057cd22..9e741a8b7c 100644 --- a/packages/tenant-process/test/tenant.integration.test.ts +++ b/packages/tenant-process/test/tenant.integration.test.ts @@ -2,7 +2,7 @@ /* eslint-disable @typescript-eslint/no-floating-promises */ import { fail } from "assert"; -import { describe, expect, it } from "vitest"; +import { describe, expect, it, vi } from "vitest"; import { genericLogger } from "pagopa-interop-commons"; import { Descriptor, @@ -114,6 +114,8 @@ describe("Integration tests", () => { expect(writtenPayload.tenant).toEqual(toTenantV2(updatedTenant)); }); it("Should create a tenant by the upsert if it does not exist", async () => { + vi.useFakeTimers(); + vi.setSystemTime(new Date()); const mockAuthData = getMockAuthData(); const tenantSeed = { externalId: { @@ -142,16 +144,19 @@ describe("Integration tests", () => { const writtenPayload: TenantOnboardedV2 | undefined = protobufDecoder( TenantOnboardedV2 ).parse(writtenEvent.data); + const expectedTenant: Tenant = { ...mockTenant, externalId: tenantSeed.externalId, id: unsafeBrandId(id), kind: getTenantKind([], tenantSeed.externalId), selfcareId: tenantSeed.selfcareId, - createdAt: new Date(Number(writtenPayload.tenant?.createdAt)), + onboardedAt: new Date(), + createdAt: new Date(), }; expect(writtenPayload.tenant).toEqual(toTenantV2(expectedTenant)); + vi.useRealTimers(); }); it("Should throw operation forbidden if role isn't internal", async () => { await addOneTenant(mockTenant); diff --git a/packages/tenant-process/test/utils.ts b/packages/tenant-process/test/utils.ts index d081a74257..ed073b3ae9 100644 --- a/packages/tenant-process/test/utils.ts +++ b/packages/tenant-process/test/utils.ts @@ -76,6 +76,7 @@ export const getMockTenant = (): Tenant => ({ createdAt: new Date(), attributes: [], selfcareId: generateId(), + onboardedAt: new Date(), externalId: { value: "123456", origin: "IPA", From 0d92c4f5e84959643b0ce5be54950a20af6ef766 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 4 Jul 2024 12:35:14 +0200 Subject: [PATCH 39/41] Fix workflow --- .github/workflows/pr.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 233735393d..e44e51c375 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -26,20 +26,20 @@ jobs: - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version-file: ./package.json - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: run_install: true - run: pnpm lint check: - name: Check + name: Check runs-on: ubuntu-latest steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version-file: ./package.json - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: run_install: true - run: pnpm check @@ -51,8 +51,8 @@ jobs: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4 - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: - node-version-file: ./package.json - - uses: pnpm/action-setup@v2 + node-version-file: ./package.json + - uses: pnpm/action-setup@v4 with: run_install: true - run: pnpm test @@ -65,7 +65,7 @@ jobs: - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version-file: ./package.json - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: run_install: true - run: pnpm build From d687f2bb3e8a8d5651e1c00daad2c81464da96b6 Mon Sep 17 00:00:00 2001 From: Roberto Taglioni Date: Thu, 4 Jul 2024 12:40:27 +0200 Subject: [PATCH 40/41] Fix workflow --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e44e51c375..3f5c026f7c 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4 with: node-version-file: ./package.json - - uses: pnpm/action-setup@v2 + - uses: pnpm/action-setup@v4 with: run_install: true - run: pnpm format:check From b08e8bd8e7088b428cf43981d2846c98bbd38ab6 Mon Sep 17 00:00:00 2001 From: Roberto Gregnanin Date: Mon, 15 Jul 2024 18:24:15 +0200 Subject: [PATCH 41/41] Added "e" to "$lt" --- .../src/tenantConsumerServiceV1.ts | 10 +++++----- .../src/tenantConsumerServiceV2.ts | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/tenant-readmodel-writer/src/tenantConsumerServiceV1.ts b/packages/tenant-readmodel-writer/src/tenantConsumerServiceV1.ts index 57372d7480..559bbcbe2f 100644 --- a/packages/tenant-readmodel-writer/src/tenantConsumerServiceV1.ts +++ b/packages/tenant-readmodel-writer/src/tenantConsumerServiceV1.ts @@ -26,7 +26,7 @@ export async function handleMessageV1( .with({ type: "TenantDeleted" }, async (msg) => { await tenants.deleteOne({ "data.id": msg.stream_id, - "metadata.version": { $lt: msg.version }, + "metadata.version": { $lte: msg.version }, }); }) .with( @@ -51,7 +51,7 @@ export async function handleMessageV1( await tenants.updateOne( { "data.id": msg.stream_id, - "metadata.version": { $lt: msg.version }, + "metadata.version": { $lte: msg.version }, }, { $set: { @@ -65,7 +65,7 @@ export async function handleMessageV1( await tenants.updateOne( { "data.id": msg.stream_id, - "metadata.version": { $lt: msg.version }, + "metadata.version": { $lte: msg.version }, }, { $set: { @@ -79,7 +79,7 @@ export async function handleMessageV1( await tenants.updateOne( { "data.id": msg.stream_id, - "metadata.version": { $lt: msg.version }, + "metadata.version": { $lte: msg.version }, }, { $set: { @@ -95,7 +95,7 @@ export async function handleMessageV1( await tenants.updateOne( { "data.id": msg.stream_id, - "metadata.version": { $lt: msg.version }, + "metadata.version": { $lte: msg.version }, }, { $pull: { diff --git a/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts b/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts index c780d02bbf..77598616d8 100644 --- a/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts +++ b/packages/tenant-readmodel-writer/src/tenantConsumerServiceV2.ts @@ -12,7 +12,7 @@ export async function handleMessageV2( .with({ type: "MaintenanceTenantDeleted" }, async (message) => { await tenants.deleteOne({ "data.id": message.stream_id, - "metadata.version": { $lt: message.version }, + "metadata.version": { $lte: message.version }, }); }) .with( @@ -31,7 +31,7 @@ export async function handleMessageV2( await tenants.updateOne( { "data.id": message.stream_id, - "metadata.version": { $lt: message.version }, + "metadata.version": { $lte: message.version }, }, { $set: {