@proconnect-gouv/proconnect.identite 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/managers/certification/certification-score.js +2 -2
- package/dist/managers/organization/force-join-organization.d.ts +1 -1
- package/dist/managers/user/assign-user-verification-type-to-domain.js +2 -2
- package/dist/repositories/organization/find-by-user-id.d.ts +1 -1
- package/dist/repositories/organization/get-users-by-organization.d.ts +1 -1
- package/dist/repositories/organization/link-user-to-organization.d.ts +1 -1
- package/dist/repositories/user/update-user-organization-link.d.ts +1 -1
- package/dist/types/user-organization-link.d.ts +10 -10
- package/dist/types/user-organization-link.d.ts.map +1 -1
- package/dist/types/user-organization-link.js +9 -4
- package/package.json +1 -1
- package/src/managers/certification/certification-score.ts +2 -2
- package/src/managers/certification/process-certification-dirigeant.test.ts +83 -18
- package/src/managers/user/assign-user-verification-type-to-domain.ts +2 -2
- package/src/types/user-organization-link.ts +10 -4
- package/testing/seed/franceconnect/index.ts +14 -0
- package/tsconfig.lib.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @proconnect-gouv/proconnect.identite
|
|
2
2
|
|
|
3
|
+
## 1.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1764](https://github.com/proconnect-gouv/proconnect-identite/pull/1764) [`6484e64`](https://github.com/proconnect-gouv/proconnect-identite/commit/6484e64f558493b5963d32681dab645484b87693) Thanks [@rdubigny](https://github.com/rdubigny)! - Ajout d'une catégorie SuperWeakLinkTypes pour gérer les cas des domaines non vérifiés
|
|
8
|
+
|
|
3
9
|
## 1.5.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
|
@@ -71,8 +71,8 @@ export function certificationScore(identitePivot, sourceDirigeant) {
|
|
|
71
71
|
else {
|
|
72
72
|
// For foreigners: check country code (with conversion if needed from RNE)
|
|
73
73
|
// Both should already be in COG format (99XXX)
|
|
74
|
-
if (identitePivot.birthcountry
|
|
75
|
-
sourceDirigeant.birthcountry
|
|
74
|
+
if (identitePivot.birthcountry === null ||
|
|
75
|
+
sourceDirigeant.birthcountry === null ||
|
|
76
76
|
identitePivot.birthcountry === sourceDirigeant.birthcountry) {
|
|
77
77
|
matches.add(MatchCriteria.enum.birth_country);
|
|
78
78
|
}
|
|
@@ -13,7 +13,7 @@ export declare function forceJoinOrganizationFactory({ findEmailDomainsByOrganiz
|
|
|
13
13
|
is_external?: boolean;
|
|
14
14
|
}) => Promise<{
|
|
15
15
|
is_external: boolean;
|
|
16
|
-
verification_type: "
|
|
16
|
+
verification_type: "organization_dirigeant" | "code_sent_to_official_contact_email" | "domain" | "imported_from_coop_mediation_numerique" | "imported_from_inclusion_connect" | "in_liste_dirigeants_rna" | "in_liste_dirigeants_rne" | "official_contact_email" | "ordre_professionnel_domain" | "proof_received" | "verified_by_coop_mediation_numerique" | "bypassed" | "domain_not_verified_yet" | "no_validation_means_available" | "no_verification_means_for_entreprise_unipersonnelle" | "no_verification_means_for_small_association";
|
|
17
17
|
verified_at: Date | null;
|
|
18
18
|
has_been_greeted: boolean;
|
|
19
19
|
needs_official_contact_email_verification: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//
|
|
2
|
-
import { LinkTypes, UnverifiedLinkTypes } from "#src/types";
|
|
2
|
+
import { LinkTypes, SuperWeakLinkTypes, UnverifiedLinkTypes } from "#src/types";
|
|
3
3
|
import { getEmailDomain } from "@proconnect-gouv/proconnect.core/services/email";
|
|
4
4
|
import { match } from "ts-pattern";
|
|
5
5
|
export function assignUserVerificationTypeToDomainFactory({ getUsers, updateUserOrganizationLink, }) {
|
|
@@ -9,7 +9,7 @@ export function assignUserVerificationTypeToDomainFactory({ getUsers, updateUser
|
|
|
9
9
|
const userDomain = getEmailDomain(email);
|
|
10
10
|
if (userDomain === domain &&
|
|
11
11
|
match(link_verification_type)
|
|
12
|
-
.with(...UnverifiedLinkTypes, () => true)
|
|
12
|
+
.with(...UnverifiedLinkTypes, ...SuperWeakLinkTypes, () => true)
|
|
13
13
|
.otherwise(() => false)) {
|
|
14
14
|
return updateUserOrganizationLink(organization_id, id, {
|
|
15
15
|
verification_type: LinkTypes.enum.domain,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DatabaseContext, Organization } from "#src/types";
|
|
2
2
|
export declare function findByUserIdFactory({ pg }: DatabaseContext): (userId: number) => Promise<(Organization & {
|
|
3
3
|
is_external: boolean;
|
|
4
|
-
verification_type: "
|
|
4
|
+
verification_type: "organization_dirigeant" | "code_sent_to_official_contact_email" | "domain" | "imported_from_coop_mediation_numerique" | "imported_from_inclusion_connect" | "in_liste_dirigeants_rna" | "in_liste_dirigeants_rne" | "official_contact_email" | "ordre_professionnel_domain" | "proof_received" | "verified_by_coop_mediation_numerique" | "bypassed" | "domain_not_verified_yet" | "no_validation_means_available" | "no_verification_means_for_entreprise_unipersonnelle" | "no_verification_means_for_small_association";
|
|
5
5
|
verified_at: Date | null;
|
|
6
6
|
has_been_greeted: boolean;
|
|
7
7
|
needs_official_contact_email_verification: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DatabaseContext, User } from "#src/types";
|
|
2
2
|
export declare function getUsersByOrganizationFactory({ pg }: DatabaseContext): (organization_id: number, additionalWhereClause?: string, additionalParams?: any[]) => Promise<(User & {
|
|
3
3
|
is_external: boolean;
|
|
4
|
-
verification_type: "
|
|
4
|
+
verification_type: "organization_dirigeant" | "code_sent_to_official_contact_email" | "domain" | "imported_from_coop_mediation_numerique" | "imported_from_inclusion_connect" | "in_liste_dirigeants_rna" | "in_liste_dirigeants_rne" | "official_contact_email" | "ordre_professionnel_domain" | "proof_received" | "verified_by_coop_mediation_numerique" | "bypassed" | "domain_not_verified_yet" | "no_validation_means_available" | "no_verification_means_for_entreprise_unipersonnelle" | "no_verification_means_for_small_association";
|
|
5
5
|
verified_at: Date | null;
|
|
6
6
|
has_been_greeted: boolean;
|
|
7
7
|
needs_official_contact_email_verification: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DatabaseContext, InsertUserOrganizationLink } from "#src/types";
|
|
2
2
|
export declare function linkUserToOrganizationFactory({ pg }: DatabaseContext): ({ is_external, needs_official_contact_email_verification, organization_id, user_id, verification_type, }: InsertUserOrganizationLink) => Promise<{
|
|
3
3
|
is_external: boolean;
|
|
4
|
-
verification_type: "
|
|
4
|
+
verification_type: "organization_dirigeant" | "code_sent_to_official_contact_email" | "domain" | "imported_from_coop_mediation_numerique" | "imported_from_inclusion_connect" | "in_liste_dirigeants_rna" | "in_liste_dirigeants_rne" | "official_contact_email" | "ordre_professionnel_domain" | "proof_received" | "verified_by_coop_mediation_numerique" | "bypassed" | "domain_not_verified_yet" | "no_validation_means_available" | "no_verification_means_for_entreprise_unipersonnelle" | "no_verification_means_for_small_association";
|
|
5
5
|
verified_at: Date | null;
|
|
6
6
|
has_been_greeted: boolean;
|
|
7
7
|
needs_official_contact_email_verification: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DatabaseContext, UserOrganizationLink } from "#src/types";
|
|
2
2
|
export declare function updateUserOrganizationLinkFactory({ pg }: DatabaseContext): (organization_id: number, user_id: number, fieldsToUpdate: Partial<UserOrganizationLink>) => Promise<{
|
|
3
3
|
is_external: boolean;
|
|
4
|
-
verification_type: "
|
|
4
|
+
verification_type: "organization_dirigeant" | "code_sent_to_official_contact_email" | "domain" | "imported_from_coop_mediation_numerique" | "imported_from_inclusion_connect" | "in_liste_dirigeants_rna" | "in_liste_dirigeants_rne" | "official_contact_email" | "ordre_professionnel_domain" | "proof_received" | "verified_by_coop_mediation_numerique" | "bypassed" | "domain_not_verified_yet" | "no_validation_means_available" | "no_verification_means_for_entreprise_unipersonnelle" | "no_verification_means_for_small_association";
|
|
5
5
|
verified_at: Date | null;
|
|
6
6
|
has_been_greeted: boolean;
|
|
7
7
|
needs_official_contact_email_verification: boolean;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
export declare const WeakLinkTypes: readonly ["code_sent_to_official_contact_email", "domain", "domain_not_verified_yet", "imported_from_coop_mediation_numerique", "imported_from_inclusion_connect", "in_liste_dirigeants_rna", "in_liste_dirigeants_rne", "official_contact_email", "ordre_professionnel_domain", "proof_received", "verified_by_coop_mediation_numerique", "bypassed"];
|
|
3
2
|
export declare const StrongLinkTypes: readonly ["organization_dirigeant"];
|
|
4
|
-
export declare const
|
|
3
|
+
export declare const WeakLinkTypes: readonly ["code_sent_to_official_contact_email", "domain", "imported_from_coop_mediation_numerique", "imported_from_inclusion_connect", "in_liste_dirigeants_rna", "in_liste_dirigeants_rne", "official_contact_email", "ordre_professionnel_domain", "proof_received", "verified_by_coop_mediation_numerique", "bypassed"];
|
|
4
|
+
export declare const SuperWeakLinkTypes: readonly ["domain_not_verified_yet"];
|
|
5
5
|
export declare const UnverifiedLinkTypes: readonly ["no_validation_means_available", "no_verification_means_for_entreprise_unipersonnelle", "no_verification_means_for_small_association"];
|
|
6
6
|
export declare const LinkTypes: z.ZodEnum<{
|
|
7
|
+
organization_dirigeant: "organization_dirigeant";
|
|
7
8
|
code_sent_to_official_contact_email: "code_sent_to_official_contact_email";
|
|
8
9
|
domain: "domain";
|
|
9
|
-
domain_not_verified_yet: "domain_not_verified_yet";
|
|
10
10
|
imported_from_coop_mediation_numerique: "imported_from_coop_mediation_numerique";
|
|
11
11
|
imported_from_inclusion_connect: "imported_from_inclusion_connect";
|
|
12
12
|
in_liste_dirigeants_rna: "in_liste_dirigeants_rna";
|
|
@@ -16,7 +16,7 @@ export declare const LinkTypes: z.ZodEnum<{
|
|
|
16
16
|
proof_received: "proof_received";
|
|
17
17
|
verified_by_coop_mediation_numerique: "verified_by_coop_mediation_numerique";
|
|
18
18
|
bypassed: "bypassed";
|
|
19
|
-
|
|
19
|
+
domain_not_verified_yet: "domain_not_verified_yet";
|
|
20
20
|
no_validation_means_available: "no_validation_means_available";
|
|
21
21
|
no_verification_means_for_entreprise_unipersonnelle: "no_verification_means_for_entreprise_unipersonnelle";
|
|
22
22
|
no_verification_means_for_small_association: "no_verification_means_for_small_association";
|
|
@@ -24,9 +24,9 @@ export declare const LinkTypes: z.ZodEnum<{
|
|
|
24
24
|
export declare const BaseUserOrganizationLinkSchema: z.ZodObject<{
|
|
25
25
|
is_external: z.ZodBoolean;
|
|
26
26
|
verification_type: z.ZodEnum<{
|
|
27
|
+
organization_dirigeant: "organization_dirigeant";
|
|
27
28
|
code_sent_to_official_contact_email: "code_sent_to_official_contact_email";
|
|
28
29
|
domain: "domain";
|
|
29
|
-
domain_not_verified_yet: "domain_not_verified_yet";
|
|
30
30
|
imported_from_coop_mediation_numerique: "imported_from_coop_mediation_numerique";
|
|
31
31
|
imported_from_inclusion_connect: "imported_from_inclusion_connect";
|
|
32
32
|
in_liste_dirigeants_rna: "in_liste_dirigeants_rna";
|
|
@@ -36,7 +36,7 @@ export declare const BaseUserOrganizationLinkSchema: z.ZodObject<{
|
|
|
36
36
|
proof_received: "proof_received";
|
|
37
37
|
verified_by_coop_mediation_numerique: "verified_by_coop_mediation_numerique";
|
|
38
38
|
bypassed: "bypassed";
|
|
39
|
-
|
|
39
|
+
domain_not_verified_yet: "domain_not_verified_yet";
|
|
40
40
|
no_validation_means_available: "no_validation_means_available";
|
|
41
41
|
no_verification_means_for_entreprise_unipersonnelle: "no_verification_means_for_entreprise_unipersonnelle";
|
|
42
42
|
no_verification_means_for_small_association: "no_verification_means_for_small_association";
|
|
@@ -51,9 +51,9 @@ export type BaseUserOrganizationLink = z.output<typeof BaseUserOrganizationLinkS
|
|
|
51
51
|
export declare const UserOrganizationLinkSchema: z.ZodObject<{
|
|
52
52
|
is_external: z.ZodBoolean;
|
|
53
53
|
verification_type: z.ZodEnum<{
|
|
54
|
+
organization_dirigeant: "organization_dirigeant";
|
|
54
55
|
code_sent_to_official_contact_email: "code_sent_to_official_contact_email";
|
|
55
56
|
domain: "domain";
|
|
56
|
-
domain_not_verified_yet: "domain_not_verified_yet";
|
|
57
57
|
imported_from_coop_mediation_numerique: "imported_from_coop_mediation_numerique";
|
|
58
58
|
imported_from_inclusion_connect: "imported_from_inclusion_connect";
|
|
59
59
|
in_liste_dirigeants_rna: "in_liste_dirigeants_rna";
|
|
@@ -63,7 +63,7 @@ export declare const UserOrganizationLinkSchema: z.ZodObject<{
|
|
|
63
63
|
proof_received: "proof_received";
|
|
64
64
|
verified_by_coop_mediation_numerique: "verified_by_coop_mediation_numerique";
|
|
65
65
|
bypassed: "bypassed";
|
|
66
|
-
|
|
66
|
+
domain_not_verified_yet: "domain_not_verified_yet";
|
|
67
67
|
no_validation_means_available: "no_validation_means_available";
|
|
68
68
|
no_verification_means_for_entreprise_unipersonnelle: "no_verification_means_for_entreprise_unipersonnelle";
|
|
69
69
|
no_verification_means_for_small_association: "no_verification_means_for_small_association";
|
|
@@ -83,9 +83,9 @@ export declare const InsertUserOrganizationLinkSchema: z.ZodObject<{
|
|
|
83
83
|
user_id: z.ZodNumber;
|
|
84
84
|
organization_id: z.ZodNumber;
|
|
85
85
|
verification_type: z.ZodEnum<{
|
|
86
|
+
organization_dirigeant: "organization_dirigeant";
|
|
86
87
|
code_sent_to_official_contact_email: "code_sent_to_official_contact_email";
|
|
87
88
|
domain: "domain";
|
|
88
|
-
domain_not_verified_yet: "domain_not_verified_yet";
|
|
89
89
|
imported_from_coop_mediation_numerique: "imported_from_coop_mediation_numerique";
|
|
90
90
|
imported_from_inclusion_connect: "imported_from_inclusion_connect";
|
|
91
91
|
in_liste_dirigeants_rna: "in_liste_dirigeants_rna";
|
|
@@ -95,7 +95,7 @@ export declare const InsertUserOrganizationLinkSchema: z.ZodObject<{
|
|
|
95
95
|
proof_received: "proof_received";
|
|
96
96
|
verified_by_coop_mediation_numerique: "verified_by_coop_mediation_numerique";
|
|
97
97
|
bypassed: "bypassed";
|
|
98
|
-
|
|
98
|
+
domain_not_verified_yet: "domain_not_verified_yet";
|
|
99
99
|
no_validation_means_available: "no_validation_means_available";
|
|
100
100
|
no_verification_means_for_entreprise_unipersonnelle: "no_verification_means_for_entreprise_unipersonnelle";
|
|
101
101
|
no_verification_means_for_small_association: "no_verification_means_for_small_association";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-organization-link.d.ts","sourceRoot":"","sources":["../../src/types/user-organization-link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"user-organization-link.d.ts","sourceRoot":"","sources":["../../src/types/user-organization-link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,eAAe,qCAAsC,CAAC;AAEnE,eAAO,MAAM,aAAa,6TAahB,CAAC;AAMX,eAAO,MAAM,kBAAkB,sCAAuC,CAAC;AAQvE,eAAO,MAAM,mBAAmB,kJAItB,CAAC;AAEX,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;EAAyD,CAAC;AAEhF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;iBASzC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAC7C,OAAO,8BAA8B,CACtC,CAAC;AAIF,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOtC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAI/E,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;iBAW5C,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAC/C,OAAO,gCAAgC,CACxC,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
export const StrongLinkTypes = ["organization_dirigeant"];
|
|
2
3
|
export const WeakLinkTypes = [
|
|
3
4
|
"code_sent_to_official_contact_email",
|
|
4
5
|
"domain",
|
|
5
|
-
"domain_not_verified_yet",
|
|
6
6
|
"imported_from_coop_mediation_numerique",
|
|
7
7
|
"imported_from_inclusion_connect",
|
|
8
8
|
"in_liste_dirigeants_rna",
|
|
@@ -14,10 +14,15 @@ export const WeakLinkTypes = [
|
|
|
14
14
|
// Used in the sandbox environment to bypass the verification process
|
|
15
15
|
"bypassed",
|
|
16
16
|
];
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
// This link type should be considered as unverified.
|
|
18
|
+
// However, doing so would trigger a FranceConnect authentication requirement for the user.
|
|
19
|
+
// Users shouldn't face inconvenience while waiting for domain review completion.
|
|
20
|
+
// Instead, we should remove these unverified domains and then eliminate this special case from the codebase.
|
|
21
|
+
export const SuperWeakLinkTypes = ["domain_not_verified_yet"];
|
|
22
|
+
const VerifiedLinkTypes = [
|
|
20
23
|
...StrongLinkTypes,
|
|
24
|
+
...WeakLinkTypes,
|
|
25
|
+
...SuperWeakLinkTypes,
|
|
21
26
|
];
|
|
22
27
|
export const UnverifiedLinkTypes = [
|
|
23
28
|
"no_validation_means_available",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proconnect-gouv/proconnect.identite",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"homepage": "https://github.com/proconnect-gouv/proconnect-identite/tree/main/packages/identite#readme",
|
|
5
5
|
"bugs": "https://github.com/proconnect-gouv/proconnect-identite/issues",
|
|
6
6
|
"repository": {
|
|
@@ -96,8 +96,8 @@ export function certificationScore(
|
|
|
96
96
|
// For foreigners: check country code (with conversion if needed from RNE)
|
|
97
97
|
// Both should already be in COG format (99XXX)
|
|
98
98
|
if (
|
|
99
|
-
identitePivot.birthcountry
|
|
100
|
-
sourceDirigeant.birthcountry
|
|
99
|
+
identitePivot.birthcountry === null ||
|
|
100
|
+
sourceDirigeant.birthcountry === null ||
|
|
101
101
|
identitePivot.birthcountry === sourceDirigeant.birthcountry
|
|
102
102
|
) {
|
|
103
103
|
matches.add(MatchCriteria.enum.birth_country);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { IdentityVectorSchema } from "#src/types";
|
|
4
4
|
import {
|
|
5
|
+
AmberleyVailFranceConnectUserInfo,
|
|
5
6
|
LiElJonsonFranceConnectUserInfo,
|
|
6
7
|
RogalDornFranceConnectUserInfo,
|
|
7
8
|
} from "#testing/seed/franceconnect";
|
|
@@ -18,17 +19,57 @@ import {
|
|
|
18
19
|
RogalDornEstablishment,
|
|
19
20
|
} from "@proconnect-gouv/proconnect.insee/testing/seed";
|
|
20
21
|
import {
|
|
22
|
+
AmberleyVailPouvoir,
|
|
21
23
|
RogalDornPouvoir,
|
|
22
24
|
UlysseTosiPouvoir,
|
|
23
25
|
} from "@proconnect-gouv/proconnect.registre_national_entreprises/testing/seed";
|
|
24
26
|
import assert from "node:assert/strict";
|
|
25
27
|
import { describe, it } from "node:test";
|
|
28
|
+
import * as ApiEntreprise from "./adapters/api_entreprise.js";
|
|
29
|
+
import * as INSEE from "./adapters/insee.js";
|
|
30
|
+
import * as RNE from "./adapters/rne.js";
|
|
26
31
|
import { processCertificationDirigeantFactory } from "./process-certification-dirigeant.js";
|
|
27
32
|
|
|
28
33
|
//
|
|
29
34
|
|
|
30
35
|
describe("processCertificationDirigeantFactory", () => {
|
|
31
36
|
it("should recognize a user as executive of a auto-entrepreneur", async () => {
|
|
37
|
+
const processCertificationDirigeant = processCertificationDirigeantFactory({
|
|
38
|
+
ApiEntrepriseInfogreffeRepository: {
|
|
39
|
+
findMandatairesSociauxBySiren: () => Promise.reject(new Error("💣")),
|
|
40
|
+
},
|
|
41
|
+
RegistreNationalEntreprisesApiRepository: {
|
|
42
|
+
findPouvoirsBySiren: () => Promise.reject(new Error("💣")),
|
|
43
|
+
},
|
|
44
|
+
InseeApiRepository: {
|
|
45
|
+
findBySiren: () => Promise.resolve(LiElJonsonEstablishment),
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const certificationDirigeantResult = await processCertificationDirigeant(
|
|
50
|
+
rogal_dorn_org_info,
|
|
51
|
+
LiElJonsonFranceConnectUserInfo,
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
assert.deepEqual(certificationDirigeantResult, {
|
|
55
|
+
cause: "exact_match",
|
|
56
|
+
details: {
|
|
57
|
+
dirigeant: INSEE.toIdentityVector(LiElJonsonEstablishment),
|
|
58
|
+
matches: new Set([
|
|
59
|
+
"family_name",
|
|
60
|
+
"first_name",
|
|
61
|
+
"gender",
|
|
62
|
+
"birth_date",
|
|
63
|
+
"birth_place",
|
|
64
|
+
]),
|
|
65
|
+
identity: IdentityVectorSchema.parse(LiElJonsonFranceConnectUserInfo),
|
|
66
|
+
source: "api.insee.fr/api-sirene/private",
|
|
67
|
+
},
|
|
68
|
+
ok: true,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("should recognize a foreign user as executive of a auto-entrepreneur", async () => {
|
|
32
73
|
const processCertificationDirigeant = processCertificationDirigeantFactory({
|
|
33
74
|
ApiEntrepriseInfogreffeRepository: {
|
|
34
75
|
findMandatairesSociauxBySiren: () => Promise.reject(new Error("💣")),
|
|
@@ -49,10 +90,7 @@ describe("processCertificationDirigeantFactory", () => {
|
|
|
49
90
|
assert.deepEqual(certificationDirigeantResult, {
|
|
50
91
|
cause: "exact_match",
|
|
51
92
|
details: {
|
|
52
|
-
dirigeant:
|
|
53
|
-
...IdentityVectorSchema.parse(RogalDornFranceConnectUserInfo),
|
|
54
|
-
birthplace: null, // INSEE adapter returns null for foreigners
|
|
55
|
-
},
|
|
93
|
+
dirigeant: INSEE.toIdentityVector(RogalDornEstablishment),
|
|
56
94
|
matches: new Set([
|
|
57
95
|
"family_name",
|
|
58
96
|
"first_name",
|
|
@@ -88,11 +126,8 @@ describe("processCertificationDirigeantFactory", () => {
|
|
|
88
126
|
assert.deepEqual(certificationDirigeantResult, {
|
|
89
127
|
cause: "below_threshold",
|
|
90
128
|
details: {
|
|
91
|
-
dirigeant:
|
|
92
|
-
|
|
93
|
-
birthcountry: null, // INSEE adapter returns null for French people
|
|
94
|
-
},
|
|
95
|
-
matches: new Set(["gender"]),
|
|
129
|
+
dirigeant: INSEE.toIdentityVector(LiElJonsonEstablishment),
|
|
130
|
+
matches: new Set(["gender", "birth_country"]),
|
|
96
131
|
identity: IdentityVectorSchema.parse(RogalDornFranceConnectUserInfo),
|
|
97
132
|
source: "api.insee.fr/api-sirene/private",
|
|
98
133
|
},
|
|
@@ -122,10 +157,7 @@ describe("processCertificationDirigeantFactory", () => {
|
|
|
122
157
|
assert.deepEqual(certificationDirigeantResult, {
|
|
123
158
|
cause: "exact_match",
|
|
124
159
|
details: {
|
|
125
|
-
dirigeant:
|
|
126
|
-
...IdentityVectorSchema.parse(RogalDornFranceConnectUserInfo),
|
|
127
|
-
birthplace: null, // RNE adapter returns null for foreigners
|
|
128
|
-
},
|
|
160
|
+
dirigeant: RNE.toIdentityVector(RogalDornPouvoir),
|
|
129
161
|
matches: new Set([
|
|
130
162
|
"family_name",
|
|
131
163
|
"first_name",
|
|
@@ -140,6 +172,43 @@ describe("processCertificationDirigeantFactory", () => {
|
|
|
140
172
|
});
|
|
141
173
|
});
|
|
142
174
|
|
|
175
|
+
it("should match Amberley Vail among the executive of Papillon in RNE", async () => {
|
|
176
|
+
const processCertificationDirigeant = processCertificationDirigeantFactory({
|
|
177
|
+
ApiEntrepriseInfogreffeRepository: {
|
|
178
|
+
findMandatairesSociauxBySiren: () => Promise.reject(new Error("💣")),
|
|
179
|
+
},
|
|
180
|
+
RegistreNationalEntreprisesApiRepository: {
|
|
181
|
+
findPouvoirsBySiren: () =>
|
|
182
|
+
Promise.resolve([UlysseTosiPouvoir, AmberleyVailPouvoir]),
|
|
183
|
+
},
|
|
184
|
+
InseeApiRepository: {
|
|
185
|
+
findBySiren: () => Promise.reject(new Error("💣")),
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
const certificationDirigeantResult = await processCertificationDirigeant(
|
|
190
|
+
papillon_org_info,
|
|
191
|
+
AmberleyVailFranceConnectUserInfo,
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
assert.deepEqual(certificationDirigeantResult, {
|
|
195
|
+
cause: "exact_match",
|
|
196
|
+
details: {
|
|
197
|
+
dirigeant: RNE.toIdentityVector(AmberleyVailPouvoir),
|
|
198
|
+
matches: new Set([
|
|
199
|
+
"family_name",
|
|
200
|
+
"first_name",
|
|
201
|
+
"gender",
|
|
202
|
+
"birth_date",
|
|
203
|
+
"birth_country",
|
|
204
|
+
]),
|
|
205
|
+
identity: IdentityVectorSchema.parse(AmberleyVailFranceConnectUserInfo),
|
|
206
|
+
source: "registre-national-entreprises.inpi.fr/api",
|
|
207
|
+
},
|
|
208
|
+
ok: true,
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
143
212
|
it("should match Rogal Dorn among the executive of Papillon in Infogreffe", async () => {
|
|
144
213
|
const processCertificationDirigeant = processCertificationDirigeantFactory({
|
|
145
214
|
ApiEntrepriseInfogreffeRepository: {
|
|
@@ -162,11 +231,7 @@ describe("processCertificationDirigeantFactory", () => {
|
|
|
162
231
|
assert.deepEqual(certificationDirigeantResult, {
|
|
163
232
|
cause: "exact_match",
|
|
164
233
|
details: {
|
|
165
|
-
dirigeant:
|
|
166
|
-
...IdentityVectorSchema.parse(RogalDornFranceConnectUserInfo),
|
|
167
|
-
birthplace: null, // API Entreprise adapter doesn't provide birthplace
|
|
168
|
-
gender: null, // API Entreprise adapter doesn't provide gender
|
|
169
|
-
},
|
|
234
|
+
dirigeant: ApiEntreprise.toIdentityVector(RogalDornMandataire),
|
|
170
235
|
matches: new Set([
|
|
171
236
|
"family_name",
|
|
172
237
|
"first_name",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import type { GetUsersByOrganizationHandler } from "#src/repositories/organization";
|
|
4
4
|
import type { UpdateUserOrganizationLinkHandler } from "#src/repositories/user";
|
|
5
|
-
import { LinkTypes, UnverifiedLinkTypes } from "#src/types";
|
|
5
|
+
import { LinkTypes, SuperWeakLinkTypes, UnverifiedLinkTypes } from "#src/types";
|
|
6
6
|
import { getEmailDomain } from "@proconnect-gouv/proconnect.core/services/email";
|
|
7
7
|
import { match } from "ts-pattern";
|
|
8
8
|
|
|
@@ -30,7 +30,7 @@ export function assignUserVerificationTypeToDomainFactory({
|
|
|
30
30
|
if (
|
|
31
31
|
userDomain === domain &&
|
|
32
32
|
match(link_verification_type)
|
|
33
|
-
.with(...UnverifiedLinkTypes, () => true)
|
|
33
|
+
.with(...UnverifiedLinkTypes, ...SuperWeakLinkTypes, () => true)
|
|
34
34
|
.otherwise(() => false)
|
|
35
35
|
) {
|
|
36
36
|
return updateUserOrganizationLink(organization_id, id, {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
+
export const StrongLinkTypes = ["organization_dirigeant"] as const;
|
|
4
|
+
|
|
3
5
|
export const WeakLinkTypes = [
|
|
4
6
|
"code_sent_to_official_contact_email",
|
|
5
7
|
"domain",
|
|
6
|
-
"domain_not_verified_yet",
|
|
7
8
|
"imported_from_coop_mediation_numerique",
|
|
8
9
|
"imported_from_inclusion_connect",
|
|
9
10
|
"in_liste_dirigeants_rna",
|
|
@@ -16,11 +17,16 @@ export const WeakLinkTypes = [
|
|
|
16
17
|
"bypassed",
|
|
17
18
|
] as const;
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
// This link type should be considered as unverified.
|
|
21
|
+
// However, doing so would trigger a FranceConnect authentication requirement for the user.
|
|
22
|
+
// Users shouldn't face inconvenience while waiting for domain review completion.
|
|
23
|
+
// Instead, we should remove these unverified domains and then eliminate this special case from the codebase.
|
|
24
|
+
export const SuperWeakLinkTypes = ["domain_not_verified_yet"] as const;
|
|
20
25
|
|
|
21
|
-
|
|
22
|
-
...WeakLinkTypes,
|
|
26
|
+
const VerifiedLinkTypes = [
|
|
23
27
|
...StrongLinkTypes,
|
|
28
|
+
...WeakLinkTypes,
|
|
29
|
+
...SuperWeakLinkTypes,
|
|
24
30
|
] as const;
|
|
25
31
|
|
|
26
32
|
export const UnverifiedLinkTypes = [
|
|
@@ -41,3 +41,17 @@ export const RogalDornFranceConnectUserInfo: FranceConnectUserInfo = {
|
|
|
41
41
|
updated_at: new Date(),
|
|
42
42
|
user_id: NaN,
|
|
43
43
|
};
|
|
44
|
+
|
|
45
|
+
export const AmberleyVailFranceConnectUserInfo: FranceConnectUserInfo = {
|
|
46
|
+
birthcountry: "99102",
|
|
47
|
+
birthdate: new Date(Date.UTC(29000, 6, 7)),
|
|
48
|
+
birthplace: "",
|
|
49
|
+
created_at: new Date("2023-04-10"),
|
|
50
|
+
family_name: "Vail",
|
|
51
|
+
gender: "female",
|
|
52
|
+
given_name: "Amberley",
|
|
53
|
+
preferred_username: "Holy Inquisition",
|
|
54
|
+
sub: "ORDOS546",
|
|
55
|
+
updated_at: new Date(),
|
|
56
|
+
user_id: NaN,
|
|
57
|
+
};
|