Skip to content

Commit

Permalink
fix: lbac 1490: refactor verification de compte unique
Browse files Browse the repository at this point in the history
  • Loading branch information
remy-auricoste committed Apr 30, 2024
1 parent c8b6f26 commit 2be43d1
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ import {
validateCreationEntrepriseFromCfa,
} from "@/services/etablissement.service"
import { getMainRoleManagement, getPublicUserRecruteurPropsOrError } from "@/services/roleManagement.service"
import { getUser2ByEmail, validateUser2Email } from "@/services/user2.service"
import { emailHasActiveRole, getUser2ByEmail, validateUser2Email } from "@/services/user2.service"
import {
autoValidateUser,
createOrganizationUser,
getUserRecruteurByEmail,
isUserEmailChecked,
sendWelcomeEmailToUserRecruteur,
setUserHasToBeManuallyValidated,
Expand Down Expand Up @@ -177,8 +176,7 @@ export default (server: Server) => {
const origin = req.body.origin ?? "formulaire public de création"
const formatedEmail = email.toLocaleLowerCase()
// check if user already exist
const userRecruteurOpt = await getUserRecruteurByEmail(formatedEmail)
if (userRecruteurOpt) {
if (await emailHasActiveRole(formatedEmail)) {
throw Boom.forbidden("L'adresse mail est déjà associée à un compte La bonne alternance.")
}

Expand Down
10 changes: 5 additions & 5 deletions server/src/jobs/lba_recruteur/formulaire/createUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { VALIDATION_UTILISATEUR } from "shared/constants/recruteur"
import { IUserRecruteur } from "shared/models"
import { AccessStatus } from "shared/models/roleManagement.model"

import { emailHasActiveRole } from "@/services/user2.service"

import { logger } from "../../../common/logger"
import { createUser, getUserRecruteurByEmail } from "../../../services/userRecruteur.service"
import { createUser } from "../../../services/userRecruteur.service"

export const createUserFromCLI = async (
{
Expand All @@ -19,10 +21,8 @@ export const createUserFromCLI = async (
{ options }: { options: { Type: IUserRecruteur["type"]; Email_valide: IUserRecruteur["is_email_checked"] } }
) => {
const { Type, Email_valide } = options
const exist = await getUserRecruteurByEmail(email)

if (exist) {
logger.error(`Users ${email} already exist - ${exist._id}`)
if (await emailHasActiveRole(email)) {
logger.error(`User ${email} already have an active role`)
return
}

Expand Down
32 changes: 15 additions & 17 deletions server/src/services/etablissement.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ import { createFormulaire, getFormulaire } from "./formulaire.service"
import mailer, { sanitizeForEmail } from "./mailer.service"
import { getOpcoBySirenFromDB, saveOpco } from "./opco.service"
import { modifyPermissionToUser } from "./roleManagement.service"
import { emailHasActiveRole } from "./user2.service"
import {
UserAndOrganization,
autoValidateUser as authorizeUserOnEntreprise,
createOrganizationUser,
getUserRecruteurByEmail,
isUserEmailChecked,
setEntrepriseInError,
setEntrepriseValid,
Expand Down Expand Up @@ -700,26 +700,25 @@ export const getEntrepriseDataFromSiret = async ({ siret, type }: { siret: strin
const isCfaCreationValid = async (siret: string): Promise<boolean> => {
const cfa = await Cfa.findOne({ siret }).lean()
if (!cfa) return true
const role = await RoleManagement.findOne({ authorized_type: AccessEntityType.CFA, authorized_id: cfa._id.toString() }).lean()
if (!role) return true
if (getLastStatusEvent(role.status)?.status !== AccessStatus.DENIED) {
return false
}
return true
const roles = await RoleManagement.find({ authorized_type: AccessEntityType.CFA, authorized_id: cfa._id.toString() }).lean()
const managingAccess = [AccessStatus.GRANTED, AccessStatus.AWAITING_VALIDATION]
const managingRoles = roles.filter((role) => {
const roleStatus = getLastStatusEvent(role.status)?.status
return roleStatus ? managingAccess.includes(roleStatus) : false
})
return managingRoles.length ? false : true
}

export const getOrganismeDeFormationDataFromSiret = async (siret: string, shouldValidate = true) => {
if (shouldValidate) {
const isValid = await isCfaCreationValid(siret)
if (!isValid) {
throw Boom.forbidden("Ce numéro siret est déjà associé à un compte utilisateur.", { reason: BusinessErrorCodes.ALREADY_EXISTS })
}
export const getOrganismeDeFormationDataFromSiret = async (siret: string) => {
const isValid = await isCfaCreationValid(siret)
if (!isValid) {
throw Boom.forbidden("Ce numéro siret est déjà associé à un compte utilisateur.", { reason: BusinessErrorCodes.ALREADY_EXISTS })
}
const referentiel = await getEtablissementFromReferentiel(siret)
if (!referentiel) {
throw Boom.badRequest("Le numéro siret n'est pas référencé comme centre de formation.", { reason: BusinessErrorCodes.UNKNOWN })
}
if (shouldValidate && referentiel.etat_administratif === "fermé") {
if (referentiel.etat_administratif === "fermé") {
throw Boom.badRequest("Le numéro siret indique un établissement fermé.", { reason: BusinessErrorCodes.CLOSED })
}
if (!referentiel.adresse) {
Expand All @@ -728,7 +727,7 @@ export const getOrganismeDeFormationDataFromSiret = async (siret: string, should
})
}
const formattedReferentiel = formatReferentielData(referentiel)
if (shouldValidate && !formattedReferentiel.is_qualiopi) {
if (!formattedReferentiel.is_qualiopi) {
throw Boom.badRequest("L’organisme rattaché à ce SIRET n’est pas certifié Qualiopi", { reason: BusinessErrorCodes.NOT_QUALIOPI, ...formattedReferentiel })
}
return formattedReferentiel
Expand Down Expand Up @@ -767,8 +766,7 @@ export const entrepriseOnboardingWorkflow = {
const cfaErrorOpt = await validateCreationEntrepriseFromCfa({ siret, cfa_delegated_siret })
if (cfaErrorOpt) return cfaErrorOpt
const formatedEmail = email.toLocaleLowerCase()
const userRecruteurOpt = await getUserRecruteurByEmail(formatedEmail)
if (userRecruteurOpt) {
if (await emailHasActiveRole(formatedEmail)) {
return errorFactory("L'adresse mail est déjà associée à un compte La bonne alternance.", BusinessErrorCodes.ALREADY_EXISTS)
}
let entrepriseData: Partial<EntrepriseData>
Expand Down
16 changes: 15 additions & 1 deletion server/src/services/user2.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import Boom from "boom"
import { VALIDATION_UTILISATEUR } from "shared/constants/recruteur"
import { AccessStatus } from "shared/models/roleManagement.model"
import { IUser2, IUserStatusEvent, UserEventType } from "shared/models/user2.model"
import { getLastStatusEvent } from "shared/utils"

import { User2 } from "@/common/model"
import { RoleManagement, User2 } from "@/common/model"
import { ObjectId } from "@/common/mongodb"

import { isUserEmailChecked } from "./userRecruteur.service"
Expand Down Expand Up @@ -74,3 +76,15 @@ export const validateUser2Email = async (id: string): Promise<IUser2> => {
}

export const getUser2ByEmail = async (email: string): Promise<IUser2 | null> => User2.findOne({ email: email.toLocaleLowerCase() }).lean()

export const emailHasActiveRole = async (email: string) => {
const userOpt = await getUser2ByEmail(email)
if (!userOpt) return
const roles = await RoleManagement.find({ user_id: userOpt._id }).lean()
const activeStatus = [AccessStatus.GRANTED, AccessStatus.AWAITING_VALIDATION]
const activeRoles = roles.filter((role) => {
const roleStatus = getLastStatusEvent(role.status)?.status
return roleStatus ? activeStatus.includes(roleStatus) : false
})
return Boolean(activeRoles.length)
}
1 change: 0 additions & 1 deletion server/src/services/userRecruteur.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ const roleStatusToUserRecruteurStatus = (roleStatus: AccessStatus): ETAT_UTILISA
}

export const getUserRecruteurById = (id: string | ObjectIdType) => getUserRecruteurByUser2Query({ _id: typeof id === "string" ? new ObjectId(id) : id })
export const getUserRecruteurByEmail = (email: string) => getUserRecruteurByUser2Query({ email })

export const userAndRoleAndOrganizationToUserRecruteur = (
user: IUser2,
Expand Down

0 comments on commit 2be43d1

Please sign in to comment.