diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..b031331fe0b9705c699fc22dd044f867c1fb1505 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +src/ +ldap_connexion_config.json \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9386d1b1379ce418459cd00beec21ecc43d3a7bd..77a886f18139a4fc9c53de74056d2dbf610190ae 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,6 @@ # Official framework image. Look for the different tagged releases at: # https://hub.docker.com/r/library/node/tags/ -image: node:latest +image: node:10-slim # Only needed when using a docker container to run your tests in. # Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service @@ -25,8 +25,6 @@ stages: # make migrations on and seed the db install-dependencies: stage: install - before_script: - - npm i -g npm script: - npm ci artifacts: diff --git a/Dockerfile b/Dockerfile index 2a69b6ceb89e2e234c8dd76d900649c4a856d1dd..6efd65c661ade15fd90973b4884f3a12f0368a0d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,3 @@ FROM node:10.9-alpine -RUN npm install +CMD [ "node", "build/bundle.js" ] diff --git a/README.md b/README.md index 91ffe8519a593e3a288bf31b1cf7faf082b39e68..d41a124426bb148a0fddfeb4b55fa8939d6cd775 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ L'API de Sigma nécessite de se connecter au LDAP Frankiz, à la fois pour obten * 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> | diff --git a/package-lock.json b/package-lock.json index 75e5fa9b5c291c5a746d1eb0ae0480326a05f9d8..fcc43b467a3c99c80f78ed0f383fa3a95a3d8035 100644 --- a/package-lock.json +++ b/package-lock.json @@ -201,6 +201,23 @@ "@types/node": "*" } }, + "@types/connect-ensure-login": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@types/connect-ensure-login/-/connect-ensure-login-0.1.4.tgz", + "integrity": "sha512-MLXOS6+5MnhkB7F34xE66wX9MEEfrUJRfNM9Uv0vEre8kH13tILO9j2b7fI4xwyLXSEn9k3uIE8U46MQ1CWByw==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/connect-flash": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/@types/connect-flash/-/connect-flash-0.0.34.tgz", + "integrity": "sha512-QC93TwnTZ0sk//bfT81o7U4GOedbOZAcgvqi0v1vJqCESC8tqIVnhzB1CHiAUBUWFjoxG5JQF0TYaNa6DMb6Ig==", + "requires": { + "@types/express": "*" + } + }, "@types/events": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", @@ -245,14 +262,15 @@ "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" }, "@types/node": { - "version": "9.4.7", - "resolved": "http://registry.npmjs.org/@types/node/-/node-9.4.7.tgz", - "integrity": "sha512-4Ba90mWNx8ddbafuyGGwjkZMigi+AWfYLSDCpovwsE63ia8w93r3oJ8PIAQc3y8U+XHcnMOHPIzNe3o438Ywcw==" + "version": "10.9.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.9.3.tgz", + "integrity": "sha512-DOzWZKUnmFYG0KUOs+9HEBju2QhBU6oM2zeluunQNt0vnJvnkHvtDNlQPZDkTrkC5pZrNx1TPqeL137zciXZMQ==" }, "@types/passport": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-0.3.5.tgz", - "integrity": "sha512-J7mdY1nnhjdbkXT84S3WsyrTtDf2KqUJ9JW3Y9vxA5GuXlejIuvwHw9A2TdNklAqPG2Q0TWqlsA2a2GIeV1jYA==", + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-0.4.6.tgz", + "integrity": "sha512-P7TxrdpAze3nvHghYPeLlHkYcFDiIkRBbp7xYz2ehX9zmi1yr/qWQMTpXsMxN5w3ESJpMzn917inK4giASaDcQ==", + "dev": true, "requires": { "@types/express": "*" } @@ -4168,14 +4186,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -4190,20 +4206,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -4320,8 +4333,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -4333,7 +4345,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4348,7 +4359,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4356,14 +4366,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -4382,7 +4390,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -4463,8 +4470,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -4476,7 +4482,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -4598,7 +4603,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -7736,6 +7740,14 @@ "version": "7.0.56", "resolved": "http://registry.npmjs.org/@types/node/-/node-7.0.56.tgz", "integrity": "sha512-NgjN3xPyqbAXSIpznNAR5Cisx5uKqJWxcS9kefzSFEX/9J7O01/FHyfnvPI7SztBf9p6c8mqOn3olZWJx3ja6g==" + }, + "@types/passport": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-0.3.5.tgz", + "integrity": "sha512-J7mdY1nnhjdbkXT84S3WsyrTtDf2KqUJ9JW3Y9vxA5GuXlejIuvwHw9A2TdNklAqPG2Q0TWqlsA2a2GIeV1jYA==", + "requires": { + "@types/express": "*" + } } } }, @@ -9715,6 +9727,19 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "ts-loader": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-4.5.0.tgz", + "integrity": "sha512-ihgVaSmgrX4crGV4n7yuoHPoCHbDzj9aepCZR9TgIx4SgJ9gdnB6xLHgUBb7bsFM/f0K6x9iXa65KY/Fu1Klkw==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^3.1.4", + "semver": "^5.0.1" + } + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -9750,6 +9775,12 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, + "typescript": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.3.tgz", + "integrity": "sha512-kk80vLW9iGtjMnIv11qyxLqZm20UklzuR2tL0QAnDIygIUIemcZMxlMWudl9OOt76H3ntVzcTiddQ1/pAAJMYg==", + "dev": true + }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", diff --git a/package.json b/package.json index bdd1bb6689c5ab89ae85bc9274d41c810e56de20..6d5a9fd574bec411594f6e88adf9576c5f38ea4f 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,10 @@ "url-loader": "^0.6.2" }, "devDependencies": { + "@types/connect-ensure-login": "^0.1.4", + "@types/connect-flash": "0.0.34", + "@types/node": "^10.9.3", + "@types/passport": "^0.4.6", "babel-eslint": "^8.2.6", "eslint": "^4.19.1", "eslint-config-standard": "^11.0.0", @@ -58,6 +62,8 @@ "eslint-plugin-standard": "^3.1.0", "jsdoc": "^3.5.5", "nodemon": "^1.18.3", + "ts-loader": "^4.5.0", + "typescript": "^3.0.3", "webpack": "^4.17.1", "webpack-cli": "^2.1.5", "webpack-node-externals": "^1.7.2" diff --git a/src/admin_view/admin.router.js b/src/admin_view/admin.router.ts similarity index 95% rename from src/admin_view/admin.router.js rename to src/admin_view/admin.router.ts index a7b8b2a4056a66bb209c1f155ffe706072b774a7..a3c0f7f75deef6a2d8781aabd4bfb7f35591dae6 100644 --- a/src/admin_view/admin.router.js +++ b/src/admin_view/admin.router.ts @@ -10,10 +10,13 @@ import { Router } from 'express'; import knex from '../../db/knex_router'; import passport from 'passport'; +import flash from 'connect-flash'; import { ensureLoggedIn } from 'connect-ensure-login'; const router = Router(); +router.use(flash()); + let port = process.env.PORT || 3000; @@ -23,9 +26,6 @@ let port = process.env.PORT || 3000; */ router.get('/', function (req, res) { - console.log("adminview: GET handler for /adminview route"); - console.log('adminview: Connecting to ' + req.url); - console.log('adminview: Trying to go to admin page...'); res.redirect('/adminview/admin'); }); @@ -47,7 +47,6 @@ router.get('/admin', // donc on laisse passer sans déclencher d'erreur 500 try { let user = req.user; - //let user = req.user; console.log('adminview: Welcome,', user.uid); userName = user.uid; } catch (err) { diff --git a/src/config_passport.js b/src/config_passport.js index f07fa2fe73a935c58ebc064721536dcf3f5bd91b..ca35df95e59b4e8b9b87e5a4937b5bd1794c1d82 100644 --- a/src/config_passport.js +++ b/src/config_passport.js @@ -17,18 +17,16 @@ */ import passport from 'passport'; import LdapStrategy from 'passport-ldapauth'; -import fs from 'fs'; -import path from 'path'; -import { config } from './ldap/config'; +import { ldapConfig } from './ldap/config'; // specifies options for 'ldapauth' strategy, to customize the behaviour of subsequent passport.authenticate('ldapauth') calls passport.use(new LdapStrategy({ server: { - url: config.ldap.server, + url: ldapConfig.ldap.server, //bindDn: '.............', //bindCredentials: '..........', - searchBase: config.ldap.searchBase, - searchFilter: config.ldap.searchFilter, + searchBase: ldapConfig.ldap.searchBase, + searchFilter: ldapConfig.ldap.searchFilter, //searchAttributes: ['givenName', 'sn'], //tlsOptions: '..........', }, diff --git a/src/index.js b/src/index.js deleted file mode 100644 index d7929d9739ea580e9c23d5eb61d7231ce4b1e46b..0000000000000000000000000000000000000000 --- a/src/index.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @file Lance le serveur configuré dans {@link server.js} - * @author manifold - */ -import app from './server'; -import colors from 'colors'; -import passport from 'passport'; - -const port = process.env.PORT || 3000; - -app.listen(port, () => { - console.log(colors.blue(`Express server listening on port ${port}.`)); -}); diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..4773230279d6960d6e51d06fb1393dc061c8191f --- /dev/null +++ b/src/index.ts @@ -0,0 +1,12 @@ +/** + * @file Lance le serveur configuré dans {@link server.ts} + * @author manifold + */ +import app from './server'; +import colors from 'colors'; + +const port = process.env.PORT || 3000; + +app.listen(port, () => { + console.log(colors.blue("Express server listening on port %s."), port); +}); diff --git a/src/ldap/config.js b/src/ldap/config.js index 1c4793a8408e4e9cb187230db6fb3eb1be92bfcc..91d253a311ebee5f62bfcbde998096d0d4db7be6 100644 --- a/src/ldap/config.js +++ b/src/ldap/config.js @@ -2,18 +2,23 @@ * @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'); - +const fs = require('fs'); +const path = require('path'); +const colors = require('colors'); // 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')); +const configPath = path.resolve('./', 'ldap_config.json'); +const credsPath = path.resolve('./', 'ldap_connexion_config.json'); +console.log(colors.cyan("Loading LDAP config file from %s"), configPath); +console.log(colors.cyan("Loading LDAP credentials from %s"), credsPath); +const ldapConfig = JSON.parse(fs.readFileSync(configPath)); +const credentialsConfig = JSON.parse(fs.readFileSync(credsPath)); // Override config server from environment if (process.env.LDAP_URI != null) { - config.ldap.server = process.env.LDAP_URI; + ldapConfig.ldap.server = process.env.LDAP_URI; } module.exports = { - config + ldapConfig, + credentialsConfig }; diff --git a/src/ldap/ldap_data.js b/src/ldap/ldap_data.js index c7c298a2e3aebc158ec148c799b8c2d1200da133..24407ef0e025c6a534826103fb48fcf591d98712 100644 --- a/src/ldap/ldap_data.js +++ b/src/ldap/ldap_data.js @@ -22,10 +22,10 @@ var path = require('path'); // Important ; permet de vérifier que l'utilisateur reste connecté. var ensureLoggedin = require('connect-ensure-login').ensureLoggedIn; -const config = require('./config').config; +const { ldapConfig, credentialsConfig } = require('./config'); // Connection au serveur LDAP avec des temps de timeout arbitraires -var client = ldap.createClient({url: config.ldap.server}); -console.log(`Connecting to LDAP at ${config.ldap.server}.`); +var client = ldap.createClient({url: ldapConfig.ldap.server}); +console.log(`Connecting to LDAP at ${ldapConfig.ldap.server}.`); //------------------------------------------------------------------------------------------------------------------------ // Fonctions de base @@ -138,7 +138,7 @@ function ajouterLDAP(user, dn, vals) { return new Promise((resolve, reject) => { connecterLDAP(user); // Ajout LDAP selon la configuration en argument - client.add(config.key_id+"="+vals[config.key_id]+","+dn, vals, function(err) { + client.add(ldapConfig.key_id+"="+vals[ldapConfig.key_id]+","+dn, vals, function(err) { reject(err); }); client.bind("", "", (err, res) => {}); @@ -192,13 +192,13 @@ function trouverGroupesModulable(input, return_attributes) { let str=ldapEscape.filter("${txt}", { txt: input}); // Construction du filtre custom - let filter= "(|("+config.key_id+"="+str+")"+ // On cherche la valeur exacte - "(|("+config.key_id+"=*"+str+")"+ // La valeur finale avec des trucs avant ; wildcard * - "(|("+config.key_id+"=*"+str+"*)"+ // La valeur du milieu avec des trucs avant et après - "("+config.key_id+"="+str+"*))))"; // La valeur du début avec des trucs après + let filter= "(|("+ldapConfig.key_id+"="+str+")"+ // On cherche la valeur exacte + "(|("+ldapConfig.key_id+"=*"+str+")"+ // La valeur finale avec des trucs avant ; wildcard * + "(|("+ldapConfig.key_id+"=*"+str+"*)"+ // La valeur du milieu avec des trucs avant et après + "("+ldapConfig.key_id+"="+str+"*))))"; // La valeur du début avec des trucs après // Appel rechercheLDAP avec filtre de l'espace - rechercherLDAP(config.dn_groups, return_attributes, filter).then(res => resolve(res)); + rechercherLDAP(ldapConfig.dn_groups, return_attributes, filter).then(res => resolve(res)); }); } @@ -237,7 +237,7 @@ function repliquerTOLModulable(data, return_attributes) { // Escape de l'input utilisateur let str=ldapEscape.filter("${input}", { input: val}); // Traduction en language LDAP - let attribute = config.user[key]; + let attribute = ldapConfig.user[key]; // Creation du filtre étape par étape filter="(&"+filter+ "(|("+attribute+"="+str+")"+ // On cherche la valeur exacte "(|("+attribute+"=*"+str+")"+ // La valeur finale avec des trucs avant ; wildcard * (MEF la wildcart ne marche pas pour tous les attributs) @@ -247,7 +247,7 @@ function repliquerTOLModulable(data, return_attributes) { } } // Appel rechercheLDAP avec filtre de l'espace - rechercherLDAP(config.dn_users, return_attributes, filter).then(res => resolve(res)); + rechercherLDAP(ldapConfig.dn_users, return_attributes, filter).then(res => resolve(res)); }); } @@ -260,7 +260,7 @@ function repliquerTOLModulable(data, return_attributes) { * @return {Promise(Object[])} Liste de dictionnaires de profils en cohérence avec l'input avec pour clés tous les attributs disponibles ou presque (voir config). */ function repliquerTOL(data) { - return repliquerTOLModulable(data, config.user.profil); + return repliquerTOLModulable(data, ldapConfig.user.profil); } /** @@ -279,7 +279,7 @@ function repliquerTOL(data) { function assurerUnicite(valeur, attribut, dn, evoluerValeur, n=0) { return new Promise((resolve, reject) => { // Recherche d'autres occurences de l'id - rechercherLDAP(dn, config.key_id, "("+attribut+"="+valeur+")").then(matches => { + rechercherLDAP(dn, ldapConfig.key_id, "("+attribut+"="+valeur+")").then(matches => { // On renvoit la valeur si elle est bien unique if (matches.length==0) { resolve(valeur); } // Sinon, on tente de nouveau notre chance avec la valeur suivante @@ -299,7 +299,7 @@ function assurerUnicite(valeur, attribut, dn, evoluerValeur, n=0) { function genererUid(givenName, lastName, promotion) { // Le filtrage évite l'injection de code dans le LDAP, le normalize et lowerCase standardisent le format return new Promise((resolve, reject) => { - assurerUnicite(ldapEscape.filter("${uid}",{uid: givenName+'.'+lastName}).toLowerCase().normalize('UFD'), config.key_id, config.dn_users, (id,n) => { + assurerUnicite(ldapEscape.filter("${uid}",{uid: givenName+'.'+lastName}).toLowerCase().normalize('UFD'), ldapConfig.key_id, ldapConfig.dn_users, (id,n) => { if (n==1) { id+='.'+ldapEscape.filter("${pr}",{pr: promotion}); } // Si prénom.nom existe déjà , on rajoute la promo else if (n==2) { id+='.'+n-1; } // Puis si prénom.nom.promo existe déjà on passe à nom.prenom.promo .1 else if (n>2) { id+=+n; } // Ensuite on continue .23, .234, etc... @@ -317,7 +317,7 @@ function genererUid(givenName, lastName, promotion) { function genererGid(name) { // Le filtrage évite l'injection de code dans le LDAP, le normalize et lowerCase standardisent le format return new Promise((resolve, reject) => { - assurerUnicite(ldapEscape.filter("${id}",{id: name}).toLowerCase().normalize('UFD'), config.key_id, config.dn_groups, (id,n) => { + assurerUnicite(ldapEscape.filter("${id}",{id: name}).toLowerCase().normalize('UFD'), ldapConfig.key_id, ldapConfig.dn_groups, (id,n) => { if (n==1) { id+='.'+n; } // Si nom existe déjà , on essaie nom.1 else if (n>1) { id+=+n; } // Ensuite on continue .12, .123, etc... return id; @@ -395,9 +395,9 @@ class UtilisateurAnonyme { * @return {Promise(string[])} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre */ listGroups(uid) { - let filtered_request = ldapEscape.filter(config.key_id + "=${id}," + config.dn_users, { id: uid }); + let filtered_request = ldapEscape.filter(ldapConfig.key_id + "=${id}," + ldapConfig.dn_users, { id: uid }); // console.log(filtered_request); - return rechercherLDAP(filtered_request, config.user.groups) + return rechercherLDAP(filtered_request, ldapConfig.user.groups) .then(res => res[0]); } @@ -408,9 +408,9 @@ class UtilisateurAnonyme { * @return {Promise(String[])} Liste des uid des membres où l'id fournie est membre (noms flat des groupes) */ listMembers(uid) { - let filtered_request = ldapEscape.filter(config.key_id + "=${id}," + config.dn_groups, { id: uid }); + let filtered_request = ldapEscape.filter(ldapConfig.key_id + "=${id}," + ldapConfig.dn_groups, { id: uid }); // console.log(filtered_request); - return rechercherLDAP(filtered_request, config.group.member) + return rechercherLDAP(filtered_request, ldapConfig.group.member) .then(res => res); } @@ -423,7 +423,7 @@ class UtilisateurAnonyme { listAdmins(gid) { return new Promise((resolve, reject) => { rechercherLDAP(ldapEscape.filter( - config.key_id+"=${id},"+config.dn_users, {id : gid}), config.group.admin).then(res => resolve(res[0]) + ldapConfig.key_id+"=${id},"+ldapConfig.dn_users, {id : gid}), ldapConfig.group.admin).then(res => resolve(res[0]) ); }); } @@ -436,7 +436,7 @@ class UtilisateurAnonyme { * voir `ldap_config.json`(..\..\ldap_config.json) pour les clés exactes. */ getUser(uid) { - return rechercherLDAP(ldapEscape.filter(config.key_id+"=${id},"+config.dn_users, {id : uid}), config.user.profil); + return rechercherLDAP(ldapEscape.filter(ldapConfig.key_id+"=${id},"+ldapConfig.dn_users, {id : uid}), ldapConfig.user.profil); } /** @@ -447,9 +447,9 @@ class UtilisateurAnonyme { * voir `ldap_config.json`(../../ldap_config.json) pour les clés exactes. */ getGroup(gid) { - let filtered_request = ldapEscape.filter(config.key_id + "=${id}," + config.dn_groups, { id: gid }); + let filtered_request = ldapEscape.filter(ldapConfig.key_id + "=${id}," + ldapConfig.dn_groups, { id: gid }); // console.log(filtered_request); - return rechercherLDAP(filtered_request, config.group.profil); + return rechercherLDAP(filtered_request, ldapConfig.group.profil); } //------------------------------------------------------------------------------------------------------------------------ @@ -466,11 +466,11 @@ class UtilisateurAnonyme { trouverGroupesParTypes(input, type) { return new Promise((resolve, reject) => { // Simple appel à la fonction précédente - trouverGroupesModulable(input, [config.key_id, config.group.type]).then(gList => { + trouverGroupesModulable(input, [ldapConfig.key_id, ldapConfig.group.type]).then(gList => { let gidtyList = []; gList.forEach(g => { // Si le groupe est du bon type on rajoute son gid - if (g[config.group.type]==type) { gidtyList.push(g[config.key_id]); } + if (g[ldapConfig.group.type]==type) { gidtyList.push(g[ldapConfig.key_id]); } }); resolve(gidtyList); }); @@ -486,7 +486,7 @@ class UtilisateurAnonyme { */ repliquerTOLdesIds(data) { return new Promise((resolve, reject) => { - repliquerTOLModulable(data, config.key_id).then(res => { + repliquerTOLModulable(data, ldapConfig.key_id).then(res => { resolve(res); }); }); @@ -529,56 +529,56 @@ class UtilisateurConnecte extends UtilisateurAnonyme { let vals = {}; // uid de base généré à partir du nom standardisé - genererGid(user, data['name']).then(id => { vals[config.group['name']]=id; }); + genererGid(user, data['name']).then(id => { vals[ldapConfig.group['name']]=id; }); // Ecriture de toutes les valeurs directement inscrites dans le LDAP (in pour input) - config.group.direct_input.forEach(key_att => vals[config.group[key_att]]=data[key_att]); + ldapConfig.group.direct_input.forEach(key_att => vals[ldapConfig.group[key_att]]=data[key_att]); // Appel à la fonction de base - ajouterLDAP(user, config.key_id+"="+vals[config.group['name']]+","+config.dn_groups, vals).then( res => { + ajouterLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.group['name']]+","+ldapConfig.dn_groups, vals).then( res => { // Certains champs nécessitent de petits calculs let vals2={}; // Sauvegarde du nom (pour le cas où gid != data['name']) - vals2[config.group["name"]]=data['name']; + vals2[ldapConfig.group["name"]]=data['name']; // ?! - vals2[config.user['password']] = ''; + vals2[ldapConfig.user['password']] = ''; // Génération id aléatoire et test contre le LDAP - genererIdNum(user, config.groups["idNumber"], config.dn_groups).then(id => { vals2[config.group['idNumber']]=id; }); + genererIdNum(user, ldapConfig.groups["idNumber"], ldapConfig.dn_groups).then(id => { vals2[ldapConfig.group['idNumber']]=id; }); // FOIREUX : Hypothèse sur la structure du reste des données mais évite un assurerUnicite à deux variables - vals2[config.group['idNumber2']]=vals2[config.group['idNumber']]; + vals2[ldapConfig.group['idNumber2']]=vals2[ldapConfig.group['idNumber']]; // Stockage machine ; dépend du prénom - vals2[config.group['directory']] = '/hosting/groups/'+vals[config.key_id]; + vals2[ldapConfig.group['directory']] = '/hosting/groups/'+vals[ldapConfig.key_id]; // Code root - vals2[config.group['cleanFullName']]=data['name'].replace(':', ';').toLowerCase().normalize('UFD'); + vals2[ldapConfig.group['cleanFullName']]=data['name'].replace(':', ';').toLowerCase().normalize('UFD'); // Adressage root - vals2[config.group['login']] = "/sbin/nologin"; + vals2[ldapConfig.group['login']] = "/sbin/nologin"; // Permissions BR - vals2[config.group['readPerm']] = '!*'; - vals2[config.group['writePerm']] = '!*'; + vals2[ldapConfig.group['readPerm']] = '!*'; + vals2[ldapConfig.group['writePerm']] = '!*'; // Inscription des valeurs calculées - modifierLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_groups, "add", vals2).then(res => { + modifierLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.key_id]+","+ldapConfig.dn_groups, "add", vals2).then(res => { if (!res) { reject(false); } }); ["posixAccount", "posixGroup", "brAccount"].forEach(cst => { let vals3={}; - vals3[config.group['class']]=cst; - modifierLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_groups, "add", vals3).then(res => { + vals3[ldapConfig.group['class']]=cst; + modifierLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.key_id]+","+ldapConfig.dn_groups, "add", vals3).then(res => { if (!res) { reject(false); } }); }); // Utilisation des fonctions adaptées pour assurer la cohérence de l'ensemble - data['members'].forEach(uid => { this.ajouterMembreGroupe(user, uid, vals[config.key_att]); }); - data['admins'].forEach(uid => { this.ajouterAdministrateurGroupe(user, uid, vals[config.key_att]); }); + data['members'].forEach(uid => { this.ajouterMembreGroupe(user, uid, vals[ldapConfig.key_att]); }); + data['admins'].forEach(uid => { this.ajouterAdministrateurGroupe(user, uid, vals[ldapConfig.key_att]); }); resolve(true); }); @@ -607,8 +607,8 @@ class UtilisateurConnecte extends UtilisateurAnonyme { this.getUser(user, uid).then(profil => { // Reecriture de profil avec les bons champs Object.keys(profil).forEach(keyLDAP => { - Object.keys(config.user).forEach(keyAlias => { - config.user[keyAlias]=keyLDAP; + Object.keys(ldapConfig.user).forEach(keyAlias => { + ldapConfig.user[keyAlias]=keyLDAP; profil[keyAlias]=profil[keyLDAP]; }); }); @@ -669,8 +669,8 @@ class AdministrateurConnecte extends UtilisateurConnecte { this.listMembers(user,gid).then(lm => { if (!lm.includes(uid)) { let vals = {}; - vals[config.groups.member] = uid; - modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "add", vals).then(res => { + vals[ldapConfig.groups.member] = uid; + modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_groups, { id: gid }), "add", vals).then(res => { // Erreur si pb lors de la modification if (!res) { reject(false); } }); @@ -679,8 +679,8 @@ class AdministrateurConnecte extends UtilisateurConnecte { }).then(res => this.listGroups(user,uid)).then( lg => { if (!lg.includes(gid)) { let vals2 = {}; - vals2[config.users.groups] = gid; - modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_users, { id: uid }), "add", vals2).then(res => { + vals2[ldapConfig.users.groups] = gid; + modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_users, { id: uid }), "add", vals2).then(res => { // Erreur si pb lors de la modification if (!res) { reject(false); } }); @@ -704,7 +704,7 @@ class AdministrateurConnecte extends UtilisateurConnecte { this.listMembers(user,gid).then(lm => { if (lm.includes(uid)) { // Supprime tous les utilisateurs - modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "del", config.group.member).then(res => { + modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_groups, { id: gid }), "del", ldapConfig.group.member).then(res => { // Les rajoute un par un, sauf pour le supprimé lm.forEach(id => { if (id!=uid) { this.ajouterMembreGroupe(user,id, gid); } @@ -715,7 +715,7 @@ class AdministrateurConnecte extends UtilisateurConnecte { // Vérifie que l'utilisateur est pas déjà viré pour users if (lg.includes(gid)) { // Supprime tous les groupes - modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_users, { id: uid }), "del", config.group.admin).then(res => { + modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_users, { id: uid }), "del", ldapConfig.group.admin).then(res => { // Les rajoute un par un, sauf pour le supprimé lg.forEach(id => { if (id!=gid) { this.ajouterMembreGroupe(user,uid, id); } @@ -744,8 +744,8 @@ class AdministrateurConnecte extends UtilisateurConnecte { if (!la.includes(uid)) { // Finalement modification, uniquement dans groups let vals = {}; - vals[config.groups.admin] = uid; - modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "add", vals).then(res => { + vals[ldapConfig.groups.admin] = uid; + modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_groups, { id: gid }), "add", vals).then(res => { // Gestion d'erreur if (!res) { reject(false); } }); @@ -772,7 +772,7 @@ class AdministrateurConnecte extends UtilisateurConnecte { this.listAdmins(user,gid).then(la => { if (la.includes(uid)) { // Supprime tous les administrateurs - modifierLDAP(user, ldapEscape(config.key_id+"=${id},"+config.dn_groups, { id: gid }), "del", config.group.admin).then(res => { + modifierLDAP(user, ldapEscape(ldapConfig.key_id+"=${id},"+ldapConfig.dn_groups, { id: gid }), "del", ldapConfig.group.admin).then(res => { // Les rajoute un par un, sauf pour le supprimé la.forEach(id => { if (id!=uid) { this.ajouterAdministrateurGroupe(user, id, gid); } @@ -801,8 +801,8 @@ class AdministrateurConnecte extends UtilisateurConnecte { this.getGroup(user, gid).then(profil => { // Reecriture de profil avec les bons champs Object.keys(profil).forEach(keyLDAP => { - Object.keys(config.group).forEach(keyAlias => { - config.group[keyAlias]=keyLDAP; + Object.keys(ldapConfig.group).forEach(keyAlias => { + ldapConfig.group[keyAlias]=keyLDAP; profil[keyAlias]=profil[keyLDAP]; }); }); @@ -835,11 +835,11 @@ class AdministrateurConnecte extends UtilisateurConnecte { // Gestion des membres et administrateurs d'abord this.getGroup(user, gid).then(profil => { // Ordre important - profil[config.group['admin']].forEach(id => { this.removeGroupAdmin(user, id, gid); }); - profil[config.group['member']].forEach(id => { this.removeGroupMember(user, id, gid); }); + profil[ldapConfig.group['admin']].forEach(id => { this.removeGroupAdmin(user, id, gid); }); + profil[ldapConfig.group['member']].forEach(id => { this.removeGroupMember(user, id, gid); }); // Elimination }).then(res => { - supprimerLDAP(user, config.key_id+"="+gid+","+config.dn_groups); + supprimerLDAP(user, ldapConfig.key_id+"="+gid+","+ldapConfig.dn_groups); }).then(res => { if (res) {resolve(true); }}); }); } @@ -886,21 +886,21 @@ class SuperAdministrateurConnecte extends AdministrateurConnecte { // uid de base généré à partir de nom et prénom, plus potentiellement promo et un offset // MEF mélange de Promise et de fonction standard - genererUid(user, data['givenName'],data['lastName'],data['promotion']).then(id => { vals[config.key_id]=id; } ); + genererUid(user, data['givenName'],data['lastName'],data['promotion']).then(id => { vals[ldapConfig.key_id]=id; } ); // Ecriture de toutes les valeurs directement inscrites dans le LDAP (in pour input) // Génère une erreur si un champ n'est pas rempli - config.user.direct_input.forEach(key_att => vals[config.user[key_att]]=data[key_att]); + ldapConfig.user.direct_input.forEach(key_att => vals[ldapConfig.user[key_att]]=data[key_att]); // Appel à la fonction de base - ajouterLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_users, vals).then( res => { + ajouterLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.key_id]+","+ldapConfig.dn_users, vals).then( res => { // Modifications multiples pour avoir plusieurs champs de même type ; boucle sur les attributs multiples (d'où mul) - config.user.muliple_input.forEach(key_att => { + ldapConfig.user.muliple_input.forEach(key_att => { // On rajoute chaque valeur en entrée data[key_att].forEach(val => { let vals2 = {}; - vals2[config.user[key_att]]=val; - modifierLDAP(user, config.key_id+"="+vals[config.key_id]+","+config.dn_users, "add", vals2).then(res => { + vals2[ldapConfig.user[key_att]]=val; + modifierLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.key_id]+","+ldapConfig.dn_users, "add", vals2).then(res => { if (!res) { reject(false); } }); }); @@ -910,51 +910,51 @@ class SuperAdministrateurConnecte extends AdministrateurConnecte { let vals3={}; // Création d'un nom complet lisible - vals3[config.user['fullName']]=data['givenName']+' '+data['lastName'].toUpperCase(); + vals3[ldapConfig.user['fullName']]=data['givenName']+' '+data['lastName'].toUpperCase(); // ?! - vals3[config.user['password']] = '{CRYPT}' + data['password']; + vals3[ldapConfig.user['password']] = '{CRYPT}' + data['password']; // Ecriture d'un surnom s'il y a lieu if ((data['nickname']!=undefined)&(data['nickname']!='')) { - vals3[config.user['nickname']]=data['nickname']; + vals3[ldapConfig.user['nickname']]=data['nickname']; } // Génération id aléatoire unique - genererIdNum(user, config.user['id'], config.dn_users).then(id => { vals3[config.user['id']]=id; }); + genererIdNum(user, ldapConfig.user['id'], ldapConfig.dn_users).then(id => { vals3[ldapConfig.user['id']]=id; }); // Stockage machine ; dépend du prénom - vals3[config.user['directory']] = '/hosting/users/' + data['givenName'][0]; + vals3[ldapConfig.user['directory']] = '/hosting/users/' + data['givenName'][0]; // Code root - vals3[config.user['cleanFullName']]=data['fullName'].replace(':', ';').toLowerCase().normalize('UFD'); + vals3[ldapConfig.user['cleanFullName']]=data['fullName'].replace(':', ';').toLowerCase().normalize('UFD'); // Adressage root - if (data['groups'].includes("on_platal")) { vals3[config.user['login']] = "/bin/bash"; } - else { vals3[config.user['login']] = "/sbin/nologin"; } + if (data['groups'].includes("on_platal")) { vals3[ldapConfig.user['login']] = "/bin/bash"; } + else { vals3[ldapConfig.user['login']] = "/sbin/nologin"; } // Permissions BR - vals3[config.user['readPerm']] = 'br.*,public.*'; - if (data['readPerm'].length>0) { vals3[config.user['readPerm']] += ',' + data['readPerm']; } - vals3[config.user['writePerm']] = 'br.*,!br.blague-du-jour,public.*,!br.campagnekes'; - if (data['writePerm'].length>0) { vals3[config.user['readPerm']] += ',' + data['writePerm']; } + vals3[ldapConfig.user['readPerm']] = 'br.*,public.*'; + if (data['readPerm'].length>0) { vals3[ldapConfig.user['readPerm']] += ',' + data['readPerm']; } + vals3[ldapConfig.user['writePerm']] = 'br.*,!br.blague-du-jour,public.*,!br.campagnekes'; + if (data['writePerm'].length>0) { vals3[ldapConfig.user['readPerm']] += ',' + data['writePerm']; } // Valeur nécessaire mais inutile - vals3[config.user['idNum']] ='5000'; + vals3[ldapConfig.user['idNum']] ='5000'; // Inscription des valeurs calculées - modifierLDAP(user, config.key_id+"="+vals[config.user['hruid']]+","+config.dn_users, "add", vals3).then(res => { + modifierLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.user['hruid']]+","+ldapConfig.dn_users, "add", vals3).then(res => { if (!res) { reject(false); } }); ["posixAccount", "shadowAccount", "inetOrgPerson", "brAccount"].forEach(cst => { let val3={}; - vals3[config.user['class']]=cst; - modifierLDAP(user, config.key_id+"="+vals[config.user['hruid']]+","+config.dn_users, "add", vals3).then(res => { + vals3[ldapConfig.user['class']]=cst; + modifierLDAP(user, ldapConfig.key_id+"="+vals[ldapConfig.user['hruid']]+","+ldapConfig.dn_users, "add", vals3).then(res => { if (!res) { reject(false); } }); }); // Utilisation des fonctions adaptées pour assurer la cohérence de l'ensemble - data['groupsIsMember'].forEach(gid => { this.ajouterMembreGroupe(user, vals[config.key_id], gid); }); - data['groupsIsAdmin'].forEach(gid => { this.ajouterAdministrateurGroupe(user, vals[config.key_id], gid); }); + data['groupsIsMember'].forEach(gid => { this.ajouterMembreGroupe(user, vals[ldapConfig.key_id], gid); }); + data['groupsIsAdmin'].forEach(gid => { this.ajouterAdministrateurGroupe(user, vals[ldapConfig.key_id], gid); }); resolve(true); }); @@ -978,13 +978,13 @@ class SuperAdministrateurConnecte extends AdministrateurConnecte { return new Promise((resolve, reject) => { // Gestion des groupes d'abord this.getUser(user, uid).then(profil => { - profil[config.user['groups']].forEach(gid => { + profil[ldapConfig.user['groups']].forEach(gid => { this.isGroupAdmin(user, uid, gid).then(res => { if (this.la.includes(res)) { this.supprimerAdministrateurGroupe(user, uid, gid); } }).then(res => { this.removeGroupMember(user, uid, gid); }); }); // Elimination - }).then(res => { supprimerLDAP(user, config.key_id+"="+uid+","+config.dn_users); }); + }).then(res => { supprimerLDAP(user, ldapConfig.key_id+"="+uid+","+ldapConfig.dn_users); }); }); } } diff --git a/src/server.js b/src/server.ts similarity index 78% rename from src/server.js rename to src/server.ts index f931c3a1e181d96ba678fbb82c15b2294baa4b73..3153aa6f0751bf17e7417b60793c5f0a63591696 100644 --- a/src/server.js +++ b/src/server.ts @@ -4,12 +4,11 @@ * La configuration inclut tout le _middleware_ définissant les API et les services * nécessaire utilisés, comme `express-session`, GraphiQL, GraphQL Voyager. * - * TODO: changer cette description... ^ - * TODD: qu'arrive-t-il aux requetes avec un cookie expire? elles ne sont traitees ni par passport.session() ni par passport.authenticate('ldapauth')... + * @todo changer cette description... ^ + * @todo qu'arrive-t-il aux requetes avec un cookie expire? elles ne sont traitees ni par passport.session() ni par passport.authenticate('ldapauth')... * * @author manifold, kadabra -*/ - + */ import express from 'express'; import bodyParser from 'body-parser'; // packages pour graphql @@ -30,10 +29,10 @@ import favicon from 'serve-favicon'; import morgan from 'morgan'; // packages pour pouvoir importer depuis des fichiers de config import path from 'path'; -import fs from 'fs'; -import './config_passport'; +import { ldapConfig, credentialsConfig } from './ldap/config'; +const { dn, passwd } = credentialsConfig; const app = express(); // "The app object conventionally denotes the Express application" (https://expressjs.com/en/4x/api.html#app) @@ -44,17 +43,6 @@ app.use(bodyParser.urlencoded({ //parses bodies of media type "application/x-www })); app.use(cookieParser()); //parses Cookie header and populate req.cookies with an object keyed by the cookie names. was necessary for express-session before its v1.5.0. on peut probablement l'enlever desormais. -//GHETTO -// Config de passport pour l'authentification ldap. -// Ne fait que *configurer* passport pour la strategie 'ldap' (pas d'incidence sur la strategie 'session' normalement) -import './config_passport.js'; - - - -/** - * @desc TRUCS DIVERS - */ - // cache le fait que l'application tourne sous Express dans le header HTTP. app.disable('x-powered-by'); // Morgan is middleware for logging requests @@ -65,40 +53,41 @@ app.use(favicon(path.resolve('./', 'assets', 'favicon.ico'))); app.use('/assets', express.static(path.resolve('./', 'assets'))); /** - * FIN TRUCS DIVERS + * @desc AUTHENTIFICATION POUR LES REQUETES POSSEDANT UN COOKIE ET PROVENANT D'UN UTILISATEUR DEJA AUTHENTIFIE + * Remarque: introduit aussi les middlewares session et passport, + * qui sont aussi utiles pour l'authentification dans les autres cas. */ - - - - /** - * @desc AUTHENTIFICATION POUR LES REQUETES POSSEDANT UN COOKIE ET PROVENANT D'UN UTILISATEUR DEJA AUTHENTIFIE - * Remarque: introduit aussi les middlewares session et passport, qui sont aussi utiles pour l'authentification dans les autres cas. + * WTF??? why is sessionSecret in ldap_config.json? it has nothing to do with ldap. + * @todo FIX */ -const configPath = path.resolve('./', 'ldap_config.json'); -const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); -// WTF??? why is sessionSecret in ldap_config.json? it has nothing to do with ldap. TODO - -// defines parameters for *session store*. (adds field req.session and do some magic stuff) -// basically, searches for a session matching the received cookie and, if found, adds field req.blasomethingbla containing serialized object representing user (i.e. similar to what passport.serializeUser() could produce) -// TODO: it is important to configure this right!!! please check out https://www.npmjs.com/package/express-session and make sure you understand the way session is stored. (en vrai c'est vraiment important...) -app.use(session({ - secret: config.sessionSecret, +/** +/* defines parameters for *session store*. (adds field req.session and do some magic stuff) + * basically, searches for a session matching the received cookie and, if found, adds field req.blasomethingbla containing serialized + * object representing user (i.e. similar to what passport.serializeUser() could produce) + * @todo do this right + * it is important to configure this right!!! please check out https://www.npmjs.com/package/express-session + * and make sure you understand the way session is stored. (en vrai c'est vraiment important...) + */ + app.use(session({ + secret: ldapConfig.sessionSecret, resave: true, saveUninitialized: false, //store: // TODO: change this. express-session doc warns that default value is ok to use for development only })); -app.use(passport.initialize()); //initialize Passport. (adds hidden field req._passport and do some magic stuff) +app.use(passport.initialize()); +//initialize Passport. (adds hidden field req._passport and do some magic stuff) //GHETTO //app.use(passport.session()); //this is equivalent to app.use(passport.authenticate('session')) +//this is equivalent to app.use(passport.authenticate('session')) app.use(passport.session(), (req, res, next)=>{ - console.log("Used passport.session()"); - console.log(`passport.session() found user: ${req.user ? req.user.uid : "none"}`); - console.log("passport.session() user is authenticated:", req.isAuthenticated()); + console.log( + `passport.session: found user: ${req.user ? req.user.uid : "none"} + authenticated: ${req.isAuthenticated()}`); next(); -}); //this is equivalent to app.use(passport.authenticate('session')) +}); // *aucun* effet sur les requetes n'ayant pas ete reconnues par app.use(session(...)) (e.g. les requetes sans cookie ou les requetes avec cookie expired). source: lecture directe du code passport/lib/strategies/session.js sur github... :/ /* @@ -108,13 +97,6 @@ app.use((req, res, next) => { }); */ -/** - * FIN AUTHENTIFICATION POUR LES REQUETES POSSEDANT UN COOKIE ET PROVENANT D'UN UTILISATEUR DEJA AUTHENTIFIE - */ - - - - /** * @desc AUTHENTIFICATION POUR LES REQUETES DE CONNEXION VIA LDAP VENANT DU FRONT @@ -122,21 +104,19 @@ app.use((req, res, next) => { * i.e. quand l'utilisateur submit le formulaire de login avec ses identifiants/mdp dans le front * Remarque: configure aussi passport pour l'authentification ldap, ce qui est aussi utile pour les requetes de connexion via ldap venant de adminview */ - -const FRONTEND_SERVER_URL = 'change this to frontend server IP address'; -const FRONTEND_SERVER_URL_LOCAL = 'http://localhost:8888'; +const FRONTEND_SERVER_URL = process.env.FRONTEND_SERVER_URL || 'http://localhost:8888'; // Options de configuration pour le _middleware_ `cors`. // CORS = Cross Origin Resource Sharing const corsOptions = { - origin: FRONTEND_SERVER_URL_LOCAL, // Configures the Access-Control-Allow-Origin CORS header. i.e. specifies that sigma-back wants to make resources accessible to this site (and this site only) + origin: FRONTEND_SERVER_URL, // Configures the Access-Control-Allow-Origin CORS header. i.e. specifies that sigma-back wants to make resources accessible to this site (and this site only) credentials: true // Configures the Access-Control-Allow-Credentials CORS header. i.e. allows cookies to be included on cross-origin requests }; app.use(cors(corsOptions)); //GHETTO // Config de passport pour l'authentification ldap. Ne fait que *configurer* passport (aucun passport.authenticate() n'est appele, par exemple) -import './config_passport.js'; +import './config_passport'; //with custom callback: //http://www.passportjs.org/docs/authenticate/#custom-callback @@ -176,8 +156,9 @@ app.post('/login', (req, res, next) => { // return next(err); // handle error? or drop request and answer with res.json()? } // If all went well - console.log("| Authentication succeeded! :-)"); - // passport.authenticate automatically includes a Set-Cookie HTTP header in the response. The JSON body is just to signal the frontend that all went well + console.log("| Authentication succeeded! :)"); + // passport.authenticate automatically includes a Set-Cookie HTTP header in + // the response. The JSON body is just to signal the frontend that all went well return res.status(200).json({ message: 'Authentication succeeded', authSucceeded: true @@ -203,16 +184,9 @@ app.post('/login', ); */ -/** - * FIN AUTHENTIFICATION POUR LES REQUETES DE CONNEXION VIA LDAP VENANT DU FRONT - */ - - /** * @desc API GRAPHQL */ - -import { dn, passwd } from "../ldap_connexion_config.json"; // default bind user const environment = process.env.NODE_ENV || 'development'; app.use('/graphql', @@ -222,9 +196,11 @@ app.use('/graphql', let password; console.log("Responding to graphql request..."); - console.log(`| User: ${req.user ? req.user.uid : "none"}`); - console.log(`| Authorization: ${req.headers.authorization}`); - console.log("| User is authenticated:",req.isAuthenticated()); + console.log(` + | User: ${req.user ? req.user.uid : "none"} + | Authorization: ${req.headers.authorization} + | Authenticated: ${req.isAuthenticated()} + `.trim()); if(req.isAuthenticated()) { console.log("graphql API is receiving a request from an authenticated user! \\o/"); @@ -240,7 +216,7 @@ app.use('/graphql', uid = dn.split("=")[1].split(",")[0]; password = passwd; } - + return { schema, graphiql: environment == 'development', // gives access to GraphiQL if req comes from browser (je crois) @@ -293,9 +269,5 @@ app.get('/*', ((req, res, next) => res.redirect('/adminview')) ); -/** - * FIN SETUP DE ADMINVIEW, L'INTERFACE ADMIN DES BDD - */ - export default app; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..6d8e02665c7c6babd9fb1aead695ed1ca929ea23 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "target": "es6", + "moduleResolution": "node", + "sourceMap": true, + "outDir": "build", + "resolveJsonModule": true, + }, + "include": [ + "src/**/*", + "db/**/*" + ] +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 47ae22d5d75574d81dfb3e76453e20a4d120b9af..33696452d9956d7e0c177f5c4b17e633bf203f7f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -3,40 +3,46 @@ const nodeExternals = require('webpack-node-externals'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const config = { - entry: './src/index.js', + entry: './src/index.ts', target: 'node', node: { __dirname: false }, - - output: { - path: path.resolve(__dirname, 'build'), - publicPath: '/assets/', - filename: 'bundle.js' - }, - - devtool: 'source-map', - - externals: [nodeExternals()], + //devtool: 'inline-source-map', + externals: [ + nodeExternals(), + { + ldapConfig: './ldap_config.json', + credentialsConfig: './ldap_connexion_config.json' + } + ], module: { rules: [{ test: /\.js$/, use: ['eslint-loader'] + },{ + test: /\.ts$/, + use: ['ts-loader'], },{ test: /\.css$/, use: ['style-loader', 'css-loader'] + }, { + type: 'javascript/auto', + test: /\.json$/, + use: ['file-loader'] },{ test: /\.(png|jpg|ico)$/, - exclude: /node_modules/, loader: 'file-loader', options: { limit: 10000 } }] }, - + resolve: { + extensions: ['.ts', '.js'] + }, plugins: [ new CopyWebpackPlugin([{ from: 'src/css', @@ -46,7 +52,13 @@ const config = { to: 'views' }] ) - ] + ], + + output: { + path: path.resolve(__dirname, 'build'), + publicPath: '/assets/', + filename: 'bundle.js' + }, }; module.exports = config; \ No newline at end of file