From a77cbd1b08d195cdbd7589902b81d289435beef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Auricoste?= Date: Thu, 2 Nov 2023 17:07:34 +0100 Subject: [PATCH] fix: securisation de /formulaire/offre/f/:jobId/cancel --- shared/constants/recruteur.ts | 7 ------- shared/routes/formulaire.route.ts | 16 ++++++++++------ .../espace_pro/ConfirmationSuppressionOffre.tsx | 9 +++++---- ui/utils/api.ts | 7 ++++--- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/shared/constants/recruteur.ts b/shared/constants/recruteur.ts index a73f4db8f1..ebb6cebfad 100644 --- a/shared/constants/recruteur.ts +++ b/shared/constants/recruteur.ts @@ -1,10 +1,3 @@ -export enum JOB_STATUS { - ACTIVE = "Active", - POURVUE = "Pourvue", - ANNULEE = "Annulée", - EN_ATTENTE = "En attente", -} - export enum RECRUITER_STATUS { ACTIF = "Actif", ARCHIVE = "Archivé", diff --git a/shared/routes/formulaire.route.ts b/shared/routes/formulaire.route.ts index d9cc313d6d..ee2a744a80 100644 --- a/shared/routes/formulaire.route.ts +++ b/shared/routes/formulaire.route.ts @@ -1,6 +1,6 @@ import { z } from "../helpers/zodWithOpenApi" import { zObjectId } from "../models/common" -import { ZJob, ZJobWrite } from "../models/job.model" +import { JOB_STATUS, ZJob, ZJobWrite } from "../models/job.model" import { ZRecruiter, ZRecruiterWritable } from "../models/recruiter.model" import { IRoutesDef } from "./common.routes" @@ -177,20 +177,24 @@ export const zFormulaireRoute = { "/formulaire/offre/f/:jobId/cancel": { method: "put", path: "/formulaire/offre/f/:jobId/cancel", - // TODO_SECURITY_FIX gestion des permissions - // TODO_SECURITY_FIX session gérée par cookie server // TODO_SECURITY_FIX Scinder les routes pour cancel depuis admin OU cancel depuis CTA dans un email (avec jwt) params: z.object({ jobId: zObjectId }).strict(), body: z .object({ - job_status: z.string(), + job_status: z.enum([JOB_STATUS.POURVUE, JOB_STATUS.ANNULEE]), job_status_comment: z.string(), }) .strict(), response: { - "2xx": z.object({}).strict(), + "200": z.object({}).strict(), + }, + securityScheme: { + auth: "cookie-session", + access: "job:manage", + ressources: { + job: [{ _id: { type: "params", key: "jobId" } }], + }, }, - securityScheme: null, }, "/formulaire/offre/:jobId/provided": { method: "put", diff --git a/ui/components/espace_pro/ConfirmationSuppressionOffre.tsx b/ui/components/espace_pro/ConfirmationSuppressionOffre.tsx index 977d6b182b..9d469e854a 100644 --- a/ui/components/espace_pro/ConfirmationSuppressionOffre.tsx +++ b/ui/components/espace_pro/ConfirmationSuppressionOffre.tsx @@ -18,6 +18,7 @@ import { } from "@chakra-ui/react" import { useState } from "react" import { useQueryClient } from "react-query" +import { JOB_STATUS } from "shared" import { ArrowRightLine, Close } from "../../theme/components/icons" import { cancelOffreFromAdmin } from "../../utils/api" @@ -47,7 +48,7 @@ export default function ConfirmationSuppressionOffre(props) { } } - const updateOffer = (job_status) => { + const cancelOffer = (job_status: JOB_STATUS.POURVUE | JOB_STATUS.ANNULEE) => { cancelOffreFromAdmin(offre._id, { job_status, job_status_comment: job_status_comment ?? undefined }) .then(() => { toast({ @@ -91,7 +92,7 @@ export default function ConfirmationSuppressionOffre(props) { - @@ -107,7 +108,7 @@ export default function ConfirmationSuppressionOffre(props) { - @@ -120,7 +121,7 @@ export default function ConfirmationSuppressionOffre(props) { SetjobStatusComment(e.target.value)} isRequired minLength={3} /> - diff --git a/ui/utils/api.ts b/ui/utils/api.ts index 4fda9fd48a..9906e6b5d3 100644 --- a/ui/utils/api.ts +++ b/ui/utils/api.ts @@ -1,6 +1,6 @@ import { captureException } from "@sentry/nextjs" import Axios from "axios" -import { IJobWritable, INewDelegations } from "shared" +import { IJobWritable, INewDelegations, IRoutes } from "shared" import { publicConfig } from "../config.public" @@ -34,8 +34,9 @@ export const getOffre = (jobId) => API.get(`/formulaire/offre/f/${jobId}`) export const createOffre = (establishment_id: string, newOffre: IJobWritable) => apiPost("/formulaire/:establishment_id/offre", { params: { establishment_id }, body: newOffre }) export const patchOffre = (jobId, data, config) => API.patch(`/formulaire/offre/${jobId}`, data, config).catch(errorHandler) export const cancelOffre = (jobId) => API.put(`/formulaire/offre/${jobId}/cancel`) -export const cancelOffreFromAdmin = (jobId, data) => API.put(`/formulaire/offre/f/${jobId}/cancel`, data) -export const extendOffre = (jobId) => apiPut(`/formulaire/offre/:jobId/extend`, { params: { jobId } }) +export const cancelOffreFromAdmin = (jobId: string, data: IRoutes["put"]["/formulaire/offre/f/:jobId/cancel"]["body"]["_input"]) => + apiPut("/formulaire/offre/f/:jobId/cancel", { params: { jobId }, body: data }) +export const extendOffre = (jobId: string) => apiPut(`/formulaire/offre/:jobId/extend`, { params: { jobId } }) export const fillOffre = (jobId) => API.put(`/formulaire/offre/${jobId}/provided`) export const createEtablissementDelegation = ({ data, jobId }: { jobId: string; data: INewDelegations }) => apiPost(`/formulaire/offre/:jobId/delegation`, { params: { jobId }, body: data })