From 5893ddb1f4805adcce13b6aa1baa4829d535fc20 Mon Sep 17 00:00:00 2001
From: ManifoldFR <wilson.jallet@gmail.com>
Date: Wed, 29 Aug 2018 20:15:20 +0200
Subject: [PATCH] Centraliser import config LDAP
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Capacité de remplacer des valeurs dynamiquement par des envars

resolves #8
---
 README.md              | 50 ++++++++++++++++++++++++++++++------------
 knexfile.js            |  4 ++--
 package-lock.json      | 46 +++++++++++++++++++-------------------
 package.json           |  9 ++++----
 src/config_passport.js | 22 +++++++++----------
 src/ldap/config.js     | 19 ++++++++++++++++
 src/ldap/ldap_data.js  | 10 ++++-----
 src/views/home.pug     |  2 +-
 8 files changed, 99 insertions(+), 63 deletions(-)
 create mode 100644 src/ldap/config.js

diff --git a/README.md b/README.md
index 6f61af1..91ffe85 100644
--- a/README.md
+++ b/README.md
@@ -8,9 +8,9 @@ Pour obtenir une copie de ce dépôt, clonez-le avec
 
     git clone git@gitlab.binets.fr:br/sigma-backend.git
 
-ou `git clone https://gitlab.binets.fr/br/sigma-backend.git`, puis installez les dépendences JavaScript avec `npm install`.
+ou `git clone https://gitlab.binets.fr/br/sigma-backend.git`, puis installez les dépendances JavaScript avec `npm install`.
 
-A terme, ce projet doit tourner sur un serveur de l'Ecole polytechnique et fournir à un serveur frontend *au code séparé et documenté séparément* toute les données nécessaires à son bon fonctionnement (authentification, appartenance à un groupe, droits de visibilité...). Le dépôt pour le serveur front se trouve ici : https://gitlab.binets.fr/br/sigma-frontend (on l'appellera indifferemment serveur front, front ou frontend...)
+À terme, ce projet doit tourner sur un serveur du BR et servir d'API à un _frontend_ React *au code séparé et documenté séparément* toute les données nécessaires à son bon fonctionnement (authentification, appartenance à un groupe, droits de visibilité...). Le dépôt pour le serveur front se trouve ici : <https://gitlab.binets.fr/br/sigma-frontend> (on l'appellera indifféremment serveur front, front ou frontend...)
 
 Ce document détaille les différentes dépendances du projet, sa structure générale, détaille un peu plus des éléments sur la base de données et la documentation ; le code est également commenté en détail.
 
