Skip to content

Commit

Permalink
feat(lbac-2294): pas de creation de compte si l email existe (#1685)
Browse files Browse the repository at this point in the history
* feat(lbac-2294): pas de creation de compte si l email existe

* fix: revert husky
  • Loading branch information
remy-auricoste authored Dec 9, 2024
1 parent cdeccef commit 2b63393
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`POST /etablissement/creation > Vérifie que le recruteur est créé avec une offre 1`] = `
exports[`POST /etablissement/creation > Création d'entreprise > Vérifie que le recruteur est créé avec une offre 1`] = `
{
"address": "20 AVENUE DE SEGUR 75007 PARIS",
"address_detail": {
Expand Down Expand Up @@ -55,7 +55,17 @@ exports[`POST /etablissement/creation > Vérifie que le recruteur est créé ave
}
`;

exports[`POST /etablissement/creation > Vérifie que le recruteur est créé avec une offre 2`] = `
exports[`POST /etablissement/creation > Création d'entreprise > Vérifie que le recruteur est créé avec une offre 2`] = `
{
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"origin": "lba",
"phone": "0612345678",
}
`;

exports[`POST /etablissement/creation > Création de CFA > Vérifie que le CFA est créé 1`] = `
{
"email": "[email protected]",
"first_name": "John",
Expand Down
182 changes: 130 additions & 52 deletions server/src/http/controllers/etablissementRecruteur.controller.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { useMongo } from "@tests/utils/mongo.test.utils"
import { useServer } from "@tests/utils/server.test.utils"
import { saveUserWithAccount } from "@tests/utils/user.test.utils"
import omit from "lodash/omit"
import nock from "nock"
import { ENTREPRISE, OPCOS_LABEL } from "shared/constants"
import { CFA, ENTREPRISE, OPCOS_LABEL } from "shared/constants"
import { z } from "shared/helpers/zodWithOpenApi"
import { UserEventType } from "shared/models"
import { zRoutes } from "shared/routes"
import { beforeEach, describe, expect, it } from "vitest"

import { apiEntrepriseEtablissementFixture } from "@/common/apis/apiEntreprise/apiEntreprise.client.fixture"
import { getDbCollection } from "@/common/utils/mongodbUtils"

describe("POST /etablissement/creation", () => {
useMongo()
Expand All @@ -19,72 +21,148 @@ describe("POST /etablissement/creation", () => {
.persist()
.get(new RegExp("/sirene/etablissements/diffusibles/", "g"))
.reply(200, apiEntrepriseEtablissementFixture.dinum)
return () => {
return async () => {
mockEntreprise.persist(false)
await getDbCollection("recruiters").deleteMany()
await getDbCollection("rolemanagements").deleteMany()
await getDbCollection("entreprises").deleteMany()
await getDbCollection("cfas").deleteMany()
await getDbCollection("userswithaccounts").deleteMany()
}
})

const bodySchema = zRoutes.post["/etablissement/creation"].body
type CreationBody = z.output<typeof bodySchema>
const responseSchema = zRoutes.post["/etablissement/creation"].response["200"]
type CreationResponse = z.output<typeof responseSchema>

it("Vérifie que le recruteur est créé avec une offre", async () => {
const response = await httpClient().inject({
const defaultCreationEntreprisePayload = {
email: "[email protected]",
first_name: "John",
last_name: "Doe",
phone: "0612345678",
establishment_siret: "42476141900045",
origin: "lba",
opco: OPCOS_LABEL.AKTO,
idcc: "3248",
type: ENTREPRISE,
} as const

const defaultCreationCFAPayload = {
opco: null,
email: "[email protected]",
first_name: "John",
last_name: "Doe",
phone: "0612345678",
origin: "lba",
type: CFA,
establishment_siret: "52151363000017",
} as const

const callCreation = (body: CreationBody) =>
httpClient().inject({
method: "POST",
path: "/api/etablissement/creation",
body: {
email: "[email protected]",
first_name: "John",
last_name: "Doe",
phone: "0612345678",
establishment_siret: "42476141900045",
origin: "lba",
opco: OPCOS_LABEL.AKTO,
idcc: "3248",
type: ENTREPRISE,
},
body,
})
expect.soft(response.statusCode).toBe(200)
const { formulaire, user } = response.json() as CreationResponse
expect.soft(omit(formulaire, ["_id", "createdAt", "establishment_id", "managed_by", "updatedAt"])).toMatchSnapshot()
expect.soft(omit(user, ["_id", "createdAt", "updatedAt", "last_action_date", "status"])).toMatchSnapshot()
expect.soft(user.status[0].status).toBe(UserEventType.ACTIF)
})

it("Vérifie qu'une fois créé, l'opco n'est plus modifié par une autre création de compte", async () => {
const response = await httpClient().inject({
method: "POST",
path: "/api/etablissement/creation",
body: {
email: "[email protected]",
first_name: "John",
last_name: "Doe",
phone: "0612345678",
establishment_siret: "42476141900045",
origin: "lba",
opco: OPCOS_LABEL.AKTO,
idcc: "3248",
type: ENTREPRISE,
},
describe("Création d'entreprise", () => {
it("Vérifie que le recruteur est créé avec une offre", async () => {
const response = await callCreation(defaultCreationEntreprisePayload)
expect.soft(response.statusCode).toBe(200)
const { formulaire, user } = response.json() as CreationResponse
expect.soft(omit(formulaire, ["_id", "createdAt", "establishment_id", "managed_by", "updatedAt"])).toMatchSnapshot()
expect.soft(omit(user, ["_id", "createdAt", "updatedAt", "last_action_date", "status"])).toMatchSnapshot()
expect.soft(user.status[0].status).toBe(UserEventType.ACTIF)
})
const { formulaire } = response.json() as CreationResponse
expect.soft(formulaire?.opco).toBe(OPCOS_LABEL.AKTO)

const response2 = await httpClient().inject({
method: "POST",
path: "/api/etablissement/creation",
body: {
it("Vérifie qu'une fois créé, l'opco n'est plus modifié par une autre création de compte", async () => {
const response = await callCreation(defaultCreationEntreprisePayload)
const { formulaire } = response.json() as CreationResponse
expect.soft(formulaire?.opco).toBe(OPCOS_LABEL.AKTO)

const response2 = await callCreation({
...defaultCreationEntreprisePayload,
email: "[email protected]",
first_name: "John",
last_name: "Doe",
phone: "0612345678",
establishment_siret: "42476141900045",
origin: "lba",
opco: OPCOS_LABEL.CONSTRUCTYS,
idcc: "3248",
type: ENTREPRISE,
},
})
const { formulaire: formulaire2 } = response2.json() as CreationResponse
expect.soft(formulaire2?.opco).toBe(OPCOS_LABEL.AKTO)
})

it("Vérifie qu'un email ne peut pas créer plusieurs comptes", async () => {
const response = await callCreation(defaultCreationEntreprisePayload)
const { formulaire } = response.json() as CreationResponse
expect.soft(formulaire?.opco).toBe(OPCOS_LABEL.AKTO)

const response2 = await callCreation({
...defaultCreationEntreprisePayload,
establishment_siret: "48755980900016",
})
expect.soft(response2.statusCode).toBe(403)
expect.soft(response2.json().message).toBe("L'adresse mail est déjà associée à un compte La bonne alternance.")
})
it("Vérifie qu'un email ne peut pas créer un compte si l utilisateur existe déjà", async () => {
// given
const { email } = defaultCreationEntreprisePayload
await saveUserWithAccount({ email })
// when
const response = await callCreation({ ...defaultCreationEntreprisePayload, email })
// then
expect.soft(response.statusCode).toBe(403)
expect.soft(response.json().message).toBe("L'adresse mail est déjà associée à un compte La bonne alternance.")
})
})
describe("Création de CFA", () => {
it("Vérifie que le CFA est créé", async () => {
const response = await callCreation(defaultCreationCFAPayload)
expect.soft(response.statusCode).toBe(200)
const { formulaire, user } = response.json() as CreationResponse
expect.soft(formulaire).not.toBeDefined()
expect.soft(omit(user, ["_id", "createdAt", "updatedAt", "last_action_date", "status"])).toMatchSnapshot()
expect.soft(user.status[0].status).toBe(UserEventType.ACTIF)
})
it("Vérifie qu un email ne peut pas créer 2 comptes CFA", async () => {
const response = await callCreation(defaultCreationCFAPayload)
expect.soft(response.statusCode).toBe(200)
const response2 = await callCreation({ ...defaultCreationCFAPayload, establishment_siret: "13002172800261" })
expect.soft(response2.statusCode).toBe(403)
expect.soft(response2.json().message).toBe("L'adresse mail est déjà associée à un compte La bonne alternance.")
})
it("Vérifie que 2 emails ne peuvent pas avoir un compte sur le même CFA", async () => {
const response = await callCreation(defaultCreationCFAPayload)
expect.soft(response.statusCode).toBe(200)
const response2 = await callCreation({ ...defaultCreationCFAPayload, email: "[email protected]" })
expect.soft(response2.statusCode).toBe(403)
expect.soft(response2.json().message).toBe("Ce numéro siret est déjà associé à un compte utilisateur.")
})
it("Vérifie qu'un email ne peut pas créer un compte si l utilisateur existe déjà", async () => {
// given
const { email } = defaultCreationCFAPayload
await saveUserWithAccount({ email })
// when
const response = await callCreation({ ...defaultCreationCFAPayload, email })
// then
expect.soft(response.statusCode).toBe(403)
expect.soft(response.json().message).toBe("L'adresse mail est déjà associée à un compte La bonne alternance.")
})
})
describe("ENTREPRISE / CFA", () => {
it("Vérifie que un email ne peut pas créer un compte entreprise puis un compte CFA", async () => {
const email = defaultCreationEntreprisePayload.email
const response = await callCreation({ ...defaultCreationEntreprisePayload, email })
expect.soft(response.statusCode).toBe(200)
const response2 = await callCreation({ ...defaultCreationCFAPayload, email })
expect.soft(response2.statusCode).toBe(403)
expect.soft(response2.json().message).toBe("L'adresse mail est déjà associée à un compte La bonne alternance.")
})
it("Vérifie que un email ne peut pas créer un compte CFA puis un compte entreprise", async () => {
const email = defaultCreationEntreprisePayload.email
const response = await callCreation({ ...defaultCreationCFAPayload, email })
expect.soft(response.statusCode).toBe(200)
const response2 = await callCreation({ ...defaultCreationEntreprisePayload, email })
expect.soft(response2.statusCode).toBe(403)
expect.soft(response2.json().message).toBe("L'adresse mail est déjà associée à un compte La bonne alternance.")
})
const { formulaire: formulaire2 } = response2.json() as CreationResponse
expect.soft(formulaire2?.opco).toBe(OPCOS_LABEL.AKTO)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {
setUserHasToBeManuallyValidated,
updateLastConnectionDate,
} from "@/services/userRecruteur.service"
import { emailHasActiveRole, getUserWithAccountByEmail, isUserDisabled, isUserEmailChecked, validateUserWithAccountEmail } from "@/services/userWithAccount.service"
import { getUserWithAccountByEmail, isUserDisabled, isUserEmailChecked, validateUserWithAccountEmail } from "@/services/userWithAccount.service"

import { getAllDomainsFromEmailList, getEmailDomain, isEmailFromPrivateCompany, isUserMailExistInReferentiel } from "../../common/utils/mailUtils"
import { notifyToSlack } from "../../common/utils/slackUtils"
Expand Down Expand Up @@ -210,7 +210,7 @@ export default (server: Server) => {
const origin = req.body.origin ?? "formulaire public de création"
const formatedEmail = email.toLocaleLowerCase()
// check if user already exist
if (await emailHasActiveRole(formatedEmail)) {
if (await getUserWithAccountByEmail(formatedEmail)) {
throw forbidden("L'adresse mail est déjà associée à un compte La bonne alternance.")
}

Expand Down
4 changes: 2 additions & 2 deletions server/src/services/etablissement.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { getStaticFilePath } from "@/common/utils/getStaticFilePath"
import { getHttpClient } from "@/common/utils/httpUtils"
import { getDbCollection } from "@/common/utils/mongodbUtils"
import { userWithAccountToUserForToken } from "@/security/accessTokenService"
import { emailHasActiveRole, isUserEmailChecked } from "@/services/userWithAccount.service"
import { getUserWithAccountByEmail, isUserEmailChecked } from "@/services/userWithAccount.service"

import { isEmailFromPrivateCompany, isEmailSameDomain } from "../common/utils/mailUtils"
import { sentryCaptureException } from "../common/utils/sentryUtils"
Expand Down Expand Up @@ -607,7 +607,7 @@ export const entrepriseOnboardingWorkflow = {
}
const formatedEmail = email.toLocaleLowerCase()
// Faut-il rajouter un contrôle sur l'existance du couple email/siret dans la collection recruiters ?
if (await emailHasActiveRole(formatedEmail)) {
if (await getUserWithAccountByEmail(formatedEmail)) {
return errorFactory("L'adresse mail est déjà associée à un compte La bonne alternance.", BusinessErrorCodes.ALREADY_EXISTS)
}
let siretResponse: Awaited<ReturnType<typeof getEntrepriseDataFromSiret>>
Expand Down

0 comments on commit 2b63393

Please sign in to comment.