betagouv/service-national-universel

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

Summary

Maintainability
A
0 mins
Test Coverage
const express = require("express");
const router = express.Router();
const Joi = require("joi");
const jwt = require("jsonwebtoken");
const { ROLES } = require("snu-lib");
const { getToken } = require("../passport");
const config = require("config");
const { serializeYoung, serializeReferent } = require("../utils/serializer");
const { ERRORS } = require("../utils");

const { YoungModel, ReferentModel } = require("../models");
const { capture } = require("../sentry");
const { checkJwtSigninVersion } = require("../jwt-options");

const allowedRole = (user) => {
  switch (user?.role) {
    case ROLES.ADMIN:
      return "admin";
    case ROLES.REFERENT_DEPARTMENT:
    case ROLES.REFERENT_REGION:
      return "referent";
    case ROLES.RESPONSIBLE:
    case ROLES.SUPERVISOR:
      return "structure";
    case ROLES.HEAD_CENTER:
      return "head_center";
    case ROLES.ADMIN_CLE:
      return "administrateur_cle";
    case ROLES.REFERENT_CLASSE:
      return "referent_classe";
    default:
      return "public";
  }
};

router.get("/token", async (req, res) => {
  try {
    const token = getToken(req);
    if (!token) return res.status(401).send({ ok: false, user: { restriction: "public" } });

    let jwtPayload;
    try {
      jwtPayload = await jwt.verify(token, config.JWT_SECRET);
    } catch (error) {
      return res.status(401).send({ ok: false, user: { restriction: "public" } });
    }

    const { error, value } = Joi.object({
      __v: Joi.string().required(),
      _id: Joi.string().required(),
      passwordChangedAt: Joi.date().allow(null),
      lastLogoutAt: Joi.date().allow(null),
    }).validate(jwtPayload, { stripUnknown: true });

    if (error || !checkJwtSigninVersion(value)) {
      return res.status(401).json({ ok: false, user: { restriction: "public" } });
    }

    const { _id, passwordChangedAt, lastLogoutAt } = value;

    // First, check in the YoungModel
    let user = await YoungModel.findById(_id);
    if (user) {
      if (passwordChangedAt?.getTime() === user.passwordChangedAt?.getTime() && lastLogoutAt?.getTime() === user.lastLogoutAt?.getTime()) {
        user.set({ lastActivityAt: Date.now() });
        await user.save();
        return res.status(200).send({ ok: true, user: { ...serializeYoung(user, user), allowedRole: "young" } });
      }
    }

    // If not found in YoungModel, check in ReferentModel
    user = await ReferentModel.findById(_id);
    if (user) {
      if (passwordChangedAt?.getTime() === user.passwordChangedAt?.getTime() && lastLogoutAt?.getTime() === user.lastLogoutAt?.getTime()) {
        user.set({ lastActivityAt: Date.now() });
        await user.save();
        return res.status(200).send({ ok: true, user: { ...serializeReferent(user, user), allowedRole: allowedRole(user) } });
      }
    }

    return res.status(401).send({ ok: false, user: { restriction: "public" } });
  } catch (error) {
    capture(error);
    return res.status(500).send({ ok: false, code: ERRORS.SERVER_ERROR, user: null });
  }
});

module.exports = router;