diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 71a6cec492bb21276249979a9acb3ad825fa7dcd..f24be0302fa8290575a0427afd9af0dbdfba1255 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -45,18 +45,6 @@ test:lint: tags: - lint -# Run the Express server and perform requests to it -test:async: - stage: test - script: - - npm start & - - sleep 5 - - curl http://localhost:3000 - - pkill node - - exit 0 - tags: - - server - deploy_staging: stage: deploy script: diff --git a/README.md b/README.md index dc592e62df4a195f95dbce4fef1b179f6e5396f3..a0c3b75e2b17660278364408c01cdc893391e2b0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [](https://gitlab.binets.fr/br/sigma-backend/commits/master) -## Introduction +# Introduction Ce dépôt contient le _backend_ de Sigma, le successeur de Frankiz, un site étudiant permettant de gérer les groupes et les étudiants du plateau de Saclay. @@ -10,7 +10,7 @@ Pour obtenir une copie de ce dépôt, clonez-le avec ou `git clone https://gitlab.binets.fr/br/sigma-backend.git`, puis installez les dépendences JavaScript avec `npm install`. -A terme, ce projet doit tourné sur un serveur de l'école polytechnique et fournir à un serveur front - 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é...). +A terme, ce projet doit tourné sur un serveur de l'école polytechnique et fournir à un serveur front *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é...). 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. @@ -39,25 +39,24 @@ Le serveur utilisé est [express.js](https://expressjs.com/) ; il est configuré La structure générale du projet est détaillée ci-dessous ; pas d'inquiétude, la plupart des fichiers .js sont aussi extensivement documentés plus bas. -- Racine du projet : fichiers de configuration ; - - config.json : données "sensibles" spécifique au projet à priori non partageable (adresse du LDAP, mots de passe), - - configfile_doc.json : JSDoc, l'outil de génération automatique de documentation, - - autres fichiers relatifs à des modules particuliers ou à la gestion de paquets, - - [`assets`](../assets) : ressources ; - - images et divers (dont l'essentiel flavicon) - - [`build`](../build) : dépendances gérées automatiquement ; - - bundle.js est un monstrueux fichier généré automatiquement qui gère nos dépendances. - - [`db`](../db) : base de donnée sigma ; - - knex_router.js charge la configuration précisée dans knexfile.js, - - [`migrations`](../db/migrations) stocke l'ensemble des migrations knex ; c'est un équivalent d'un répertoire git pour la BDD sigma (du coup seulement les groupes pas les individus), - - [`seeds`](../db/seeds) : stocke les éléments de générations des BDD ; c'est un ensemble de scripts. - - [`doc`](.) : documentation ; - - ensemble de pages html et fichiers associés ; index.html permet de naviguer sereinement sur toute la doc JSDoc. - - [`node_modules`](../node_modules) : gestion automatique des modules. - - [`src`](../src) : code source - - [`admin_view`](../src/admin_view) : gestion d'une interface administrateur de la base de donnée, s'appuie sur *css* et *views* - - [`ldap`](../src/ldap) : gestion des requêtes LDAP - +* Racine du projet : fichiers de configuration ; + * config.json : données "sensibles" spécifique au projet à priori non partageable (adresse du LDAP, mots de passe), + * configfile_doc.json : JSDoc, l'outil de génération automatique de documentation, + * autres fichiers relatifs à des modules particuliers ou à la gestion de paquets, + * [`assets`](../assets) : ressources ; + * images et divers (dont l'essentiel flavicon) + * [`build`](../build) : dépendances gérées automatiquement ; + * bundle.js est un monstrueux fichier généré automatiquement qui gère nos dépendances. + * [`db`](../db) : base de donnée sigma ; + * knex_router.js charge la configuration précisée dans knexfile.js, + * [`migrations`](../db/migrations) stocke l'ensemble des migrations knex ; c'est un équivalent d'un répertoire git pour la BDD sigma (du coup seulement les groupes pas les individus), + * [`seeds`](../db/seeds) : stocke les éléments de générations des BDD ; c'est un ensemble de scripts. + * [`doc`](.) : documentation ; + * ensemble de pages html et fichiers associés ; index.html permet de naviguer sereinement sur toute la doc JSDoc. + * [`node_modules`](../node_modules) : gestion automatique des modules. + * [`src`](../src) : code source + * [`admin_view`](../src/admin_view) : gestion d'une interface administrateur de la base de donnée, s'appuie sur *css* et *views* + * [`ldap`](../src/ldap) : gestion des requêtes LDAP La syntaxe adoptée est JavaScript ES6, un standard moderne (2015) de JavaScript. Il permet d'importer des dépendances en utilisant le mot-clé `import`, ce que le serveur Node.js ne comprend pas puisque la version 8 de Node ne comprend que le standard ES5 (2009), qui gère les imports avec `require()`. @@ -66,33 +65,43 @@ La syntaxe adoptée est JavaScript ES6, un standard moderne (2015) de JavaScript Sigma s'appuie sur deux bases de données : * La BDD frankiz accessible par LDAP hébergée sur un serveur de l'école, qui contient identifiants, mots de passe, et toutes les informations sur les utilisateurs et groupes spécifiques X. - * On y accède par des requêtes LDAP, d'où la nécessité de ldap.js. + * On y accède par des requêtes LDAP, d'où la nécessité de ldap.js. * La BDD de sigma propre est en [PostgreSQL](https://www.postgresql.fr/), hébergée en propre BR, qui contient les groupes et leurs niveaux de visibilité mais peu d'information sur les utilisateurs (seulement son école). - * Cette BDD est géré par [Knex](http://knexjs.org). + * Les requêtes à cette base de données sont gérées par [Knex.js](http://knexjs.org). Cette structure peut sembler lourde et redondante mais s'explique par plusieurs raisons : * Volonté d'intégrer d'autres écoles simplement - * Rajouter leurs groupes sur la BDD sigma - * Pas les obliger à rejoindre notre LDAP avec notre structure + * Rajouter leurs groupes sur la BDD sigma + * Pas les obliger à rejoindre notre LDAP avec notre structure * Garder le LDAP X et le mettre à jour ; il est utilisé par beaucoup d'autres sites X * Enjeu de sécurité - * La BDD de sigma est public et ne comporte rien de compromettant - * La BDD accessible par LDAP de l'X qui contient des informations plus sensibles et qui doit être plus protégée + * La BDD de sigma est public et ne comporte rien de compromettant + * La BDD accessible par LDAP de l'X qui contient des informations plus sensibles et qui doit être plus protégée Les deux sections suivantes détaillent les opérations possibles grâce au back directement sur les bases de données via sigma. -### Fonctions knexjs +### Guide: Knex.js -Quelques exemples de fonctions utiles de `knexjs` [Knex](http://knexjs.org) +L'interface en ligne de commande de [Knex.js](http://knexjs.org) contient les commandes suivantes : -* `knex migrate:make migration_name` crée une migration dans `migrations/` : le nom du fichier est `migration_name.js` avec la date et l'heure en préfixe +* `knex migrate:make migration_name` crée une migration dans `db/migrations/` * `knex migrate:latest` met à jour le schéma de la BDD * `knex seed:make filename` crée un _seed_ `seeds/filename` * `knex seed:run` insère les _seeds_ dans la BDD Un fichier _seed_ permet d'insérer des données dans la BDD. Ils sont stockés dans [`seeds`](../db/seeds). +#### Comment faire une migration + +On utilisera l'interface en ligne de commande de Knex.js. + +Les migrations servent à **mettre à jour le schéma de la base de données**. Pour créer une migration, on lance la commande `knex migrate:make <nom_migration>`, qui crée un fichier `db/migrations/[hash]_nom_migration.js` où le hash est la date et l'heure. + +Maintenant, on édite le fichier de migration. Il fait deux exports, `exports.up` et `exports.down`, qui définissent respectivement comment mettre à jour le schéma de la BDD et comment annuler la modification si `knex migrate:rollback` est invoqué. + +Il faut se référer à la documentation de Knex.js pour comprendre comment écrire les requêtes. Voici un [cheatsheet](https://devhints.io/knex). + ### Fonctions LDAP On peut facilement explorer et modifier des éléments du LDAP de l'école depuis le réseau de l'X avec [JXplorer](http://jxplorer.org/) en entrant `frankiz` dans nouvelle connexion et en allant dans `net`. @@ -115,7 +124,7 @@ Pour faire tourner le serveur, il y a deux options : 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. -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érrer la documentation est : `npm run doc` ## Documentation diff --git a/ldap_config.json b/ldap_config.json new file mode 100644 index 0000000000000000000000000000000000000000..34e97c93c6a21021b45e2282906be46db14b1938 --- /dev/null +++ b/ldap_config.json @@ -0,0 +1,23 @@ +{ + "connexion": { + "dn": "uid=quentin.chevalier,ou=eleves,dc=frankiz,dc=net", + "passwd": "Ie42fds'eaJm1" + }, + "ldap": { + "server": "ldap://frankiz.eleves.polytechnique.fr:389", + "searchBase": "ou=eleves,dc=frankiz,dc=net", + "searchFilter": "(uid={{username}})" + }, + "dn_groups":"ou=groups,dc=frankiz,dc=net", + "dn_users": "ou=eleves,dc=frankiz,dc=net", + "key_al": "uid", + "filter_id": "(uid=${id})", + "filter_lg": "(restrictedMemberUid=${id})", + "attributes_id": ["uid"], + "attributes_al": ["memberUid"], + "attributes_lm":["restrictedMemberUid"], + "attributes_lg":["brMemberOf"], + "attributes_all": ["jpegPhoto","givenName", "sn", "brBirthdate", "brPromo","telephoneNumber","mail","brRoom","brIP"], + "search_attributes_tol": ["givenName", "sn", "displayName", "country", "brMemberOf", "brPromo", "brMemberOf", "brMemberOf", "brMemberOf", "telephoneNumber","mail","brRoom","brIP"], + "sessionSecret":"change this" +} \ No newline at end of file diff --git a/src/graphql/schema.js b/src/graphql/schema.js index 9db49a7f6ee041cba7828726ed30a83a69728660..e8d35ce5741128b248aa2f3d0713ac699316e20b 100644 --- a/src/graphql/schema.js +++ b/src/graphql/schema.js @@ -4,7 +4,7 @@ */ import knex from '../../db/knex_router'; -// import { listGroups, listMembers } from '../ldap/ldap_data'; +import { listGroups, listMembers } from '../ldap/ldap_data'; import { makeExecutableSchema } from 'graphql-tools'; import { request } from 'https'; @@ -25,13 +25,13 @@ const typeDefs = ` `; const getAllVisibleGroups = (user) => { - console.log("getAllVisibleGroups gets called") + console.log("getAllVisibleGroups gets called"); // let group_ids = listGroups(user.id); return knex.select().from('groups')/*.whereIn('id', group_ids)*/; }; const getGroupIfVisible = (user, id) => { - console.log("getGroupIfVisible gets called") + console.log("getGroupIfVisible gets called"); return getAllVisibleGroups(user).where('id', id)/*.then(function(table) { console.log(JSON.stringify(table,null,2))*/; }; diff --git a/src/ldap/ldap_auth.js b/src/ldap/ldap_auth.js index 9d35e346995ca2a914a3d799f362df39f20ff975..c881e173417d3d3b049787a938c33b6b6b3782c9 100644 --- a/src/ldap/ldap_auth.js +++ b/src/ldap/ldap_auth.js @@ -6,8 +6,10 @@ import passport from 'passport'; import LdapStrategy from 'passport-ldapauth'; import session from 'express-session'; import fs from 'fs'; +import path from 'path'; -let config = JSON.parse(fs.readFileSync('config.json', 'utf8')); +let configPath = path.resolve('./','ldap_config.json'); +let config = JSON.parse(fs.readFileSync(configPath, 'utf8')); passport.use(new LdapStrategy({ server: { diff --git a/src/ldap/ldap_data.js b/src/ldap/ldap_data.js index 9c6abdda14a99a12dcae3ddc7cf9b1a6ce41e5db..26dfb2406944477a4b741afb939d60a083a36071 100644 --- a/src/ldap/ldap_data.js +++ b/src/ldap/ldap_data.js @@ -11,12 +11,15 @@ import ldapEscape from 'ldap-escape'; */ /**/var ldap = require('ldapjs'); var fs = require('fs'); var ldapEscape = require('ldap-escape'); +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 -let config = JSON.parse(fs.readFileSync('../../config.json', 'utf8')); +let configPath = path.resolve('./','ldap_config.json'); +console.log('LDAP configuration loaded from',configPath); +let config = JSON.parse(fs.readFileSync(configPath, 'utf8')); // Connection au serveur LDAP avec des temps de timeout arbitraires var client = ldap.createClient({ url: config.ldap.server});