Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.dev.example.env
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ API_INSEE_URL="https://api.insee.fr"
API_INSEE_URI="/api-sirene/3.11"

# https://cloud.maptiler.com/account/keys/
API_MAP_TILER="dtDQE2ONXrpleRHWIyNC"
NUXT_PUBLIC_API_MAP_TILER="dtDQE2ONXrpleRHWIyNC"

ANTIVIRUS_URL="https://antivirus.fabrique.social.gouv.fr/vao/api/v1/scan"

Expand Down
3 changes: 1 addition & 2 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# pnpm (workspace-wide)
# Supply-chain hardening: avoid installing packages that are too fresh
minimumReleaseAge=72d

minimum-release-age=103680
# Ensure monorepo workspace packages are linked instead of fetched from the registry
link-workspace-packages=true
prefer-workspace-packages=true
4 changes: 3 additions & 1 deletion .talismanrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
fileignoreconfig:
- filename: .env.dev.example.env
checksum: 217ba7248908d2556647f3e315d96faa67baa36cb19d90e998d4dc6121dcf648
checksum: 7aadaf6f567f2c55827f5097bc9524a0487702e6b6f551c446aca37c0b3780c5
- filename: .github/workflows/e2e.yaml
checksum: d28e325635cc8d77cbf5b260c67cb9721b58578ac86ddd39ec691e753e4d0412
- filename: .github/workflows/lint-format-tests.yaml
Expand Down Expand Up @@ -251,6 +251,8 @@ fileignoreconfig:
checksum: e22412a54064dea24f7e200e9887726a4ef110f13570feea628c70c4fe2886a9
- filename: packages/frontend-usagers/src/components/agrement/etapes-avancement.vue
checksum: 88b30646940faf9e0726799588b6445f5292d9afd912df7bbc91ae61627b93b6
- filename: packages/frontend-usagers/src/components/agrement/historique.vue
checksum: 054caab3085a920f1a5017decf60ebd686cc2c1695eba776c40f5bdb3521dffc
- filename: packages/frontend-usagers/src/components/agrement/projets/listeSejours.vue
checksum: 8fedbc8821c31208f6a874718cd0f8805cd7990365928ce883ce1dcbd843decd
- filename: packages/frontend-usagers/src/components/agrement/projets/sejoursPrevus.vue
Expand Down
4 changes: 2 additions & 2 deletions packages/backend/src/__tests__/usagers/agrements.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jest.mock("../../middlewares/common/checkJWT", () => {
beforeAll(async () => await createTestContainer());
afterAll(async () => await removeTestContainer());

describe("GET /agrements/organisme/:id", () => {
describe("GET /agrements/organisme/:organismeId", () => {
it("devrait retourner un agrément par ID de l'organisme avec succès", async () => {
authUser = await createUsagersUser();
const organismeId = await createOrganisme({ userId: authUser.id });
Expand Down Expand Up @@ -55,7 +55,7 @@ describe("GET /agrements/organisme/:id", () => {

// Vérification des résultats
// TODO ACH Problème sur le params string. Devrait retourner une 400
expect(response.status).toBe(403);
expect(response.status).toBe(400);
});
it("devrait retourner un agrement introuvable", async () => {
authUser = await createUsagersUser();
Expand Down
4 changes: 3 additions & 1 deletion packages/backend/src/controllers/siret/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ module.exports = async function get(req, res, next) {
}

if (
uniteLegale.adresseEtablissement?.coordonneeLambertAbscisseEtablissement
uniteLegale.adresseEtablissement?.coordonneeLambertAbscisseEtablissement &&
uniteLegale.adresseEtablissement?.coordonneeLambertAbscisseEtablissement !==
"[ND]"
) {
proj4.defs(
"EPSG:2154",
Expand Down
51 changes: 43 additions & 8 deletions packages/backend/src/middlewares/checkPermissionAgrement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import { getPool } from "../utils/pgpool";

const log = logger(module.filename);

interface UserOrganismeRow {
org_id: number;
}

async function checkPermissionAgrement(
req: UserRequest,
res: Response,
Expand All @@ -21,9 +25,32 @@ async function checkPermissionAgrement(
);
}
const { id: userId } = req.decoded;
// Récupère l'Id de l'organisme en fonction de la provenance (POST ou GET)
const organismeId = req.body?.organismeId ?? req.params?.id ?? null;
log.i("IN");

const agrementId = req.params?.agrementId ?? req.body?.agrementId ?? null;
let organismeId = null;

log.i("IN", { userId });

if (agrementId) {
const orgQuery = `SELECT organisme_id FROM front.agrements WHERE id = $1`;
const orgResult = await getPool().query(orgQuery, [agrementId]);
organismeId = orgResult.rows?.[0]?.organisme_id ?? null;
if (!organismeId) {
log.w("Aucun organismeId récupéré pour l'agrement");
return next(
new AppError("Aucun organismeId récupéré pour l'agrement", {
statusCode: 404,
}),
);
}
} else {
log.w("Aucun agrementId fourni");
return next(
new AppError("Aucun agrementId fourni", {
statusCode: 400,
}),
);
}

const query = `
SELECT uo.org_id
Expand All @@ -32,18 +59,26 @@ async function checkPermissionAgrement(
WHERE u.id = $1
`;
const { rows } = await getPool().query(query, [userId]);
if (
!rows ||
rows.length !== 1 ||
rows[0].org_id.toString() !== organismeId.toString()
) {

if (!rows || rows.length === 0) {
log.w("Aucun rattachement organisme trouvé pour l'utilisateur");
return next(
new AppError("Aucun rattachement organisme trouvé pour l'utilisateur", {
statusCode: 403,
}),
);
}

const userOrgIds = rows.map((r: UserOrganismeRow) => r.org_id?.toString());
if (!userOrgIds.includes(organismeId.toString())) {
log.w("Utilisateur non autorisé à modifier l'agrement");
return next(
new AppError("Vous n'êtes pas autorisé à modifier cet agrément", {
statusCode: 403,
}),
);
}

log.i("DONE");
next();
}
Expand Down
32 changes: 0 additions & 32 deletions packages/backend/src/middlewares/checkPermissionOrganisme.js

This file was deleted.

54 changes: 54 additions & 0 deletions packages/backend/src/middlewares/checkPermissionOrganisme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { NextFunction, Response } from "express";

import { UserRequest } from "../types/request";
import AppError from "../utils/error";
import logger from "../utils/logger";
import { getPool } from "../utils/pgpool";

const log = logger(module.filename);

async function checkPermissionOrganisme(
req: UserRequest,
res: Response,
next: NextFunction,
) {
if (!req.decoded || typeof req.decoded.id === "undefined") {
log.w("Utilisateur non authentifié ou id manquant");
return next(
new AppError("Authentification requise", {
statusCode: 401,
}),
);
}
const { id: userId } = req.decoded;
const organismeId =
req.params.organismeId || req.body.organismeId || req.query.organismeId;

log.i("IN", { userId });

if (!/^\d+$/.test(organismeId)) {
return next(
new AppError("organismeId doit être un entier", {
statusCode: 400,
}),
);
}

const query = `
SELECT uo.org_id as organismeId
FROM front.user_organisme uo
JOIN front.users u ON uo.use_id = u.id
WHERE u.id = $1 AND uo.org_id = $2
`;
const { rows } = await getPool().query(query, [userId, organismeId]);
if (!rows || rows.length === 0) {
return next(
new AppError("Utilisateur non autorisé à accéder à l'organisme", {
statusCode: 403,
}),
);
}
next();
}

export default checkPermissionOrganisme;
10 changes: 6 additions & 4 deletions packages/backend/src/routes/__tests__/organisme/finalize.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const checkJWT = require("../../../middlewares/checkJWT");
const checkPermissionOrganisme = require("../../../middlewares/checkPermissionOrganisme");
const checkPermissionOrganismeModule = require("../../../middlewares/checkPermissionOrganisme");
const request = require("supertest");
const app = require("../../../app");
const Organisme = require("../../../services/Organisme");
Expand All @@ -18,9 +18,11 @@ describe("POST /organisme/:id/finalize", () => {
req.decoded = { ...user };
next();
});
checkPermissionOrganisme.mockImplementation((req, res, next) => {
next();
});
checkPermissionOrganismeModule.default.mockImplementation(
(req, res, next) => {
next();
},
);
});

afterEach(() => {
Expand Down
10 changes: 6 additions & 4 deletions packages/backend/src/routes/__tests__/organisme/update.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const checkJWT = require("../../../middlewares/checkJWT");
const checkPermissionOrganisme = require("../../../middlewares/checkPermissionOrganisme");
const checkPermissionOrganismeModule = require("../../../middlewares/checkPermissionOrganisme");
const request = require("supertest");
const app = require("../../../app");
const Organisme = require("../../../services/Organisme");
Expand All @@ -18,9 +18,11 @@ describe("POST /organisme/:id", () => {
req.decoded = { ...user };
next();
});
checkPermissionOrganisme.mockImplementation((req, res, next) => {
next();
});
checkPermissionOrganismeModule.default.mockImplementation(
(req, res, next) => {
next();
},
);
});

afterEach(() => {
Expand Down
3 changes: 2 additions & 1 deletion packages/backend/src/routes/organisme.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ const router = express.Router();

const checkJWT = require("../middlewares/checkJWT");
const BOcheckJWT = require("../middlewares/bo-check-JWT");
const checkPermissionOrganisme = require("../middlewares/checkPermissionOrganisme");
const checkPermissionOrganisme =
require("../middlewares/checkPermissionOrganisme").default;
const checkComingFrom = require("../middlewares/checkComingFrom");
const organismeController = require("../controllers/organisme");

Expand Down
31 changes: 29 additions & 2 deletions packages/backend/src/usagers/agrements/agrements.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const AgrementController = {
next: NextFunction,
) {
log.i("IN");
const organismeId = req.validatedParams!.id;
const organismeId = req.validatedParams!.organismeId;

try {
const agrement: AgrementDto | null = await AgrementService.getAgrement({
Expand All @@ -42,6 +42,20 @@ export const AgrementController = {
next(error);
}
},
async getHistory(
req: RouteRequest<AgrementUsagersRoutes["GetHistory"]>,
res: RouteResponse<AgrementUsagersRoutes["GetHistory"]>,
next: NextFunction,
) {
try {
const history = await AgrementService.getHistory(
Number(req.validatedParams!.agrementId),
);
res.status(200).json({ history });
} catch (error) {
next(error);
}
},
async post(
req: RouteRequest<AgrementUsagersRoutes["PostAgrement"]>,
res: RouteResponse<AgrementUsagersRoutes["PostAgrement"]>,
Expand All @@ -51,9 +65,22 @@ export const AgrementController = {
const agrement = req.validatedBody!;
try {
const id = await AgrementService.save(agrement);
log.i("Agrement saved", { id });

// todo: supprimer/adapter cet exemple de tracking
// await AgrementService.trackEvent({
// agrementId: id,
// boUserId: null,
// metadata: null,
// source: "Organisateur",
// type: "Mise à jour page",
// typePrecision: "Renuvellement en cours de complétion",
// usagerUserId: 1,
// });

res.json({ id });
} catch (err) {
log.w("DONE with error");
log.w("DONE with error", err);
next(err);
}
},
Expand Down
Loading
Loading