diff --git a/README.md b/README.md index 6f61af13f678faa588d2d893c100f5272c661b80..91ffe8519a593e3a288bf31b1cf7faf082b39e68 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 910e1b85e984fcbd9ae63e712a108b20834f78a7..727a50bb122d6053c173633e3e89387c0ad2b86f 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 c52a88a7ee40181a41ffbc7f6d8adce4ba2cc14c..74179b9a3f0a14392243f38268408da39150b9ed 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 474e402e368e2b9c3a4161bf8fbab9bd7c441885..bdd1bb6689c5ab89ae85bc9274d41c810e56de20 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 717e0a4eda94157dba92093b8174039deccb3dab..f07fa2fe73a935c58ebc064721536dcf3f5bd91b 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 0000000000000000000000000000000000000000..1c4793a8408e4e9cb187230db6fb3eb1be92bfcc --- /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 6f6ea7d06cbc5074979dbb540e914f842708fcf5..c7c298a2e3aebc158ec148c799b8c2d1200da133 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 718d835efc52481581b6be858273ab0d9efee8d9..34e410c2204b02099bbf4fd619a92196de20d517 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