diff --git a/packages/catalog-process/src/services/catalogService.ts b/packages/catalog-process/src/services/catalogService.ts index ae70fd9e38..2727904d5b 100644 --- a/packages/catalog-process/src/services/catalogService.ts +++ b/packages/catalog-process/src/services/catalogService.ts @@ -2208,8 +2208,9 @@ export function catalogServiceBuilder( const validatedRiskAnalysisForm = validateRiskAnalysisSchemaOrThrow( eserviceRiskAnalysisSeed.riskAnalysisForm, tenant.kind, - new Date() // [todo remove comment] risk analysis creation + new Date(), // [todo remove comment] risk analysis creation // drawback: the date of the risk analysis is set below in the function riskAnalysisValidatedFormToNewRiskAnalysis + eservice.data.personalData ); const newRiskAnalysis: RiskAnalysis = @@ -2294,8 +2295,9 @@ export function catalogServiceBuilder( const validatedRiskAnalysisForm = validateRiskAnalysisSchemaOrThrow( eserviceRiskAnalysisSeed.riskAnalysisForm, tenant.kind, - new Date() // [todo remove comment] risk analysis update + new Date(), // [todo remove comment] risk analysis update // drawback: the date of the risk analysis is replaced below in the function riskAnalysisValidatedFormToNewRiskAnalysis + eservice.data.personalData ); const updatedRiskAnalysis: RiskAnalysis = { diff --git a/packages/catalog-process/src/services/validators.ts b/packages/catalog-process/src/services/validators.ts index 00bbc30c9b..7ce7ccbb35 100644 --- a/packages/catalog-process/src/services/validators.ts +++ b/packages/catalog-process/src/services/validators.ts @@ -203,13 +203,15 @@ export function assertHasNoDraftOrWaitingForApprovalDescriptor( export function validateRiskAnalysisSchemaOrThrow( riskAnalysisForm: catalogApi.EServiceRiskAnalysisSeed["riskAnalysisForm"], tenantKind: TenantKind, - dateForExpirationValidation: Date + dateForExpirationValidation: Date, + personalDataInEService: boolean | undefined ): RiskAnalysisValidatedForm { const result = validateRiskAnalysis( riskAnalysisForm, true, tenantKind, - dateForExpirationValidation + dateForExpirationValidation, + personalDataInEService ); if (result.type === "invalid") { throw riskAnalysisValidationFailed(result.issues); @@ -233,7 +235,8 @@ export function assertRiskAnalysisIsValidForPublication( ), false, tenantKind, - new Date() + new Date(), + eservice.personalData ); if (result.type === "invalid") { diff --git a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts index ff2ae7a893..88bc5bc6ff 100644 --- a/packages/commons-test/test/riskAnalysisValidation.integration.test.ts +++ b/packages/commons-test/test/riskAnalysisValidation.integration.test.ts @@ -1,5 +1,4 @@ import { describe, expect, it, vi } from "vitest"; - import { RiskAnalysisFormToValidate, RiskAnalysisValidatedForm, @@ -11,6 +10,7 @@ import { validateRiskAnalysis, rulesVersionNotFoundError, expiredRulesVersionError, + incompatiblePersonalDataError, } from "pagopa-interop-commons"; import { tenantKind } from "pagopa-interop-models"; import { @@ -31,13 +31,15 @@ describe("Risk Analysis Validation", () => { validRiskAnalysis3_0_Pa, false, "PA", - new Date() + new Date(), + undefined ); const resultSchemaOnly = validateRiskAnalysis( validRiskAnalysis3_0_Pa, true, "PA", - new Date() + new Date(), + undefined ); expect(result).toEqual({ type: "valid", @@ -55,13 +57,15 @@ describe("Risk Analysis Validation", () => { expiredRiskAnalysis2_0_Pa, false, "PA", - new Date() + new Date(), + undefined ); const resultSchemaOnly = validateRiskAnalysis( expiredRiskAnalysis2_0_Pa, true, "PA", - new Date() + new Date(), + undefined ); expect(result).toEqual({ type: "valid", @@ -82,7 +86,8 @@ describe("Risk Analysis Validation", () => { validSchemaOnlyRiskAnalysis3_0_Pa, true, "PA", - new Date() + new Date(), + undefined ); expect(result).toEqual({ @@ -96,13 +101,15 @@ describe("Risk Analysis Validation", () => { validRiskAnalysis2_0_Private, false, "PRIVATE", - new Date() + new Date(), + undefined ); const resultSchemaOnly = validateRiskAnalysis( validRiskAnalysis2_0_Private, true, "PRIVATE", - new Date() + new Date(), + undefined ); expect(result).toEqual({ @@ -123,7 +130,8 @@ describe("Risk Analysis Validation", () => { validSchemaOnlyRiskAnalysis2_0_Private, true, "PRIVATE", - new Date() + new Date(), + undefined ); expect(result).toEqual({ @@ -137,13 +145,15 @@ describe("Risk Analysis Validation", () => { validRiskAnalysis2_0_Private, false, "GSP", - new Date() + new Date(), + undefined ); const resultSchemaOnly = validateRiskAnalysis( validRiskAnalysis2_0_Private, true, "GSP", - new Date() + new Date(), + undefined ); expect(result).toEqual({ @@ -164,7 +174,8 @@ describe("Risk Analysis Validation", () => { validSchemaOnlyRiskAnalysis2_0_Private, true, "GSP", - new Date() + new Date(), + undefined ); expect(result).toEqual({ @@ -181,7 +192,13 @@ describe("Risk Analysis Validation", () => { }; expect( - validateRiskAnalysis(invalidRiskAnalysis, false, "PA", new Date()) + validateRiskAnalysis( + invalidRiskAnalysis, + false, + "PA", + new Date(), + undefined + ) ).toEqual({ type: "invalid", issues: [rulesVersionNotFoundError("PA", invalidVersionForPA)], @@ -194,7 +211,13 @@ describe("Risk Analysis Validation", () => { }; expect( - validateRiskAnalysis(invalidRiskAnalysis2, false, "PRIVATE", new Date()) + validateRiskAnalysis( + invalidRiskAnalysis2, + false, + "PRIVATE", + new Date(), + undefined + ) ).toEqual({ type: "invalid", issues: [rulesVersionNotFoundError("PRIVATE", invalidVersionForPrivate)], @@ -209,7 +232,13 @@ describe("Risk Analysis Validation", () => { }; expect( - validateRiskAnalysis(expiredRiskAnalysis, false, "PA", new Date()) + validateRiskAnalysis( + expiredRiskAnalysis, + false, + "PA", + new Date(), + undefined + ) ).toEqual({ type: "invalid", issues: [expiredRulesVersionError(expiredVersionForPA, tenantKind.PA)], @@ -222,7 +251,13 @@ describe("Risk Analysis Validation", () => { }; expect( - validateRiskAnalysis(expiredRiskAnalysis2, false, "PRIVATE", new Date()) + validateRiskAnalysis( + expiredRiskAnalysis2, + false, + "PRIVATE", + new Date(), + undefined + ) ).toEqual({ type: "invalid", issues: [expiredRulesVersionError(expiredVersionForPrivate, "PRIVATE")], @@ -241,17 +276,17 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - { - type: "invalid", - issues: [ - dependencyNotFoundError("reasonPolicyNotProvided", "policyProvided"), - dependencyNotFoundError("confirmedDoneDpia", "doneDpia"), - missingExpectedFieldError("policyProvided"), - missingExpectedFieldError("doneDpia"), - ], - } - ); + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual({ + type: "invalid", + issues: [ + dependencyNotFoundError("reasonPolicyNotProvided", "policyProvided"), + dependencyNotFoundError("confirmedDoneDpia", "doneDpia"), + missingExpectedFieldError("policyProvided"), + missingExpectedFieldError("doneDpia"), + ], + }); }); it("should succeed schema only even if a provided answer depends on a missing field", () => { @@ -265,7 +300,9 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, true, "PA", new Date())).toEqual({ + expect( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date(), undefined) + ).toEqual({ type: "valid", value: { version: validRiskAnalysis3_0_Pa.version, @@ -290,29 +327,29 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - { - type: "invalid", - issues: [ - unexpectedDependencyValueError( - "legalBasisPublicInterest", - "legalBasis", - "PUBLIC_INTEREST" - ), - unexpectedDependencyValueError( - "ruleOfLawText", - "legalBasisPublicInterest", - "RULE_OF_LAW" - ), - unexpectedDependencyValueError( - "ruleOfLawText", - "legalBasis", - "PUBLIC_INTEREST" - ), - unexpectedDependencyValueError("otherPurpose", "purpose", "OTHER"), - ], - } - ); + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual({ + type: "invalid", + issues: [ + unexpectedDependencyValueError( + "legalBasisPublicInterest", + "legalBasis", + "PUBLIC_INTEREST" + ), + unexpectedDependencyValueError( + "ruleOfLawText", + "legalBasisPublicInterest", + "RULE_OF_LAW" + ), + unexpectedDependencyValueError( + "ruleOfLawText", + "legalBasis", + "PUBLIC_INTEREST" + ), + unexpectedDependencyValueError("otherPurpose", "purpose", "OTHER"), + ], + }); }); it("should succeed schema only even if a provided answer depends on an existing field with an unexpected value", () => { @@ -326,7 +363,9 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, true, "PA", new Date())).toEqual({ + expect( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date(), undefined) + ).toEqual({ type: "valid", value: { version: riskAnalysis.version, @@ -355,15 +394,15 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - { - type: "invalid", - issues: [ - missingExpectedFieldError("deliveryMethod"), - missingExpectedFieldError("doneDpia"), - ], - } - ); + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual({ + type: "invalid", + issues: [ + missingExpectedFieldError("deliveryMethod"), + missingExpectedFieldError("doneDpia"), + ], + }); }); it("should succeeed schema only even on missing expected answers", () => { @@ -378,7 +417,9 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, true, "PA", new Date())).toEqual({ + expect( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date(), undefined) + ).toEqual({ type: "valid", value: { version: riskAnalysis.version, @@ -404,20 +445,22 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - validateRiskAnalysis(riskAnalysis, true, "PA", new Date()) + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date(), undefined) ); - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - { - type: "invalid", - issues: [ - unexpectedFieldError("unexpectedFieldA"), - unexpectedFieldError("unexpectedFieldB"), - unexpectedFieldError("unexpectedFieldC"), - ], - } - ); + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual({ + type: "invalid", + issues: [ + unexpectedFieldError("unexpectedFieldA"), + unexpectedFieldError("unexpectedFieldB"), + unexpectedFieldError("unexpectedFieldC"), + ], + }); }); it("should fail on unexpected field value both schema only and not", () => { @@ -431,30 +474,142 @@ describe("Risk Analysis Validation", () => { }, }; - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - validateRiskAnalysis(riskAnalysis, true, "PA", new Date()) + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual( + validateRiskAnalysis(riskAnalysis, true, "PA", new Date(), undefined) ); - expect(validateRiskAnalysis(riskAnalysis, false, "PA", new Date())).toEqual( - { - type: "invalid", - issues: [ - unexpectedFieldValueError( - "purpose", - new Set(["INSTITUTIONAL", "OTHER"]) - ), - unexpectedFieldValueError( - "legalBasis", - new Set([ - "CONSENT", - "CONTRACT", - "LEGAL_OBLIGATION", - "SAFEGUARD", - "PUBLIC_INTEREST", - ]) - ), - ], - } - ); + expect( + validateRiskAnalysis(riskAnalysis, false, "PA", new Date(), undefined) + ).toEqual({ + type: "invalid", + issues: [ + unexpectedFieldValueError( + "purpose", + new Set(["INSTITUTIONAL", "OTHER"]) + ), + unexpectedFieldValueError( + "legalBasis", + new Set([ + "CONSENT", + "CONTRACT", + "LEGAL_OBLIGATION", + "SAFEGUARD", + "PUBLIC_INTEREST", + ]) + ), + ], + }); + }); + + it("should fail if the risk analysis is PRIVATE 2.0 and the eservice has different personalData", () => { + const riskAnalysisForm: RiskAnalysisFormToValidate = { + ...validRiskAnalysis2_0_Private, + answers: { + ...validRiskAnalysis2_0_Private.answers, + usesPersonalData: ["YES"], + }, + }; + expect( + validateRiskAnalysis(riskAnalysisForm, false, "GSP", new Date(), false) + ).toEqual({ + type: "invalid", + issues: [incompatiblePersonalDataError()], + }); + }); + + it("should succeed if the risk analysis is PRIVATE 2.0 and the eservice doesn't have the personalData flag", () => { + expect( + validateRiskAnalysis( + validRiskAnalysis2_0_Private, + false, + "GSP", + new Date(), + undefined + ) + ).toEqual({ + type: "valid", + value: validatedRiskAnalysis2_0_Private, + }); + }); + + it.each([true, false])( + "should succeed if the risk analysis is PA 3.0 and the eservice has any personalData flag", + (personalDataInEService) => { + expect( + validateRiskAnalysis( + validRiskAnalysis3_0_Pa, + false, + "PA", + new Date(), + personalDataInEService + ) + ).toEqual({ + type: "valid", + value: validatedRiskAnalysis3_0_Pa, + }); + } + ); + + /* + it("should fail if the risk analysis is PA 3.1 and the eservice has different personalData", () => { + const riskAnalysisForm: RiskAnalysisFormToValidate = { + ...validRiskAnalysis3_1_Pa, + answers: { + ...validRiskAnalysis3_1_Pa.answers, + usesPersonalData: ["YES"], + }, + }; + expect( + validateRiskAnalysis(riskAnalysisForm, false, "PA", new Date(), false) + ).toEqual({ + type: "invalid", + issues: [incompatiblePersonalDataError()], + }); }); + + it("should succeed if the risk analysis is PA 3.1 and the eservice doesn't have the personalData flag", () => { + expect( + validateRiskAnalysis( + validRiskAnalysis3_1_Pa, + false, + "PA", + new Date(), + undefined + ) + ).toEqual({ + type: "valid", + value: validatedRiskAnalysis3_1_Pa, + }); + }); + + it.each([ + { personalDataInEService: true, usesPersonalData: "YES" }, + { personalDataInEService: false, usesPersonalData: "NO" }, + ])( + "should succeed if the risk analysis is PA 3.1 and the eservice has consistent personalData flag", + ({ personalDataInEService, usesPersonalData }) => { + const riskAnalysisForm: RiskAnalysisFormToValidate = { + ...validRiskAnalysis3_1_Pa, + answers: { + ...validRiskAnalysis3_1_Pa.answers, + usesPersonalData: [usesPersonalData], + }, + }; + expect( + validateRiskAnalysis( + riskAnalysisForm, + false, + "PA", + new Date(), + personalDataInEService + ) + ).toEqual({ + type: "valid", + value: validatedRiskAnalysis3_1_Pa, + }); + } + ); + */ }); diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts index 0b516f4567..822db9a22d 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidation.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidation.ts @@ -13,6 +13,7 @@ import { RiskAnalysisValidationIssue, dependencyNotFoundError, expiredRulesVersionError, + incompatiblePersonalDataError, missingExpectedFieldError, rulesVersionNotFoundError, unexpectedDependencyValueError, @@ -20,18 +21,24 @@ import { unexpectedFieldFormatError, unexpectedFieldValueError, } from "./riskAnalysisValidationErrors.js"; + import { FormQuestionRules, RiskAnalysisFormRules, dataType, } from "./rules/riskAnalysisFormRules.js"; -import { riskAnalysisFormRules } from "./rules/riskAnalysisFormRulesProvider.js"; +import { + buildLabel, + formRules, + riskAnalysisFormRules, +} from "./rules/riskAnalysisFormRulesProvider.js"; export function validateRiskAnalysis( riskAnalysisForm: RiskAnalysisFormToValidate, schemaOnlyValidation: boolean, tenantKind: TenantKind, - dateForExpirationValidation: Date + dateForExpirationValidation: Date, + personalDataInEService: boolean | undefined ): RiskAnalysisValidationResult { const formRulesForValidation = getFormRulesByVersion( tenantKind, @@ -91,7 +98,23 @@ export function validateRiskAnalysis( multiAnswers: [], } ); + const personalDataInRiskAnalysis = match( + singleAnswers.find((a) => a.key === "usesPersonalData")?.value + ) + .with("YES", () => true) + .with("NO", () => false) + .otherwise(() => undefined); + const personalDataFlagValidation = validatePersonalDataFlag({ + tenantKind, + version: formRulesForValidation.version, + personalDataInRiskAnalysis, + personalDataInEService, + }); + + if (personalDataFlagValidation.length > 0) { + return invalidResult(personalDataFlagValidation); + } return validResult({ version: formRulesForValidation.version, singleAnswers, @@ -379,3 +402,37 @@ export function validResult(value: T): RiskAnalysisValidationResult { value, }; } + +const validatePersonalDataFlag = ({ + tenantKind, + version, + personalDataInRiskAnalysis, + personalDataInEService, +}: { + tenantKind: TenantKind; + version: string; + personalDataInRiskAnalysis: boolean | undefined; + personalDataInEService: boolean | undefined; +}): RiskAnalysisValidationIssue[] => { + const label = buildLabel(tenantKind, version); + return match(label) + .with( + formRules.PA_1_0, + formRules.PA_2_0, + formRules.PA_3_0, + formRules.PRIVATE_1_0, + () => [] + ) + .with(formRules.PA_3_1, formRules.PRIVATE_2_0, () => + match(personalDataInEService) + .with(P.boolean, () => { + if (personalDataInEService !== personalDataInRiskAnalysis) { + return [incompatiblePersonalDataError()]; + } + return []; + }) + .with(undefined, () => []) + .exhaustive() + ) + .exhaustive(); +}; diff --git a/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts b/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts index 97349222f4..d3b12fd948 100644 --- a/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts +++ b/packages/commons/src/risk-analysis/riskAnalysisValidationErrors.ts @@ -8,7 +8,8 @@ type RiskAnalysisValidationIssueCode = | "dependencyNotFoundError" | "unexpectedDependencyValueError" | "unexpectedFieldFormatError" - | "missingExpectedFieldError"; + | "missingExpectedFieldError" + | "incompatiblePersonalDataError"; export class RiskAnalysisValidationIssue extends InternalError { constructor({ @@ -101,3 +102,10 @@ export function missingExpectedFieldError( detail: `Expected field ${fieldName} not found in form`, }); } + +export function incompatiblePersonalDataError(): RiskAnalysisValidationIssue { + return new RiskAnalysisValidationIssue({ + code: "incompatiblePersonalDataError", + detail: `The usesPersonalData answer doesn't match the personalData flag of the eservice`, + }); +} diff --git a/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts b/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts index 063754cdf6..62f2fec76e 100644 --- a/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts +++ b/packages/commons/src/risk-analysis/rules/riskAnalysisFormRulesProvider.ts @@ -1,5 +1,10 @@ -import { TenantKind } from "pagopa-interop-models"; +import { + genericInternalError, + tenantKind, + TenantKind, +} from "pagopa-interop-models"; import { match } from "ts-pattern"; +import { z } from "zod"; import { pa1 } from "./PA/1.0.js"; import { pa2 } from "./PA/2.0.js"; import { pa3 } from "./PA/3.0.js"; @@ -7,22 +12,41 @@ import { private1 } from "./PRIVATE/1.0.js"; import { private2 } from "./PRIVATE/2.0.js"; import { RiskAnalysisFormRules } from "./riskAnalysisFormRules.js"; -const formRules = { - pa1, - pa2, - pa3, - private1, - private2, -}; +export const formRules = { + PA_1_0: "PA-1.0", + PA_2_0: "PA-2.0", + PA_3_0: "PA-3.0", + PA_3_1: "PA-3.1", + PRIVATE_1_0: "PRIVATE-1.0", + PRIVATE_2_0: "PRIVATE-2.0", +} as const; +export const FormRules = z.enum([ + Object.values(formRules)[0], + ...Object.values(formRules).slice(1), +]); +export type FormRules = z.infer; + +export function buildLabel(kind: TenantKind, version: string): FormRules { + const kindForRA = kind === tenantKind.PA ? tenantKind.PA : tenantKind.PRIVATE; + const parsed = FormRules.safeParse(`${kindForRA}-${version}`); + + if (!parsed.success) { + throw genericInternalError( + `Unsupported ruleset for kind ${kind} and version ${version}` + ); + } + return parsed.data; +} -function getFormRules(ruleset: keyof typeof formRules): RiskAnalysisFormRules { +function getFormRules(ruleset: FormRules): RiskAnalysisFormRules { return RiskAnalysisFormRules.parse( match(ruleset) - .with("pa1", () => pa1) - .with("pa2", () => pa2) - .with("pa3", () => pa3) - .with("private1", () => private1) - .with("private2", () => private2) + .with(formRules.PA_1_0, () => pa1) + .with(formRules.PA_2_0, () => pa2) + .with(formRules.PA_3_0, () => pa3) + .with(formRules.PA_3_1, () => pa3) // TODO replace with pa31 + .with(formRules.PRIVATE_1_0, () => private1) + .with(formRules.PRIVATE_2_0, () => private2) .exhaustive() ); } @@ -31,8 +55,9 @@ export const riskAnalysisFormRules: Record< TenantKind, RiskAnalysisFormRules[] > = { - PA: [getFormRules("pa1"), getFormRules("pa2"), getFormRules("pa3")], - PRIVATE: [getFormRules("private1"), getFormRules("private2")], - GSP: [getFormRules("private1"), getFormRules("private2")], - SCP: [getFormRules("private1"), getFormRules("private2")], + // TODO add PA 3.1 + PA: [getFormRules("PA-1.0"), getFormRules("PA-2.0"), getFormRules("PA-3.0")], + PRIVATE: [getFormRules("PRIVATE-1.0"), getFormRules("PRIVATE-2.0")], + GSP: [getFormRules("PRIVATE-1.0"), getFormRules("PRIVATE-2.0")], + SCP: [getFormRules("PRIVATE-1.0"), getFormRules("PRIVATE-2.0")], }; diff --git a/packages/eservice-template-process/src/services/eserviceTemplateService.ts b/packages/eservice-template-process/src/services/eserviceTemplateService.ts index 001aec8c3f..564b7af8ba 100644 --- a/packages/eservice-template-process/src/services/eserviceTemplateService.ts +++ b/packages/eservice-template-process/src/services/eserviceTemplateService.ts @@ -250,13 +250,15 @@ const replaceEServiceTemplateVersion = ( export function validateRiskAnalysisSchemaOrThrow( riskAnalysisForm: eserviceTemplateApi.EServiceTemplateRiskAnalysisSeed["riskAnalysisForm"], tenantKind: TenantKind, - dateForExpirationValidation: Date + dateForExpirationValidation: Date, + personalDataInEService: boolean | undefined ): RiskAnalysisValidatedForm { const result = validateRiskAnalysis( riskAnalysisForm, true, tenantKind, - dateForExpirationValidation + dateForExpirationValidation, + personalDataInEService ); if (result.type === "invalid") { throw riskAnalysisValidationFailed(result.issues); @@ -973,7 +975,8 @@ export function eserviceTemplateServiceBuilder( const validatedRiskAnalysisForm = validateRiskAnalysisSchemaOrThrow( createRiskAnalysis.riskAnalysisForm, createRiskAnalysis.tenantKind, - new Date() + new Date(), + template.data.personalData ); const newRiskAnalysis: EServiceTemplateRiskAnalysis = @@ -1076,7 +1079,8 @@ export function eserviceTemplateServiceBuilder( const validatedForm = validateRiskAnalysisSchemaOrThrow( updateRiskAnalysisSeed.riskAnalysisForm, updateRiskAnalysisSeed.tenantKind, - new Date() + new Date(), + template.data.personalData ); const updatedRiskAnalysisForm: RiskAnalysisForm = { diff --git a/packages/eservice-template-process/src/services/validators.ts b/packages/eservice-template-process/src/services/validators.ts index 044e3f6c37..6da458b9b3 100644 --- a/packages/eservice-template-process/src/services/validators.ts +++ b/packages/eservice-template-process/src/services/validators.ts @@ -164,7 +164,8 @@ export function assertRiskAnalysisIsValidForPublication( ), false, riskAnalysis.tenantKind, - new Date() + new Date(), + eserviceTemplate.personalData ); if (result.type === "invalid") { diff --git a/packages/purpose-process/src/services/purposeService.ts b/packages/purpose-process/src/services/purposeService.ts index 488043ac9c..5dcd3c32ec 100644 --- a/packages/purpose-process/src/services/purposeService.ts +++ b/packages/purpose-process/src/services/purposeService.ts @@ -292,7 +292,8 @@ export function purposeServiceBuilder( purpose.data.riskAnalysisForm, false, tenantKind, - purpose.data.createdAt + purpose.data.createdAt, + eservice.personalData ) : true; @@ -875,7 +876,8 @@ export function purposeServiceBuilder( purpose.data.riskAnalysisForm, false, tenantKind, - new Date() + new Date(), + eservice.personalData ) : true; @@ -1039,6 +1041,7 @@ export function purposeServiceBuilder( schemaOnlyValidation: false, tenantKind, dateForExpirationValidation: new Date(), // beware: if the purpose version was waiting for approval, a new RA might have been published + personalDataInEService: eservice.personalData, }); } @@ -1274,11 +1277,13 @@ export function purposeServiceBuilder( const createdAt = new Date(); + const eservice = await retrieveEService(eserviceId, readModelService); const validatedFormSeed = validateAndTransformRiskAnalysis( purposeSeed.riskAnalysisForm, false, await retrieveTenantKind(authData.organizationId, readModelService), - createdAt + createdAt, + eservice.personalData ); await retrieveActiveAgreement(eserviceId, consumerId, readModelService); @@ -1378,6 +1383,7 @@ export function purposeServiceBuilder( schemaOnlyValidation: false, tenantKind: producerKind, dateForExpirationValidation: createdAt, + personalDataInEService: eservice.personalData, }); const newVersion: PurposeVersion = { @@ -1490,9 +1496,10 @@ export function purposeServiceBuilder( ? `${title}${suffix}` : `${title.slice(0, prefixLengthAllowance)}${dots}${suffix}`; + const eserviceId = unsafeBrandId(seed.eserviceId); await assertPurposeTitleIsNotDuplicated({ readModelService, - eserviceId: unsafeBrandId(seed.eserviceId), + eserviceId, consumerId: organizationId, title: clonedPurposeTitle, }); @@ -1511,6 +1518,8 @@ export function purposeServiceBuilder( delegationId: purposeToClone.data.delegationId, }; + const eservice = await retrieveEService(eserviceId, readModelService); + const isRiskAnalysisValid = clonedRiskAnalysisForm ? validateRiskAnalysis( riskAnalysisFormToRiskAnalysisFormToValidate( @@ -1518,7 +1527,8 @@ export function purposeServiceBuilder( ), false, tenantKind, - currentDate + currentDate, + eservice.personalData ).type === "valid" : false; @@ -1719,7 +1729,8 @@ const performUpdatePurpose = async ( riskAnalysisForm, true, tenantKind, - new Date() + new Date(), + eservice.personalData ) : purpose.data.riskAnalysisForm; @@ -1763,7 +1774,8 @@ const performUpdatePurpose = async ( updatedPurpose.riskAnalysisForm, false, tenantKind, - new Date() + new Date(), + eservice.personalData ), }, metadata: { version: createdEvent.newVersion }, diff --git a/packages/purpose-process/src/services/validators.ts b/packages/purpose-process/src/services/validators.ts index 892725e9e2..baa6a1b27f 100644 --- a/packages/purpose-process/src/services/validators.ts +++ b/packages/purpose-process/src/services/validators.ts @@ -50,7 +50,8 @@ export const isRiskAnalysisFormValid = ( riskAnalysisForm: RiskAnalysisForm | undefined, schemaOnlyValidation: boolean, tenantKind: TenantKind, - dateForExpirationValidation: Date + dateForExpirationValidation: Date, + personalDataInEService: boolean | undefined ): boolean => { if (riskAnalysisForm === undefined) { return false; @@ -60,7 +61,8 @@ export const isRiskAnalysisFormValid = ( riskAnalysisFormToRiskAnalysisFormToValidate(riskAnalysisForm), schemaOnlyValidation, tenantKind, - dateForExpirationValidation + dateForExpirationValidation, + personalDataInEService ).type === "valid" ); } @@ -117,17 +119,20 @@ export function validateRiskAnalysisOrThrow({ schemaOnlyValidation, tenantKind, dateForExpirationValidation, + personalDataInEService, }: { riskAnalysisForm: purposeApi.RiskAnalysisFormSeed; schemaOnlyValidation: boolean; tenantKind: TenantKind; dateForExpirationValidation: Date; + personalDataInEService: boolean | undefined; }): RiskAnalysisValidatedForm { const result = validateRiskAnalysis( riskAnalysisForm, schemaOnlyValidation, tenantKind, - dateForExpirationValidation + dateForExpirationValidation, + personalDataInEService ); return match(result) .with({ type: "invalid" }, ({ issues }) => { @@ -141,7 +146,8 @@ export function validateAndTransformRiskAnalysis( riskAnalysisForm: purposeApi.RiskAnalysisFormSeed | undefined, schemaOnlyValidation: boolean, tenantKind: TenantKind, - dateForExpirationValidation: Date + dateForExpirationValidation: Date, + personalDataInEService: boolean | undefined ): PurposeRiskAnalysisForm | undefined { if (!riskAnalysisForm) { return undefined; @@ -151,6 +157,7 @@ export function validateAndTransformRiskAnalysis( schemaOnlyValidation, tenantKind, dateForExpirationValidation, + personalDataInEService, }); return { diff --git a/packages/purpose-process/test/integration/activatePurposeVersion.test.ts b/packages/purpose-process/test/integration/activatePurposeVersion.test.ts index da327fdf90..69e36b93af 100644 --- a/packages/purpose-process/test/integration/activatePurposeVersion.test.ts +++ b/packages/purpose-process/test/integration/activatePurposeVersion.test.ts @@ -1541,7 +1541,8 @@ describe("activatePurposeVersion", () => { riskAnalysisFormToRiskAnalysisFormToValidate(riskAnalysisForm), false, mockConsumer.kind as TenantKind, - new Date() + new Date(), + undefined ); expect(async () => { diff --git a/packages/purpose-process/test/mockUtils.ts b/packages/purpose-process/test/mockUtils.ts index 455f975270..2d038d8b6c 100644 --- a/packages/purpose-process/test/mockUtils.ts +++ b/packages/purpose-process/test/mockUtils.ts @@ -92,7 +92,8 @@ export const createUpdatedPurpose = ( purposeUpdateContent.riskAnalysisForm, false, tenantKind, - new Date() + new Date(), + undefined )!, writtenRiskAnalysisForm ),