@@ -31,23 +31,42 @@ npm install -g webpack
 npm install -g eslint
 ```
 
-Les dépendances les plus importantes sont knex.js, notre outil de gestion de BDD locale, GraphQL qui sert à communiquer entre serveurs, ldap.js qui interroge le LDAP avec la plupart des données, webpack qui sert à la gestion du serveur. ESlint est un outil de vérification synthaxique.
+Les dépendances les plus importantes sont knex.js, notre outil de gestion de BDD locale, GraphQL qui sert à communiquer entre serveurs, ldap.js qui interroge le LDAP avec la plupart des données, webpack qui sert à la gestion du serveur. ESlint est un outil de vérification syntaxique.
 
 Le serveur utilisé est [express.js](https://expressjs.com/) ; il est configuré dans [`server.js`](../src/server.js) puis lancé sur le port 3000 dans [`index.js`](../src/index.js).
 
+## Configuration LDAP
+
+L'API de Sigma nécessite de se connecter au LDAP Frankiz, à la fois pour obtenir des données et pour l'authentification des utilisateurs. Cela est fait à l'aide de la librairie [ldapjs](http://ldapjs.org) pour faire les requêtes au LDAP et [passportJS](http://www.passportjs.org/) pour l'auth.
+
+* La configuration LDAP de base se situe dans [ldap_config.json](ldap_config.json).
+* Elle est importée dans l'application depuis [src/ldap/config.js](src/ldap/config.js). Ce fichier écrase la config de base selon les options suivantes :
+    | **Variable** | **Description** | **Défaut** (`ldap_config.json`) |
+    | ------ | ------ | ----- |
+    | LDAP_URI | URI vers le serveur LDAP. | <ldap://frankiz.eleves.polytechnique.fr:389> |
+
+### Exemple
+
+Si on développe en dehors du plâtal et qu'on ouvre un proxy SSH _port forwarding_ du LDAP de Frankiz (<frankiz.polytechnique.fr:389>) vers <localhost:8389>, on s'y connecte en définissant
+
+```bash
+export LDAP_URI=ldap://localhost:8389
+```
+
+et le fichier `config.js` s'occupe du reste.
+
 ## Panneau d'administration
 
-Il est accessible au path /adminview/admin ; n'importe quel path devrait rediriger dessus, ou alors vers /adminview/login. Les identifiants à utiliser sont ceux de Frankiz. L'authentification se fait par le LDAP Frankiz.
+Il est accessible au path `/adminview/admin` ; n'importe quel path devrait rediriger dessus, ou alors vers `/adminview/login`. Les identifiants à utiliser sont ceux de Frankiz. L'authentification se fait par le LDAP Frankiz.
 
 ### Accès direct à la BDD via knex
 
-Le panneau d'administration sert (ou plutôt, servira à terme) à accéder directement à la BDD propre de sigma. On accède à la table `table_name` par une requête GET à '/adminview/db/`table_name`' et aux colonnes `columns` de cette table par une requête GET à '/adminview/db/`table_name`?columns=`columns`.
-Ces pages sont protégées pour n'être accessibles qu'en étant authentifé.
+Le panneau d'administration sert (ou plutôt, servira à terme) à accéder directement à la BDD propre de sigma. On accède à la table `table_name` par une requête GET à `/adminview/db/table_name`' et aux colonnes `columns` de cette table par une requête GET à `/adminview/db/table_name`?columns=`columns`.
+Ces pages sont protégées pour n'être accessibles qu'en étant authentifié.
 
 ### GraphiQL et Voyager
 
-A partir du panneau d'admin, en faisant des requêtes GET à '/graphiql' et '/voyager' respectivement, on accède à GraphiQL et à GraphQL Voyager. Ces pages sont protégées pour n'être accessibles qu'en étant authentifé.
-
+A partir du panneau d'admin, en faisant des requêtes GET à `/graphiql` et `/voyager` respectivement, on accède à GraphiQL et à GraphQL Voyager. Ces pages sont protégées pour n'être accessibles qu'en étant authentifié.
 
 ## Scripts
 
@@ -60,14 +79,17 @@ On utilisera Webpack pour transpiler le fichier source [`src/index.js`](../src/i
 * `npm run build` qui exécute la commande `webpack` avec le fichier de configuration `webpack.config.js`, ou
 * `npm run watch` qui recompile automatiquement dès que le code est modifié.
 
-Pour faire tourner le serveur, il y a deux options :
+### Démarrer le serveur
+
+Pour faire tourner le serveur, lancer
+
+    npm start
 
-* `npm serve` fait tourner le serveur `bundle.js` en mode prod sur le port 3000 (donc il faut consulter https://localhost:3000)
-* `npm start` le démarre avec [nodemon](https://nodemon.io/), outil dév qui redémarre automatiquement le serveur dans `bundle.js` dès que celui-ci est modifié.
+démarre le serveur compilé [`build/bundle.js`](build/bundle.js) avec [nodemon](https://nodemon.io/), outil dév, et le redémarre automatiquement après modification.
 
-Donc, lancer `npm run watch` dans un terminal et `npm test` dans un autre permet de recompiler le serveur __et__ le redémarrer automatiquement dès qu'il y a une modification.
+Donc, lancer `npm run watch` dans un terminal et `npm start` dans un autre permet de recompiler le serveur __et__ le relance automatiquement.
 
-Le script pour faire tourner [JSDoc](http://usejsdoc.org/index.html) et régénérrer la documentation est : `npm run doc`
+Le script pour faire tourner [JSDoc](http://usejsdoc.org/index.html) et régénérer la documentation est : `npm run doc`
 
 ## Documentation
 
@@ -75,4 +97,4 @@ La documentation détaillée du projet est [ici](./doc/index.html). Elle a été
 
 Les fichiers compilés se situent dans [`doc`](.) avec leurs fichiers image. Par nature de l'outil JSDoc il est facile de documenter en détail des fonctions .js mais plus compliqué de documenter un fichier.
 
-A la fin de ce fichier JSDoc rajjoute les commentaires placés dans chacun des fichiers et des hyperliens pour y accéder.
+A la fin de ce fichier JSDoc rajoute les commentaires placés dans chacun des fichiers et des hyperliens pour y accéder.
diff --git a/knexfile.js b/knexfile.js
index 910e1b8..727a50b 100644
--- a/knexfile.js
+++ b/knexfile.js
@@ -13,9 +13,9 @@ module.exports = {
         client: 'pg',
         connection: {
             host: 'localhost',
-            user: 'will',
+            user: 'sigma',
             password: 'password',
-            database: 'sigma_dev',
+            database: 'sigma-dev',
             charset: 'utf8'
         },
         pool: {
diff --git a/package-lock.json b/package-lock.json
index c52a88a..74179b9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2045,7 +2045,7 @@
     },
     "cacache": {
       "version": "10.0.4",
-      "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
+      "resolved": "http://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz",
       "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==",
       "requires": {
         "bluebird": "^3.5.1",
@@ -2459,9 +2459,9 @@
       "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
     },
     "colors": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.0.tgz",
-      "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw=="
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz",
+      "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ=="
     },
     "commander": {
       "version": "2.15.1",
@@ -3081,9 +3081,9 @@
       "dev": true
     },
     "elliptic": {
-      "version": "6.4.0",
-      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
-      "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+      "version": "6.4.1",
+      "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
+      "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==",
       "dev": true,
       "requires": {
         "bn.js": "^4.4.0",
@@ -3329,9 +3329,9 @@
       }
     },
     "eslint-plugin-import": {
-      "version": "2.13.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.13.0.tgz",
-      "integrity": "sha512-t6hGKQDMIt9N8R7vLepsYXgDfeuhp6ZJSgtrLEDxonpSubyxUZHjhm6LsAaZX8q6GYVxkbT3kTsV9G5mBCFR6A==",
+      "version": "2.14.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz",
+      "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==",
       "dev": true,
       "requires": {
         "contains-path": "^0.1.0",
@@ -3476,7 +3476,7 @@
     },
     "event-stream": {
       "version": "3.3.4",
-      "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
+      "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
       "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
       "dev": true,
       "requires": {
@@ -9753,9 +9753,9 @@
       "optional": true
     },
     "uglifyjs-webpack-plugin": {
-      "version": "1.2.7",
-      "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.7.tgz",
-      "integrity": "sha512-1VicfKhCYHLS8m1DCApqBhoulnASsEoJ/BvpUpP4zoNAPpKzdH+ghk0olGJMmwX2/jprK2j3hAHdUbczBSy2FA==",
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz",
+      "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==",
       "dev": true,
       "requires": {
         "cacache": "^10.0.4",
@@ -10208,9 +10208,9 @@
       }
     },
     "webpack": {
-      "version": "4.16.1",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.16.1.tgz",
-      "integrity": "sha512-6jpzObU18y7lXDJz7XCLvzgrqcJ0rZ2jhKvnTivza9gM2GvPW93xxtmEll2GgmdC0zVQAtbHrH/9BtyMjSDZfA==",
+      "version": "4.17.1",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.17.1.tgz",
+      "integrity": "sha512-vdPYogljzWPhFKDj3Gcp01Vqgu7K3IQlybc3XIdKSQHelK1C3eIQuysEUR7MxKJmdandZlQB/9BG2Jb1leJHaw==",
       "dev": true,
       "requires": {
         "@webassemblyjs/ast": "1.5.13",
@@ -10241,9 +10241,9 @@
       },
       "dependencies": {
         "acorn": {
-          "version": "5.7.1",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz",
-          "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==",
+          "version": "5.7.2",
+          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.2.tgz",
+          "integrity": "sha512-cJrKCNcr2kv8dlDnbw+JPUGjHZzo4myaxOLmpOX8a+rgX94YeTcTMv/LFJUSByRpc+i4GgVnnhLxvMu/2Y+rqw==",
           "dev": true
         },
         "eslint-scope": {
@@ -10577,9 +10577,9 @@
       "dev": true
     },
     "webpack-sources": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz",
-      "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.2.0.tgz",
+      "integrity": "sha512-9BZwxR85dNsjWz3blyxdOhTgtnQvv3OEs5xofI0wPYTwu5kaWxS08UuD1oI7WLBLpRO+ylf0ofnXLXWmGb2WMw==",
       "dev": true,
       "requires": {
         "source-list-map": "^2.0.0",
diff --git a/package.json b/package.json
index 474e402..bdd1bb6 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,6 @@
   "description": "Backend of sigma, the new Frankiz",
   "scripts": {
     "build": "webpack --mode production",
-    "serve": "node build/bundle.js",
     "dev": "webpack --mode development",
     "watch": "webpack --watch --mode development",
     "start": "nodemon --watch build build/bundle.js",
@@ -13,13 +12,13 @@
   },
   "repository": {
     "type": "git",
-    "url": "git@gitlab.binets.fr:br/sigma-backend"
+    "url": "https://gitlab.binets.fr/br/sigma-backend"
   },
   "author": "Binet Réseau",
   "license": "ISC",
   "dependencies": {
     "body-parser": "^1.18.3",
-    "colors": "^1.3.0",
+    "colors": "^1.3.2",
     "connect-ensure-login": "^0.1.1",
     "connect-flash": "^0.1.1",
     "cookie-parser": "^1.4.3",
@@ -53,13 +52,13 @@
     "eslint": "^4.19.1",
     "eslint-config-standard": "^11.0.0",
     "eslint-loader": "^2.1.0",
-    "eslint-plugin-import": "^2.13.0",
+    "eslint-plugin-import": "^2.14.0",
     "eslint-plugin-node": "^6.0.1",
     "eslint-plugin-promise": "^3.8.0",
     "eslint-plugin-standard": "^3.1.0",
     "jsdoc": "^3.5.5",
     "nodemon": "^1.18.3",
-    "webpack": "^4.16.1",
+    "webpack": "^4.17.1",
     "webpack-cli": "^2.1.5",
     "webpack-node-externals": "^1.7.2"
   }
diff --git a/src/config_passport.js b/src/config_passport.js
index 717e0a4..f07fa2f 100644
--- a/src/config_passport.js
+++ b/src/config_passport.js
@@ -1,27 +1,25 @@
-import passport from 'passport';
-import LdapStrategy from 'passport-ldapauth';
-import fs from 'fs';
-import path from 'path';
-
 /**
  * @description Configuration de passport pour utiliser l'authentification LDAP
  * @author kadabra
  *
  * on a besoin d'authentification pour 2 trucs :
- * - l'acces a l'interface admin (admin_view) du back, definie dans admin_router.js
+ * - l'accès a l'interface admin (admin_view) du back, définie dans admin_router.js
  * - le contexte graphQL
  * 
  * serializeUser permet d'obtenir une cle identifiant chaque user
- * deserializeUser fait une requete vers une BDD de users en utilisant cette cle, et met dans l'objet JS req.user toutes les infos issues de la BDD
- * Cette repartition permet de ne stocker dans la session (i.e. en memoire sur le serveur) que la cle des utilisateurs connectes et de ne "charger en memoire" toutes les infos de la BDD que lorsque necessaire
+ * deserializeUser fait une requête vers une BDD de users en utilisant cette cle, et met dans l'objet JS req.user toutes les infos issues de la BDD
+ * Cette repartition permet de ne stocker dans la session (i.e. en mémoire sur le serveur) que la cle des utilisateurs connectes et de ne "charger en mémoire" toutes les infos de la BDD que lorsque nécessaire
  * cf https://stackoverflow.com/questions/27637609/understanding-passport-serialize-deserialize#27637668
  * et http://toon.io/understanding-passportjs-authentication-flow/
  * 
  * Mais en fait dans notre cas c'est graphql qui communique avec la BDD, donc on s'en fiche! On peut se contenter de dire a serializeUser et deserializeUser de ne s'occuper que du champ uid)
- * (on pourrait penser que passer par deserializeUser permettrait de reduire le nombre d'interactions avec la BDD, mais en fait non car deserializeUser est appele *a chaque requete*)
- */
-const configPath = path.resolve('./', 'ldap_config.json');
-const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
+ * (on pourrait penser que passer par deserializeUser permettrait de réduire le nombre d'interactions avec la BDD, mais en fait non car deserializeUser est appelé *a chaque requete*)
+*/
+import passport from 'passport';
+import LdapStrategy from 'passport-ldapauth';
+import fs from 'fs';
+import path from 'path';
+import { config } from './ldap/config';
 
 // specifies options for 'ldapauth' strategy, to customize the behaviour of subsequent passport.authenticate('ldapauth') calls
 passport.use(new LdapStrategy({
diff --git a/src/ldap/config.js b/src/ldap/config.js
new file mode 100644
index 0000000..1c4793a
--- /dev/null
+++ b/src/ldap/config.js
@@ -0,0 +1,19 @@
+/**
+ * @file Importe la configuration du LDAP au sein de l'application, et remplace certaines valeurs en fonction des variables d'environnement.
+ * @author manifold
+ */
+var fs = require('fs');
+var path = require('path');
+
+// Point central ; tous les champs de la BDD sont 'cachés' dans config.json et pas visibles directement
+var configPath = path.resolve('./', 'ldap_config.json');
+const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
+
+// Override config server from environment
+if (process.env.LDAP_URI != null) {
+    config.ldap.server = process.env.LDAP_URI;
+}
+
+module.exports = {
+    config
+};
diff --git a/src/ldap/ldap_data.js b/src/ldap/ldap_data.js
index 6f6ea7d..c7c298a 100644
--- a/src/ldap/ldap_data.js
+++ b/src/ldap/ldap_data.js
@@ -13,7 +13,7 @@ import fs from 'fs';
 import ldapEscape from 'ldap-escape';
 import path from 'path'; */
 
-/**/var ldap = require('ldapjs');
+var ldap = require('ldapjs');
 var fs = require('fs');
 var assert = require('assert');
 var ldapEscape = require('ldap-escape');
@@ -22,12 +22,10 @@ var path = require('path');
 // Important ; permet de vérifier que l'utilisateur reste connecté.
 var ensureLoggedin =  require('connect-ensure-login').ensureLoggedIn;
 
-// Point central ; tous les champs de la BDD sont 'cachés' dans config.json et pas visibles directement
-var configPath = path.resolve('./','ldap_config.json');
-var config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
-
+const config = require('./config').config;
 // Connection au serveur LDAP avec des temps de timeout arbitraires
-var client = ldap.createClient({ url: config.ldap.server});
+var client = ldap.createClient({url: config.ldap.server});
+console.log(`Connecting to LDAP at ${config.ldap.server}.`);
 
 //------------------------------------------------------------------------------------------------------------------------
 // Fonctions de base
diff --git a/src/views/home.pug b/src/views/home.pug
index 718d835..34e410c 100644
--- a/src/views/home.pug
+++ b/src/views/home.pug
@@ -4,7 +4,7 @@ block content
     h1 Welcome to API server
     h2 Query the database
     p Hello, world! This is server talking to you live on port #{port}!
-    p You can use the REST API to query the database using the form below.
+    p You can query the database using the form below.
     form(action="/adminview/db", method="get")
         div.form-group
             label(for="table") Table
-- 
GitLab