diff --git a/packages/app/src/app/(default)/login/EmailLogin.tsx b/packages/app/src/app/(default)/login/EmailLogin.tsx index a4e5c79981..a743788fe2 100644 --- a/packages/app/src/app/(default)/login/EmailLogin.tsx +++ b/packages/app/src/app/(default)/login/EmailLogin.tsx @@ -4,6 +4,7 @@ import { fr } from "@codegouvfr/react-dsfr"; import { Alert } from "@codegouvfr/react-dsfr/Alert"; import { Button } from "@codegouvfr/react-dsfr/Button"; import { Input } from "@codegouvfr/react-dsfr/Input"; +import { REGEX_EMAIL } from "@common/shared-domain/domain/valueObjects"; import { Container } from "@design-system"; import { zodResolver } from "@hookform/resolvers/zod"; import { signIn } from "next-auth/react"; @@ -13,7 +14,10 @@ import { z } from "zod"; import { AlertFeatureStatus, useFeatureStatus } from "../../../components/rdsfr/FeatureStatusProvider"; const formSchema = z.object({ - email: z.string().min(1, "L'adresse email est requise.").email({ message: "L'adresse email est invalide." }), + email: z + .string() + .min(1, "L'adresse email est requise.") + .regex(REGEX_EMAIL, { message: "L'adresse email est invalide." }), }); type FormType = z.infer; diff --git a/packages/app/src/common/core-domain/dtos/ReferentDTO.ts b/packages/app/src/common/core-domain/dtos/ReferentDTO.ts index d7984591b9..62828a614d 100644 --- a/packages/app/src/common/core-domain/dtos/ReferentDTO.ts +++ b/packages/app/src/common/core-domain/dtos/ReferentDTO.ts @@ -1,9 +1,10 @@ import { COUNTIES_IDS, REGIONS_IDS } from "@common/dict"; +import { REGEX_EMAIL } from "@common/shared-domain/domain/valueObjects"; import { z } from "zod"; const substituteSchema = z.object({ name: z.string().optional(), - email: z.string().email().optional(), + email: z.string().regex(REGEX_EMAIL, { message: "L'adresse email est invalide." }).optional(), }); const baseReferentSchema = z.object({ county: z.enum(COUNTIES_IDS).optional(), @@ -14,7 +15,7 @@ const baseReferentSchema = z.object({ }); const emailReferentSubSchema = { type: z.literal("email"), - value: z.string().email(), + value: z.string().regex(REGEX_EMAIL, { message: "L'adresse email est invalide." }), }; const emailReferentSchema = baseReferentSchema.extend(emailReferentSubSchema); const emailReferentPartialSchema = baseReferentSchema.partial().extend(emailReferentSubSchema); diff --git a/packages/app/src/common/shared-domain/domain/valueObjects/Email.ts b/packages/app/src/common/shared-domain/domain/valueObjects/Email.ts index d9d112a417..4898e96874 100644 --- a/packages/app/src/common/shared-domain/domain/valueObjects/Email.ts +++ b/packages/app/src/common/shared-domain/domain/valueObjects/Email.ts @@ -1,6 +1,6 @@ import { SimpleStringValueObject } from "./SimpleStringValueObject"; -const REGEX_EMAIL = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/i; +export const REGEX_EMAIL = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/i; export class Email extends SimpleStringValueObject { constructor(email: string) { diff --git a/packages/app/src/pages/ajout-declarant.tsx b/packages/app/src/pages/ajout-declarant.tsx index 280eac9099..8f7bd85d60 100644 --- a/packages/app/src/pages/ajout-declarant.tsx +++ b/packages/app/src/pages/ajout-declarant.tsx @@ -1,7 +1,9 @@ import { Siren } from "@common/core-domain/domain/valueObjects/Siren"; import { type CreateOwnershipRequestDTO } from "@common/core-domain/dtos/CreateOwnershipRequestDTO"; import { type ValidationError } from "@common/shared-domain"; +import { Email, REGEX_EMAIL } from "@common/shared-domain/domain/valueObjects"; import { getDuplicates } from "@common/utils/array"; +import { zodValueObjectSuperRefine } from "@common/utils/zod"; import { AlertFeatureStatus, FeatureStatusProvider, useFeatureStatus } from "@components/FeatureStatusProvider"; import { BasicLayoutPublic } from "@components/layouts/BasicLayoutPublic"; import { @@ -34,7 +36,7 @@ const zodUniqueEmailArray = z.string().transform((val, ctx) => { const messages: string[] = []; for (const v of splitted) { try { - z.string().email().parse(v); + z.string().regex(REGEX_EMAIL).parse(v); } catch { messages.push(`L'adresse email "${v}" est invalide.`); } @@ -92,7 +94,7 @@ const zodUniqueSirenArray = z.string().transform((val, ctx) => { }); const formSchema = z.object({ - askerEmail: z.string().email({ message: "L'adresse email est invalide." }), + askerEmail: z.string().superRefine(zodValueObjectSuperRefine(Email, "L'adresse email est invalide.")), emails: zodUniqueEmailArray, sirens: zodUniqueSirenArray, }); diff --git a/packages/app/src/pages/representation-equilibree/declarant.tsx b/packages/app/src/pages/representation-equilibree/declarant.tsx index 132c4cd97c..0626a85d41 100644 --- a/packages/app/src/pages/representation-equilibree/declarant.tsx +++ b/packages/app/src/pages/representation-equilibree/declarant.tsx @@ -1,3 +1,4 @@ +import { REGEX_EMAIL } from "@common/shared-domain/domain/valueObjects"; import { AlertEdition } from "@components/AlertEdition"; import { RepresentationEquilibreeLayout } from "@components/layouts/RepresentationEquilibreeLayout"; import { @@ -28,7 +29,7 @@ const formSchema = z.object({ .string() .min(1, { message: "Le téléphone est requis" }) .regex(/\d{10}/gi, "Le numéro de téléphone doit être composé de 10 chiffres"), - email: z.string().email(), + email: z.string().regex(REGEX_EMAIL, { message: "L'adresse email est invalide." }), accord_rgpd: z.boolean().refine(accord_rgpd => accord_rgpd, { message: "L'accord est requis" }), }); diff --git a/packages/app/src/pages/representation-equilibree/email.tsx b/packages/app/src/pages/representation-equilibree/email.tsx index 5f06c7165b..b51adc4095 100644 --- a/packages/app/src/pages/representation-equilibree/email.tsx +++ b/packages/app/src/pages/representation-equilibree/email.tsx @@ -1,3 +1,4 @@ +import { REGEX_EMAIL } from "@common/shared-domain/domain/valueObjects"; import { normalizeRouterQuery } from "@common/utils/url"; import { ClientOnly } from "@components/ClientOnly"; import { AlertFeatureStatus, FeatureStatusProvider, useFeatureStatus } from "@components/FeatureStatusProvider"; @@ -24,7 +25,10 @@ import { type NextPageWithLayout } from "../_app"; const title = "Validation de l'email"; const formSchema = z.object({ - email: z.string().min(1, "L'adresse email est requise.").email({ message: "L'adresse email est invalide." }), + email: z + .string() + .min(1, "L'adresse email est requise.") + .regex(REGEX_EMAIL, { message: "L'adresse email est invalide." }), }); // Infer the TS type according to the zod schema.