From d39f6519411a0b2f07c0c234777a82bea6c6f423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Dubigny?= Date: Tue, 24 Mar 2026 15:27:57 +0100 Subject: [PATCH 1/2] WIP --- .../src/controllers/interaction.controller.ts | 8 +++----- .../core-fca-low/src/dto/identity-for-sp.dto.ts | 6 +++--- .../src/services/identity.sanitizer.ts | 4 ++-- .../src/services/cached-organization.service.ts | 14 +++++++------- .../src/services/logger-session.service.ts | 1 + 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/back/apps/core-fca-low/src/controllers/interaction.controller.ts b/back/apps/core-fca-low/src/controllers/interaction.controller.ts index 27daafac4..733cc207e 100644 --- a/back/apps/core-fca-low/src/controllers/interaction.controller.ts +++ b/back/apps/core-fca-low/src/controllers/interaction.controller.ts @@ -249,7 +249,7 @@ export class InteractionController { // is_service_public field is only provided by ProConnect Identité // any identity without an is_service_public field is considered to be from the public sector const isPrivateSectorIdentity = idpIdentity?.is_service_public === false; - const isRoleAgentPublic = !roles || roles.includes("agent_public"); + const isRoleAgentPublic = roles.includes("agent_public"); const doesNotAcceptPrivateSectorEmployees = spType === "public"; if ( @@ -258,10 +258,8 @@ export class InteractionController { ) { this.logger.warn({ code: "agent_public_role_mismatch", - roles, - is_service_public: idpIdentity?.is_service_public, - spType, - siret: idpIdentity?.siret, + isPrivateSectorIdentity, + isRoleAgentPublic, }); } if (isPrivateSectorIdentity && doesNotAcceptPrivateSectorEmployees) { diff --git a/back/apps/core-fca-low/src/dto/identity-for-sp.dto.ts b/back/apps/core-fca-low/src/dto/identity-for-sp.dto.ts index 1ae1d8cdd..94719f995 100644 --- a/back/apps/core-fca-low/src/dto/identity-for-sp.dto.ts +++ b/back/apps/core-fca-low/src/dto/identity-for-sp.dto.ts @@ -1,8 +1,8 @@ import { + IsArray, IsDefined, IsEnum, IsObject, - IsOptional, IsString, MaxLength, MinLength, @@ -35,6 +35,7 @@ export class IdentityForSpDto extends IdentityFromIdpDto { @IsString() idp_acr: string; + @IsArray() @IsEnum( [ "dirigeant", @@ -46,6 +47,5 @@ export class IdentityForSpDto extends IdentityFromIdpDto { ], { each: true }, ) - @IsOptional() - roles?: string[]; + roles: string[]; } diff --git a/back/apps/core-fca-low/src/services/identity.sanitizer.ts b/back/apps/core-fca-low/src/services/identity.sanitizer.ts index 9539e50e9..32e086012 100644 --- a/back/apps/core-fca-low/src/services/identity.sanitizer.ts +++ b/back/apps/core-fca-low/src/services/identity.sanitizer.ts @@ -65,6 +65,7 @@ export class IdentitySanitizer { const { featureFetchOrganizationData } = this.config.get("ApiEntreprise"); + identityForSp.roles = []; if (featureFetchOrganizationData && !!identityForSp.siret) { try { const cachedOrganization = @@ -74,11 +75,10 @@ export class IdentitySanitizer { const roles = this.cachedOrganizationService.computeRoles(cachedOrganization); identityForSp.roles = roles; - identityForSp.is_service_public = roles.includes("agent_public"); } catch (error) { this.logger.error({ code: "identity-sanitizer-cached-organization-error", - error, + originalError: error, }); } } diff --git a/back/libs/cached-organization/src/services/cached-organization.service.ts b/back/libs/cached-organization/src/services/cached-organization.service.ts index ed34e9955..679430fac 100644 --- a/back/libs/cached-organization/src/services/cached-organization.service.ts +++ b/back/libs/cached-organization/src/services/cached-organization.service.ts @@ -20,13 +20,13 @@ export class CachedOrganizationService { computeRoles(cachedOrganization: CachedOrganization): string[] { const roles: string[] = []; - const isServicePublic = isPublicService({ - cached_categorie_juridique: cachedOrganization.categorieJuridique, - cached_etat_administratif: cachedOrganization.etatAdministratif, - siret: cachedOrganization.siret, - }); - - if (isServicePublic) { + if ( + isPublicService({ + cached_categorie_juridique: cachedOrganization.categorieJuridique, + cached_etat_administratif: cachedOrganization.etatAdministratif, + siret: cachedOrganization.siret, + }) + ) { roles.push("agent_public"); } diff --git a/back/libs/logger-plugins/src/services/logger-session.service.ts b/back/libs/logger-plugins/src/services/logger-session.service.ts index 9b333eb3e..4c437e1d0 100644 --- a/back/libs/logger-plugins/src/services/logger-session.service.ts +++ b/back/libs/logger-plugins/src/services/logger-session.service.ts @@ -60,6 +60,7 @@ export class LoggerSessionService implements LoggerPluginServiceInterface { spSiret: spIdentity?.siret, spSiretHint, spSub: spIdentity?.sub, + spRoles: spIdentity?.roles, }; return context; From 332a78bb3ed5a8064aa51ac08b5aeadc633a7977 Mon Sep 17 00:00:00 2001 From: BenoitSerrano Date: Tue, 24 Mar 2026 16:46:49 +0100 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=85=20fix=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/controllers/interaction.controller.spec.ts | 12 ++++++------ .../src/services/identity.sanitizer.spec.ts | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/back/apps/core-fca-low/src/controllers/interaction.controller.spec.ts b/back/apps/core-fca-low/src/controllers/interaction.controller.spec.ts index 2e5236f24..63824a46e 100644 --- a/back/apps/core-fca-low/src/controllers/interaction.controller.spec.ts +++ b/back/apps/core-fca-low/src/controllers/interaction.controller.spec.ts @@ -395,7 +395,7 @@ describe("InteractionController", () => { const res: Partial = { redirect: jest.fn() }; const userSessionService = { get: jest.fn().mockReturnValue({ - spIdentity: { sub: "user1" }, + spIdentity: { sub: "user1", roles: ["agent_public"] }, interactionId: "interaction123", idpAcr: "high", spEssentialAcr: "high", @@ -443,7 +443,7 @@ describe("InteractionController", () => { const res = {} as Response; const userSessionService = { get: jest.fn().mockReturnValue({ - spIdentity: { sub: "user1" }, + spIdentity: { sub: "user1", roles: ["agent_public"] }, isSilentAuthentication: true, idpId: "idp123", }), @@ -461,7 +461,7 @@ describe("InteractionController", () => { const res = { redirect: jest.fn() } as unknown as Response; const userSessionService = { get: jest.fn().mockReturnValue({ - spIdentity: { sub: "user1" }, + spIdentity: { sub: "user1", roles: ["agent_public"] }, isSilentAuthentication: false, interactionId: "interaction123", idpId: "idp123", @@ -483,7 +483,7 @@ describe("InteractionController", () => { const res = {} as Response; const userSessionService = { get: jest.fn().mockReturnValue({ - spIdentity: { sub: "user1", roles: [] }, + spIdentity: { sub: "user1", roles: ["agent_public"] }, spId: "sp123", idpId: "idp123", idpIdentity: { is_service_public: false }, @@ -503,7 +503,7 @@ describe("InteractionController", () => { const res = {} as Response; const userSessionService = { get: jest.fn().mockReturnValue({ - spIdentity: { sub: "user1" }, + spIdentity: { sub: "user1", roles: ["agent_public"] }, spId: "sp123", idpId: "idp123", idpIdentity: { is_service_public: false }, @@ -524,7 +524,7 @@ describe("InteractionController", () => { const res = {} as Response; const userSessionService = { get: jest.fn().mockReturnValue({ - spIdentity: { sub: "user1" }, + spIdentity: { sub: "user1", roles: ["agent_public"] }, spEssentialAcr: "high", idpAcr: "low", }), diff --git a/back/apps/core-fca-low/src/services/identity.sanitizer.spec.ts b/back/apps/core-fca-low/src/services/identity.sanitizer.spec.ts index c9d7a859c..11ddc0968 100644 --- a/back/apps/core-fca-low/src/services/identity.sanitizer.spec.ts +++ b/back/apps/core-fca-low/src/services/identity.sanitizer.spec.ts @@ -160,6 +160,7 @@ describe("IdentitySanitizer", () => { sub, uid: "UID123", usual_name: "Doe", + roles: [], }); }); @@ -174,6 +175,7 @@ describe("IdentitySanitizer", () => { usual_name: "Doe", uid: "UID123", siret: "12345678900007", + is_service_public: true, }; config.get = jest.fn().mockReturnValue({ @@ -195,7 +197,6 @@ describe("IdentitySanitizer", () => { cachedOrganizationService.getCachedOrganizationBySiret, ).toHaveBeenCalledWith("12345678900007"); expect(identityForSp.roles).toEqual(["agent_public"]); - expect(identityForSp.is_service_public).toBe(true); }); it("should handle error when getCachedOrganizationBySiret throws", async () => { @@ -229,10 +230,9 @@ describe("IdentitySanitizer", () => { expect(logger.error).toHaveBeenCalledWith({ code: "identity-sanitizer-cached-organization-error", - error, + originalError: error, }); - expect(result.roles).toBeUndefined(); - expect(result.is_service_public).toBeUndefined(); + expect(result.roles).toEqual([]); }); it("should not throw CoreFcaInvalidIdentityException when phone number is invalid", async () => {