betagouv/service-national-universel

View on GitHub
api/src/controllers/program.js

Summary

Maintainability
C
1 day
Test Coverage
const express = require("express");
const router = express.Router();
const passport = require("passport");
const { capture } = require("../sentry");
const { logger } = require("../logger");

const { ProgramModel } = require("../models");
const { ERRORS, isYoung } = require("../utils");
const { validateId, validateString, validateArray, validateProgram } = require("../utils/validator");
const { ROLES, canCreateOrUpdateProgram } = require("snu-lib");

router.post("/", passport.authenticate("referent", { session: false, failWithError: true }), async (req, res) => {
  try {
    const { error, value: checkedProgram } = validateProgram(req.body);
    if (error) {
      capture(error);
      return res.status(400).send({ ok: false, code: ERRORS.INVALID_BODY });
    }
    if (!canCreateOrUpdateProgram(req.user, checkedProgram)) return res.status(403).send({ ok: false, code: ERRORS.OPERATION_UNAUTHORIZED });
    const data = await ProgramModel.create(checkedProgram);
    return res.status(200).send({ ok: true, data });
  } catch (error) {
    capture(error);
    res.status(500).send({ ok: false, code: ERRORS.SERVER_ERROR });
  }
});

router.put("/:id", passport.authenticate("referent", { session: false, failWithError: true }), async (req, res) => {
  try {
    const { error: errorProgram, value: checkedProgram } = validateProgram(req.body);
    const { error: errorId, value: checkedId } = validateId(req.params.id);
    if (errorProgram || errorId) return res.status(400).send({ ok: false, code: ERRORS.INVALID_BODY });
    if (!canCreateOrUpdateProgram(req.user, checkedProgram)) return res.status(403).send({ ok: false, code: ERRORS.OPERATION_UNAUTHORIZED });
    let obj = checkedProgram;
    const data = await ProgramModel.findById(checkedId);
    if (!data) return res.status(404).send({ ok: false, code: ERRORS.NOT_FOUND });
    data.set(obj);
    await data.save();
    return res.status(200).send({ ok: true, data });
  } catch (error) {
    capture(error);
    res.status(500).send({ ok: false, code: ERRORS.SERVER_ERROR });
  }
});

router.get("/:id", passport.authenticate(["referent", "young"], { session: false, failWithError: true }), async (req, res) => {
  try {
    const { error, value: checkedId } = validateId(req.params.id);
    if (error) {
      capture(error);
      return res.status(400).send({ ok: false, code: ERRORS.INVALID_PARAMS });
    }
    const data = await ProgramModel.findById(checkedId);
    if (!data) return res.status(404).send({ ok: false, code: ERRORS.NOT_FOUND });
    return res.status(200).send({ ok: true, data });
  } catch (error) {
    capture(error);
    res.status(500).send({ ok: false, code: ERRORS.SERVER_ERROR });
  }
});

router.get("/", passport.authenticate(["referent", "young"], { session: false, failWithError: true }), async (req, res) => {
  try {
    let data = [];
    if (req.user.role === ROLES.ADMIN) data = await ProgramModel.find({});
    else if (req.user.role === ROLES.HEAD_CENTER) data = await ProgramModel.find({ visibility: "HEAD_CENTER" });
    else {
      let errorDepartement, checkedDepartement;
      if (isYoung(req.user)) {
        ({ error: errorDepartement, value: checkedDepartement } = validateString(req.user.department));
      } else {
        ({ error: errorDepartement, value: checkedDepartement } = validateArray(req.user.department));
      }
      const { error: errorRegion, value: checkedRegion } = validateString(req.user.region);
      if (errorDepartement || errorRegion) return res.status(400).send({ ok: false, code: ERRORS.INVALID_BODY });
      data = await ProgramModel.find({ $or: [{ visibility: "NATIONAL" }, { department: checkedDepartement }, { region: checkedRegion }] });
    }
    return res.status(200).send({ ok: true, data });
  } catch (error) {
    capture(error);
    res.status(500).send({ ok: false, code: ERRORS.SERVER_ERROR });
  }
});

router.get("/public/engagements", async (req, res) => {
  try {
    const data = await ProgramModel.aggregate([
      {
        $match: { visibility: "NATIONAL" },
      },
      {
        $addFields: {
          order: { $ifNull: ["$order", Number.MAX_SAFE_INTEGER] },
        },
      },
      {
        $sort: { order: 1 },
      },
    ]);
    return res.status(200).send({ ok: true, data });
  } catch (error) {
    capture(error);
    res.status(500).send({ ok: false, code: ERRORS.SERVER_ERROR });
  }
});

router.get("/public/engagement/:id", async (req, res) => {
  try {
    const { error, value: checkedId } = validateId(req.params.id);
    if (error) {
      capture(error);
      return res.status(400).send({ ok: false, code: ERRORS.INVALID_PARAMS });
    }
    const data = await ProgramModel.findById(checkedId);
    if (!data) return res.status(404).send({ ok: false, code: ERRORS.NOT_FOUND });
    return res.status(200).send({ ok: true, data });
  } catch (error) {
    capture(error);
    res.status(500).send({ ok: false, code: ERRORS.SERVER_ERROR });
  }
});

router.delete("/:id", passport.authenticate("referent", { session: false, failWithError: true }), async (req, res) => {
  try {
    const { error, value: checkedId } = validateId(req.params.id);
    if (error) {
      capture(error);
      return res.status(400).send({ ok: false, code: ERRORS.INVALID_PARAMS });
    }
    const program = await ProgramModel.findById(checkedId);
    if (!canCreateOrUpdateProgram(req.user, program)) return res.status(403).send({ ok: false, code: ERRORS.OPERATION_UNAUTHORIZED });
    await program.remove();
    logger.debug(`Program ${req.params.id} has been deleted`);
    res.status(200).send({ ok: true });
  } catch (error) {
    capture(error);
    res.status(500).send({ ok: false, code: ERRORS.SERVER_ERROR });
  }
});

module.exports = router;