Source: component/helperClient.js

/**
 * This file is part of Sesatheque.
 *   Copyright 2014-2015, Association Sésamath
 *
 * Sesatheque is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License version 3
 * as published by the Free Software Foundation.
 *
 * Sesatheque is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Sesatheque (LICENCE.txt).
 * @see http://www.gnu.org/licenses/agpl.txt
 *
 *
 * Ce fichier fait partie de l'application Sésathèque, créée par l'association Sésamath.
 *
 * Sésathèque est un logiciel libre ; vous pouvez le redistribuer ou le modifier suivant
 * les termes de la GNU Affero General Public License version 3 telle que publiée par la
 * Free Software Foundation.
 * Sésathèque est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE ;
 * sans même la garantie tacite de QUALITÉ MARCHANDE ou d'ADÉQUATION à UN BUT PARTICULIER.
 * Consultez la GNU Affero General Public License pour plus de détails.
 * Vous devez avoir reçu une copie de la GNU General Public License en même temps que Sésathèque
 * (cf LICENCE.txt et http://vvlibri.org/fr/Analyse/gnu-affero-general-public-license-v3-analyse
 * pour une explication en français)
 */
'use strict'
// un module avec des méthodes communes pour le service et le controleur du client
const { defaultPrefix } = require('./common')
const helper = require('./helper')

/** @type {sesalabSsoClient} */
let client

/**
 * Retourne un authServer si on trouve sa baseUrl en config
 * @param {string} baseUrl
 * @returns {AuthServerDef}
 */
function getAuthServer (baseUrl) {
  const server = client.authServers.find((server) => server.baseUrl === baseUrl)
  /* global log */
  if (!server && typeof log !== 'undefined' && log.debug) log.debug('pas trouvé ' + baseUrl + 'parmi', client.authServers)
  return server
}

/**
 * Initialise client
 * @private
 */
function init (componentConfig, baseUrl) {
  client = helper.getBaseConfig(componentConfig, baseUrl)

  // spécifique client
  if (!componentConfig.authServers || !componentConfig.authServers.length) throw new Error('Impossible d’initialiser $sesalabSsoClient sans préciser authServers en configuration')
  client.authServers = componentConfig.authServers.map(function (authServer) {
    /**
     * @private
     * @type {AuthServer}
     */
    const cleanServer = {}
    ;['baseUrl', 'errorPage', 'loginPage', 'logoutPage'].forEach(function (prop) {
      if (typeof authServer[prop] !== 'string' || !authServer[prop]) {
        throw new Error('config incorrecte, ' + prop + ' manquant sur un authServer')
      }
      cleanServer[prop] = authServer[prop]
    })
    const prefix = authServer.prefix || defaultPrefix
    cleanServer.validate = prefix + '/validate'
    return cleanServer
  })
  // pour les callback, on initialise avec des fcts qui renvoient une erreur,
  // elle devront donc être écrasée avant de les utiliser
  if (componentConfig.logoutCallback) {
    client.logoutCallback = componentConfig.logoutCallback
  } else {
    client.logoutCallback = function (context, next) {
      next(new Error('Erreur de configuration, pas de méthode de déconnexion'))
    }
  }
  if (componentConfig.loginCallback) {
    client.loginCallback = componentConfig.loginCallback
  } else {
    client.loginCallback = function (context, user, next) {
      next(new Error('Erreur de configuration, pas de méthode de connexion'))
    }
  }
  // console.log('$sesalabSsoClient a construit le client', client)
}

/**
 * Wrapper de la loginCallback courante
 * @param context
 * @param user
 * @param next
 */
function loginCallback (context, user, next) {
  client.loginCallback(context, user, next)
}

/**
 * Wrapper de la loginCallback courante
 * @param context
 * @param next
 */
function logoutCallback (context, next) {
  client.logoutCallback(context, next)
}

/**
 * Affecte des nouvelles propriétés de client
 * @param {object} props
 */
function setClient (props) {
  Object.assign(client, props)
}

module.exports = {
  getAuthServer,
  getBaseUrl: () => client.baseUrl,
  init,
  loginCallback,
  logoutCallback,
  setClient
}

/**
 * @callback simpleCallback
 * @param {Error} [error]
 */
/**
 * @callback loginCallback
 * @param {Context} context
 * @param {User} user
 * @param {simpleCallback} next
 */
/**
 * @callback logoutCallback
 * @param {Context} context
 * @param {simpleCallback} next
 */
/**
 * La définition du client une fois normée par init
 * @typedef {Object} sesalabSsoClient
 * @property {string} baseUrl
 * @property {number} [timeout=10] Timeout des appels du validate (en s)
 * @property {string} [prefix=sesalabSso] Préfixe des routes de ce module
 * @property {AuthServer[]} authServers La liste des serveurs d'authentification
 * @property {function} loginCallback Logue le user localement, appelée avec (context, user, next), doit rappeler next(error)
 * @property {function} logoutCallback Déconnecte le user courant localement, appelée avec (context, next), doit rappeler next(error)
 */