diff --git a/README.md b/README.md index 03e0d1e55401934f42408294a82c96a62a3caae8..fdb8639b695f30d50921a9f9f880415be9350654 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Ce dépôt contient le _backend_ de Sigma, le successeur de Frankiz, un site ét Le but des lignes qui suivent est de permettre au lecteur de rapidement mettre en place et lancer un sigma local et se familiariser avec son administration. Comment obtenir la documentation détaillée du projet est expliqué à la fin de ce document. +Pour avoir un guide détaillé de l'installation de l'environnement de dev, voir [ce carnet]() + Pour obtenir une copie du projet, cloner le dépôt par : ```bash git clone git@gitlab.binets.fr:br/sigma-backend.git @@ -16,9 +18,7 @@ git clone git@gitlab.binets.fr:br/sigma-backend.git git clone https://gitlab.binets.fr/br/sigma-backend.git ``` -## Démarrer le serveur (en mode développement) - -### Installer les dépendances *npm* +## Installer les dépendances *npm* On utilise un serveur node.js avec [express.js](https://expressjs.com/). [^server] Utiliser Node.js permet d'utiliser facilement [*npm*](https://www.npmjs.com/) (Node Package Manager). Une "dépendance" est un package utilisé dans le projet. @@ -48,7 +48,77 @@ Et une dépendance supplémentaire, PostgreSQL (linux est supposé) : sudo apt install postgresql ``` -### Setup la BDD PostgreSQL +## Configuration +L'API est conçue pour êtes modulaire et pour fonctionner dans plusieurs environnements. + +On peut donc le configurer via des fichiers ou des variables d'environnement. En deux mots : + +* [`jsdoc_config.json`](../jsdoc_config.json), [`Dockerfile`](../Dockerfile), [`.dockerignore`](../.dockerignore), [`.gitignore`](../.gitignore), [`.eslintignore`](../.eslintignore), [`webpack.config.js`](../webpack.config.js) : transparents +* [`ldap_config.json`](../ldap_config.json) : noms champs du LDAP +* [`ldap_credentials.json`](../ldap_credentials.json) : paramètres de connexion secrets au LDAP +* [`.estlintrc.json`](../.eslintrc.json) : ESLINT ou à quel point cancériser le développeur +* [`.gitattributes`](../.gitattributes) : terminaison de fichiers +* [`.gitlab-ci.yml`](../.gitlab-ci.yml) : pipeline gitlab +* [`package.json`](../package.json) et [`package-lock.json`](../package-lock.json) : gestion des dépendances usuel +* [`tsconfig.json`](../tsconfig.json) : configure la compilation de fichiers Typescript en Javascript +* [`tslint.json`](../tslint.json) : configure tslint, utilisé plutôt que tsc dans le projet final +* [`.env`](../.env) : définit les variables d'environnement et ports utilisés... + +Certains de ces fichiers de configurations ont une version "distribution" en "_dist" qui permet de les partager (le reste du temps ils sont dans le .gitignore), quitte à les renommer et à les modifier en local. + +### 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'authentification. + +* La configuration LDAP de base se situe dans [ldap_config.json](../ldap_config.json). +* Les identifiants utilisés pour authentifier le serveur au LDAP sont dans [ldap_credentials.json](../ldap_credentials.json). Ils prennent la forme suivante: +```json +{ + "dn": "uid=<username>,ou=eleves,dc=frankiz,dc=net", + "passwd": "<password>" +} +``` +On peut s'inspirer de [ldap_credentials_dist.json](../ldap_credentials_dist.json). +* Elle est importée dans l'application depuis [src/ldap/internal/config.ts](../src/ldap/internal/config.ts). +* Si la variable d'environnement `LDAP_URI` est définie, l'adresse où trouver le LDAP est remplacée. + +Le LDAP de Frankiz est sous OpenLDAP, qui a l'avantage d'être largement utilisée, documentée sur Internet, compatible avec des lecteurs génériques comme [JXplorer](http://jxplorer.org/) et gérant ses propres logs (voir [ce blog](https://www.vincentliefooghe.net/content/openldap-gestion-des-logs)). + +**Exemple** + +Si on développe en dehors du plâtal et qu'on ouvre un proxy SSH avec _port forwarding_ du LDAP de Frankiz (<frankiz.polytechnique.fr:389>) vers <localhost:8389>, on s'y connecte en définissant : `LDAP_URI=ldap://localhost:8389`, soit en faisant `export LDAP_URI=...`, soit en écrivant un fichier `.env`. Le fichier `config.js` s'occupe du reste. + +### Variables d'environnement + +| **Variable** | **Description** | **Défaut** | +| ------ | ------ | ----- | +| NODE_ENV | Type de l'environnement pour node | `development` | +| TARGET_ENV | Type de l'environnement ciblé : `development`, `staging` ou `production` | [.env](../.env) | +| LDAP_URI | URI vers le serveur LDAP. | [ldap_config.json](../ldap_config.json) | +| HOST | Addresse sur laquelle le serveur écoute des requêtes. | [index.ts](../src/index.ts) | +| DB_HOST | Addresse de la base de données. | [.env](../.env) | +| DB_PASSWD | Mot de passe de la BDD | [.env](../.env) | + +Certaines variables doivent etre définies dans un fichier `.env`. On peut se contenter de recopier [.env_dist](../.env_dist) avec `cp .env_dist .env`. + +Par ailleurs, on peut définir ces variables d'environnement, **dans l'ordre décroissant de priorité :** + +* dans sa session de terminal (équivalent à `docker run -e KEY=value`) : + ```bash + export KEY=value + ``` +* au moment de lancer l'application : + ```bash + KEY=value npm start + ``` +* dans un fichier [`.env`](https://www.npmjs.com/package/dotenv) : + ```dotenv + KEY1=value1 + KEY2=value2 + ... + ``` + + +## Setup la BDD PostgreSQL La BDD PostgreSQL est utilisée pour stocker permissions, écoles des utilisateurs, annonces et événements. Créer un rôle PostgreSQL "sigma" : @@ -63,10 +133,13 @@ Créer une base de données PostgreSQL "sigma_dev" : createdb sigma_dev -U sigma -W ``` - Si vous n'arrivez pas à vous connecter (`createdb: could not connect to database template1: FATAL: Peer authentication failed for user`) : mettre à jour votre fichier `pg_hba.conf`. - - voir https://stackoverflow.com/questions/1471571/how-to-configure-postgresql-for-the-first-time -- Si vous souhaitez utiliser d'autres noms que "sigma" et "sigma_dev" : ça ne pose pas de problème, il vous faudra simplement modifier `../db/knexfile.js` et `../db/knex_init.js`. + - `sudo nano /etc/postgresql/<version>/main/pg_hba.conf` (en tant qu'utilisateur normal) + - remplacer tous les `peer` par `md5` + - redémarrer le serveur postgres : `sudo /etc/init.d/postgresql restart` +- Si vous souhaitez utiliser d'autres noms que "sigma" et "sigma_dev" : ça ne pose pas de problème, il vous faudra simplement modifier [.env](../.env). +- Sortir de l'utilisateur `postgres` avec CTRL + d -Exécuter les *migrations* et les *seeds* de knex : +Exécuter les *migrations* et les *seeds* de knex (dans le dossier `db`) : ```bash # construire le schéma de la BDD, i.e. définir les tables et leur structure. knex migrate:latest @@ -77,7 +150,7 @@ knex seed:run Voilà , vous avez une base de données à jour ! -### Démarrer le serveur +## Démarrer le serveur Dire à webpack de build le projet (build le bundle `../build/bundle.js`) : ```bash npm run dev # en mode developpement @@ -119,77 +192,19 @@ Les plus importants sont détaillées ci-dessous : - `npm run dev` : idem, mais en mode développement - `npm run watch` : idem, mais retranspile automatiquement dès que le code est modifié. - `npm run start` : lancer un serveur Node avec nodemon +- `npm run start_prod` : lancer le serveur avec Node - `npm run doc` : générer la doc JSDoc -- `npm run lint` : vérifier la syntaxe de tous les fichiers .js et .ts du dossier src/ +- `npm run lint` : discontinué +- `npm run eslint` : vérifier la syntaxe de tous les fichiers .js du dossier src/ +- `npm run tslint` : vérifier la syntaxe de tous les fichiers .ts du dossier src/ +- `npm run tsfix` : vérifie et corrige +- `npm run tsc` : compile le code TypeScript +- `npm run test` : démarre les tests unitaires `npm run start` démarre en fait le serveur buildé [`build/bundle.js`](../build/bundle.js) avec [nodemon](https://nodemon.io/), un outil de dév qui le redémarre automatiquement après toute modification *du bundle*. Donc, lancer `npm run watch` dans un terminal et `npm run start` dans un autre permet de rebuilder **et** relancer automatiquement le serveur, après toute modification *du code source*. -## Configuration -L'API est conçue pour êtes modulaire et pour fonctionner dans plusieurs environnements. - -On peut donc le configurer via des fichiers ou des variables d'environnement. En deux mots : - -* [`jsdoc_config.json`](../jsdoc_config.json), [`Dockerfile`](../Dockerfile), [`.dockerignore`](../.dockerignore), [`.gitignore`](../.gitignore), [`.eslintignore`](../.eslintignore), [`webpack.config.js`](../webpack.config.js) : transparents -* [`ldap_config.json`](../ldap_config.json) : noms champs du LDAP -* [`ldap_credentials.json`](../ldap_credentials.json) : paramètres de connexion secrets au LDAP -* [`.estlintrc.json`](../.eslintrc.json) : ESLINT ou à quel point cancériser le développeur -* [`.gitattributes`](../.gitattributes) : terminaison de fichiers -* [`.gitlab-ci.yml`](../.gitlab-ci.yml) : pipeline gitlab -* [`package.json`](../package.json) et [`package-lock.json`](../package-lock.json) : gestion des dépendances usuel -* [`tsconfig.json`](../tsconfig.json) : configure la compilation de fichiers Typescript en Javascript -* [`tslint.json`](../tslint.json) : configure tslint, utilisé plutôt que tsc dans le projet final -* [`.env`](../.env) : définit les variables d'environnement et ports utilisés... - -Certains de ces fichiers de configurations ont une version "distribution" en "_dist" qui permet de les partager (le reste du temps ils sont dans le .gitignore), quitte à les renommer et à les modifier en local. - -### 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'authentification. - -* La configuration LDAP de base se situe dans [ldap_config.json](../ldap_config.json). -* Les identifiants utilisés que authentifier le serveur au LDAP sont dans [ldap_credentials.json](../ldap_credentials.json). Ils prennent la forme suivante: -```json -{ - "dn": "uid=<username>,ou=eleves,dc=frankiz,dc=net", - "passwd": "<password>" -} -``` -* Elle est importée dans l'application depuis [src/ldap/internal/config.ts](../src/ldap/internal/config.ts). -* Si la variable d'environnement `LDAP_URI` est définie, l'adresse où trouver le LDAP est remplacée. - -Le LDAP de Frankiz est sous OpenLDAP, qui a l'avantage d'être largement utilisée, documentée sur Internet, compatible avec des lecteurs génériques comme [JXplorer](http://jxplorer.org/) et gérant ses propres logs (voir [ce blog](https://www.vincentliefooghe.net/content/openldap-gestion-des-logs)). - -**Exemple** - -Si on développe en dehors du plâtal et qu'on ouvre un proxy SSH avec _port forwarding_ du LDAP de Frankiz (<frankiz.polytechnique.fr:389>) vers <localhost:8389>, on s'y connecte en définissant : `LDAP_URI=ldap://localhost:8389`, soit en faisant `export LDAP_URI=...`, soit en écrivant un fichier `.env`. Le fichier `config.js` s'occupe du reste. - -### Variables d'environnement - -| **Variable** | **Description** | **Défaut** (`ldap_config.json`) | -| ------ | ------ | ----- | -| LDAP_URI | URI vers le serveur LDAP. | <ldap://frankiz.eleves.polytechnique.fr:389> | -| TARGET_ENV | Type de l'environnement ciblé : `development`, `staging` ou `production` | `development` | -| HOST | Addresse sur laquelle le serveur écoute des requêtes. | `localhost` en développement, `0.0.0.0` en staging/prod. | -| DB_HOST | Addresse de la base de données. | `localhost` ou `129.104.201.10` en staging/prod. | -| DB_PASSWD | Mot de passe de la BDD | `password` | - -On peut définir ces variables d'environnement, **dans l'ordre décroissant de priorité :** - -* dans sa session de terminal (équivalent à `docker run -e KEY=value`) : - ```bash - export KEY=value - ``` -* au moment de lancer l'application : - ```bash - KEY=value npm start - ``` -* dans un fichier [`.env`](https://www.npmjs.com/package/dotenv) : - ```dotenv - KEY1=value1 - KEY2=value2 - ... - ``` ## Panneau d'administration Il est accessible par navigateur au path [/adminview/admin](localhost:3000/adminview/admin) ; n'importe quel path devrait rediriger dessus. diff --git a/assets/LDAPUseCase.PNG b/assets/LDAPUseCase.PNG new file mode 100644 index 0000000000000000000000000000000000000000..6aae00183835ea38cf8255669f30f7450fd0ef5b Binary files /dev/null and b/assets/LDAPUseCase.PNG differ diff --git a/assets/LDAPUser.png b/assets/LDAPUser.png index 22c1c72af141116f60a473be51e06aabef17b2ae..69296169c96a45c9edd7c76be9d625fb341e14e6 100644 Binary files a/assets/LDAPUser.png and b/assets/LDAPUser.png differ diff --git a/ldap_config.json b/ldap_config.json index 25387b937da0d19bbf9a73cde198bcb28f5a6fd2..ba56ad7d85030d2c3f9098bdd84dd5e40f25b067 100644 --- a/ldap_config.json +++ b/ldap_config.json @@ -37,7 +37,7 @@ "members": "memberOf", "followers": "followerOf" }, - "comment_4": "Placeholders et indications de contenu de certains champs du LDAP généré par frankiz pour les groupes", + "comment_4": "Placeholders et indications de contenu de certains champs du LDAP généré par frankiz pour les groupes (childs TBA)", "group": { "gid": "cn", "name": "sn", diff --git a/notes/CONTRIBUTING.md b/notes/CONTRIBUTING.md index c61002fed3ae236348023c56a0a65f9e51acada4..923559e92327de6314157ebba9f02e3560fa42ec 100644 --- a/notes/CONTRIBUTING.md +++ b/notes/CONTRIBUTING.md @@ -1,3 +1,6 @@ +Le projet sigma +=== + Ceci est la documentation haut-niveau de sigma, décrivant le projet du point de vue développeur de façon globale, sans trop rentrer dans le détail du code. ## Pourquoi Sigma ? @@ -15,9 +18,10 @@ Ainsi, l'idée est de conserver le LDAP Frankiz mais pas sa BDD, inutilisable ca ### L'idée Il s'agit de reprendre un nouveau Frankiz plus moderne et clairement documenté, mais pas seulement. Plusieurs fonctionnalités intéressantes sont envisageables : -- gestion des inscriptions (notamment avec nombre de places limité), -- inscription par trigramme, -- minimodules ou des greffons à étudier +- fil d'actualité avec filtre personnalisable +- gestion des inscriptions (notamment avec nombre de places limité) +- inscription par trigramme +- minimodules ou greffons à étudier - intégration des événements d'autres écoles ## Description et actualité des branches @@ -61,13 +65,9 @@ Certaines anciennes branches, fraîchement mergées, sont décrites ci-dessous. - branche sur laquelle akka vodol fait tout son travail : implémentation des resolvers pour le nouveau schéma propre (le schéma "_wish_list"). Comme ça, il peut faire d'éventuelles modifications du schéma sans faire chier les autres, et ensuite on valide ensemble pour merge. -#### LDAP-refacto - -Branche obsolète à supprimer. - #### unit-tests -- TODO (@akka vodol tu peux expliquer ici a quoi sert cette branche ? et le cas échéant, la merge dans master ?) +- branche de test-unitaires ## Structure du dossier @@ -259,4 +259,4 @@ Le BR dispose de plusieurs Virtual Machines (VM) pour faire tourner les outils e Le BR 2016, plus particulièrement Wilson Jallet, Guillaume Wang, Quentin Chevalier et Anatole Romon -Le BR 2017, plus particulièrement Olivér Facklam, Grégoire Grzeckowicz et Hadrien Renaud +Le BR 2017, plus particulièrement Olivér Facklam, Grégoire Grzeckowicz et Hadrien Renaud \ No newline at end of file diff --git a/notes/hist_graphql.json b/notes/hist_graphql.json new file mode 100644 index 0000000000000000000000000000000000000000..17834f602fbd2873a6c2c8b66454aaacee9cbb5d --- /dev/null +++ b/notes/hist_graphql.json @@ -0,0 +1,4 @@ +{ + "title": "Historique GraphQL, ou comment gérer les relations de couple entre front et back-end", + "children": [] +} \ No newline at end of file diff --git a/notes/memo_sigma_graphql.md b/notes/hist_graphql.md similarity index 97% rename from notes/memo_sigma_graphql.md rename to notes/hist_graphql.md index d3366e0b9fd04b49a4f2128f7b8a861708140d78..f23b5ba184fe1ab4b4f54a1a85f211df05deac9b 100644 --- a/notes/memo_sigma_graphql.md +++ b/notes/hist_graphql.md @@ -1,11 +1,8 @@ -Implémentation du schéma et des resolvers GraphQL sur sigma-backend -=== - Remarques sur *l'implémentation*, explication de choix de design... Pour des commentaires sur la définition du schéma, se reporter plutôt aux commentaires en en-tête des fichiers `actions.graphql` et `objects.graphql`. -Pour des explications plus high-level sur la gestion des droits et les authorizations sur Sigma, voir le memo idoine (`memo_sigma_rights.md`). +Pour des explications plus high-level sur la gestion des droits et les authorizations sur Sigma, voir le memo idoine {@tutorial hist_rights}. ## Structure du dossier `src/graphql` diff --git a/notes/hist_ldap.md b/notes/hist_ldap.md index 1bf9dc3867b79438fbb31d1a3d819431cb187e1e..f1e0d4a95bb2bbf38e09f074e543f6ac159d60c9 100644 --- a/notes/hist_ldap.md +++ b/notes/hist_ldap.md @@ -1,6 +1,9 @@ +Le LDAP, sa vie, son oeuvre +=== + ## Sur le LDAP Frankiz -A l'origine Frankiz, le prédécesseur de sigma, avait sa propre base de données qu'il importait toutes les 3h dans un LDAP énorme et sale, qui contenaiit le strict minimum. Ce LDAP s'est révélé très utile à différents sites binets qui ont fait un usage très libre de cette ressource. +A l'origine Frankiz, le prédécesseur de sigma, avait sa propre base de données qu'il importait toutes les 3h dans un LDAP énorme et sale, qui contenait le strict minimum. Ce LDAP s'est révélé très utile à différents sites binets qui ont fait un usage très libre de cette ressource. De sorte que quand il fallut remplacer Frankiz, la destruction du LDAP n'était pas possible sans revoir plusieurs sites binets (à voir, le CAS était peut-être une solution suffisante). On a donc choisi de tuer la BDD Frankiz, mais seulement après avoir considérablement enrichi le LDAP pour en faire la BDD utilisateurs et groupes principale de sigma. @@ -8,26 +11,32 @@ Une documentation vieillissante est disponible sur le [`wikix`](https://wikibr.b Le BR2017 a mené un gros travail de réorganisation du LDAP donc beaucoup d'informations sur le wikix ne seront plus valides. -### Idée de nouvelle organisation du LDAP +### Nouvelle organisation du LDAP Le LDAP a été significativement enrichi depuis Frankiz, puisqu'il contient la majeure partie des données utilisateurs et groupes de sigma. Les champs parent et child permettent aux resolvers afférents de faire descendre les admins et remonter les membres, mais n'a pas d'influence à l'intérieur de l'API LDAP.  - + + + + +#### Configuration + +L'équivalence pratique entre champs du LDAP et champs du code est dans le fichier de configuration [`ldap_config`](../ldap_config.json). Idéalement, ce .json serait ensuite porté en une calsse dynamique dans le code. En atendant une structure pareille, on se contentera des structures de données décrites dans [`config`](../src/ldap/internal/config.ts). -L'équivalence pratique entre champs du LDAP et champs du code est dans le fichier de configuration [`ldap_config`](../ldap_config.json). +#### Une structure particulière -En pratique, Sigma n'utilise pas l'arbre utilisateurs pour déterminer les groupes d'un utilisateur. On préfère faire à chaque fois une requête sur l'arbre groupes. Cela permet de gérer plus finement des questions d'héritage. +Les admins et membres sont de deux types ; les admins et membres stricts, acceptés par un administrateur dans le groupe, et les admins et membres hérités, qui ont rejoint ce groupe en remontant ou en descendant la structure de parenté ; voir {@tutorial hist_rights}. ### Etat de l'API -Cette API est voulue comme la plus simple et la plus minimaliste possible ; en effet, elle sera à réimplémenter sur toutes les instances différentes de sigma pour s'adapter aux structures de données des différentes écoles. On peut administrer des groupes depuis sigma, mais pour s'interfacer d'instances à instances seules deux fonctions sont indispensables ; peek et search. +Cette API est voulue comme la plus simple et la plus minimaliste possible ; en effet, elle sera à réimplémenter sur toutes les instances différentes de sigma pour s'adapter aux structures de données des différentes écoles qui choisissent d'adopter sigma. On peut administrer des groupes depuis sigma, mais pour s'interfacer d'instances à instances seules deux fonctions sont indispensables ; peek et search. -Cette API est naïve et ne gère pas de problème de récursion. +Cette API, bien que relativement naïve, doit être capable de garder la syn,chronisation entre les deux arbres du LDAP et ainsi que les problèmes de récursion posées par le choix de la structure en admin descendant et membres montant.  Le détail de chaque fonction est disponible dans la documentation JSDOC : ([`User`](../doc/LDAP.User.html) et [`Group`](../doc/LDAP.Group.html)). -La lutet contre les injections est faite au plus bas niveau possible en utilisant [`ldapEscape`](https://www.npmjs.com/package/ldap-escape) directement dans la classe [`Basics`](../doc/LDAP.Basics.html). En effet, les injections LDAP sont relativement voyantes et ne peuvent pas se faire avec des caractères usuels. \ No newline at end of file +La lutte contre les injections est faite au plus bas niveau possible en utilisant [`ldapEscape`](https://www.npmjs.com/package/ldap-escape) directement dans la classe [`Basics`](../doc/LDAP.Basics.html). En effet, les injections LDAP sont relativement voyantes et ne peuvent pas se faire avec des caractères usuels. \ No newline at end of file diff --git a/notes/memo_jsdoc.json b/notes/memo_jsdoc.json index fc059053cd902176e1fa0a1e40aa52282e034375..0aefcd8dc1bcd6a07381c95944b4ac886d6b95fa 100644 --- a/notes/memo_jsdoc.json +++ b/notes/memo_jsdoc.json @@ -1,4 +1,4 @@ { - "title": "Memo JSDoc", + "title": "Memo JSDoc, le meilleur ami du newbie", "children": [] } \ No newline at end of file diff --git a/notes/memo_jsdoc.md b/notes/memo_jsdoc.md index 547eadb3011566674f921674e1e9946a0033aab0..e9ac628c289d2a2faa567fb9a017025a3e5e7ae8 100644 --- a/notes/memo_jsdoc.md +++ b/notes/memo_jsdoc.md @@ -1,4 +1,4 @@ -JSDoc, c'est l'outil de génération automatique de documentation. Il transforme des commentaires et des fichiers Markdown comme celui-ci en une masse de pages web lisibles même par un autiste semi-aveugle à quiil manquerait un module de sémantique. +JSDoc, c'est l'outil de génération automatique de documentation. Il transforme des commentaires et des fichiers Markdown comme celui-ci en une masse de pages web lisibles même par un autiste semi-aveugle à qui il manquerait un module de sémantique. La doc de JSDoc, paradoxalement un peu aride : [`Use JSDoc`](http://usejsdoc.org/) @@ -41,4 +41,6 @@ La factorisation de code dans des classes étant en soit une bonne pratique et p ### Les fichiers. md -JSDoc a deux façons simples d'intégrer des fichiers Mardown dans la doc ; un README en page d'accueil, ou un tutoriel comme celui-ci. Tous les tutoriels doivent être mis dans le même dossier avec des fichiers de config .json pour définir une arborescence de tutoriels propres. \ No newline at end of file +JSDoc a deux façons simples d'intégrer des fichiers Mardown dans la doc ; un README en page d'accueil, ou un tutoriel comme celui-ci. Tous les tutoriels doivent être mis dans le même dossier avec des fichiers de config .json pour définir une arborescence de tutoriels propres. + +N'hésitez pas à enrichir la documentation à votre tour, par des fichiers .md ou directement dans votre code ! \ No newline at end of file diff --git a/notes/memo_knexjs.json b/notes/memo_knexjs.json index 887d74bb75b48c0b7860316a35d9489ce39a1f51..e375581b497e4a0f1d9e1d528fc69d714ead8991 100644 --- a/notes/memo_knexjs.json +++ b/notes/memo_knexjs.json @@ -1,4 +1,4 @@ { - "title": "Memo knew.js", + "title": "Memo knew.js ou quand on a la felmme de faire du SQL", "children": [] } \ No newline at end of file diff --git a/notes/memo_knexjs.md b/notes/memo_knexjs.md index d15ec00acf6ad5658382b9eb1c9f3c8a700d0d26..cff213567e7bfb11d394a331402f9c69a68eb8b4 100644 --- a/notes/memo_knexjs.md +++ b/notes/memo_knexjs.md @@ -72,4 +72,4 @@ Solution : spécifier dans le schéma (fichiers migrations) ce qu'il faut faire On a défini les migrations (`./db/migrations/*`) en se basant sur le schéma GraphQL (`typeDefs.js`) (et pas l'inverse), ce qui se voit bien puisqu'on suit presque exactement ce dernier. **[spécifique à shitpost :]** -Un point particulier cependant : comme expliqué en commentaires du migration-file `./db/migrations/[timestamp]_create_comments.js`, on n'a pas déclaré le champ "forMessage" de la table "comments" comme ayant "messages.id" comme foreign key, car ce n'est pas possible avec PostgreSQL v10. +Un point particulier cependant : comme expliqué en commentaires du migration-file `./db/migrations/[timestamp]_create_comments.js`, on n'a pas déclaré le champ "forMessage" de la table "comments" comme ayant "messages.id" comme foreign key, car ce n'est pas possible avec PostgreSQL v10. \ No newline at end of file diff --git a/notes/memo_ldap.json b/notes/memo_ldap.json index e36839dfd17d86106cfb15eee97e1c1eb52c7e9e..a0627ac10cb6d0878bbc835eaaccbc1780875725 100644 --- a/notes/memo_ldap.json +++ b/notes/memo_ldap.json @@ -1,4 +1,4 @@ { - "title": "Memo LDAP", + "title": "Memo LDAP, ni BDD ni annuaire", "children": [] } \ No newline at end of file diff --git a/notes/memo_ldap.md b/notes/memo_ldap.md index 98d6b140e67dc674f8271e52a192674ba5bc4065..8d5179bebed5c8fe3af2965b948f90e4ae93d31b 100644 --- a/notes/memo_ldap.md +++ b/notes/memo_ldap.md @@ -6,12 +6,16 @@ Il s'agit d'une structure particulièrement rigide mais efficace en lecture. Cha La technologie est ancienne et bien connue. Le LDAP de Frankiz, OpenLDAP, contient beaucoup de fonctionnalités sympathique comme le hashage inclus des mots de passe avec salt conformément à l'état de l'art. -## Un wrapper sympathique +### Un wrapper sympathique... On accède sur un LDAP par des requêtes LDAP, d'où l'intérêt d'une bibliothèque comme [`ldap.js`](http://ldapjs.org/) qui fait office de traducteur javascript/LDAP, un peu comme knex et SQL. On s'intéressera particulièrement à la partie [`client`](http://ldapjs.org/client.html) qui est celle qui permet d'agir sur le LDAP. Cette bibliothèque est reprise et re-wrappée dans la classe [`Basics`](../src/ldap/internal/basics.ts). -## Une interface graphique agréable +### Pas complètement dépourvu de dangers ! -Pour explorer un LDAP, vous pouvez utiliser [`JXplorer`](http://jxplorer.org/). Il s'agit d'un logiciel OpenSource en Java très iparfait mais qui permet de rapidement parcourir les champs d'un LDAP et de mener des petites recherches dessus. \ No newline at end of file +Comme tous les protocoles, LDAP a ses failles. En particulier, il est possible d'injecter des commandes via un nom de domaine (Domain Name ou DN) ou un filtre (filter). Ces dangers sont adressés par sigma en utilisant la bibliothèque [`ldap-escape`](https://www.npmjs.com/package/ldap-escape). + +### Une interface graphique agréable + +Pour explorer un LDAP, vous pouvez utiliser [`JXplorer`](http://jxplorer.org/). Il s'agit d'un logiciel OpenSource en Java très imparfait mais qui permet de rapidement parcourir les champs d'un LDAP et de mener des petites recherches dessus. \ No newline at end of file diff --git a/notes/memo_postgresql.json b/notes/memo_postgresql.json index 5854303fa10a833546c5fe97ea09c1a1805ddb0b..7634a09c2fdd835ffeabd0d6677adeb6b3ae653b 100644 --- a/notes/memo_postgresql.json +++ b/notes/memo_postgresql.json @@ -1,4 +1,4 @@ { - "title": "Memo PostgreSQL", + "title": "Memo PostgreSQL, ou une technologie de base de données simple", "children": [] } \ No newline at end of file diff --git a/notes/memo_sigma_graphql.json b/notes/memo_sigma_graphql.json deleted file mode 100644 index 5b943b170fc6121e140cd16247ab654a6f4bcd7c..0000000000000000000000000000000000000000 --- a/notes/memo_sigma_graphql.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Memo GraphQL", - "children": [] -} \ No newline at end of file diff --git a/notes/memos.json b/notes/memos.json index be3440d13677639a451516f67b7ff8eca337de67..f3f6c53dc26df0dba9ce0e4aba2fafd2a5403eb2 100644 --- a/notes/memos.json +++ b/notes/memos.json @@ -3,7 +3,6 @@ "children": [ "memo_knexjs", "memo_postgresql", - "memo_sigma_graphql", "memo_jsdoc", "memo_ldap" ] diff --git a/src/ldap/export/group.ts b/src/ldap/export/group.ts index 7f1fb5803b3df1038a3c2ad194dc667ee55fcd7e..ff487f8cacce0196767c5680d7a02f1f66b86580 100644 --- a/src/ldap/export/group.ts +++ b/src/ldap/export/group.ts @@ -6,7 +6,6 @@ import { ldapConfig, groupData, categories } from '../internal/config'; import {Basics} from '../internal/basics'; import {Tools} from '../internal/tools'; -import ldapEscape from 'ldap-escape'; //------------------------------------------------------------------------------------------------------------------------ // Classes à exporter TBT @@ -36,9 +35,7 @@ export class Group { try { let data = await Tools.peek<groupData>("group", gid, groupData); // Extraction des uid de membres - for (let cat of categories) data[cat] = data[cat].map(dirtyUid => dirtyUid.split(',')[0].split('=')[1]); - data.parents = data.parents.map(dirtyGid => dirtyGid.split(',')[0].split('=')[1]) - //console.log("Found " + data.gid); + for (let cat of categories.concat(["parents"])) data[cat] = data[cat].map(dirtyId => dirtyId.split(',')[0].split('=')[1]); return data; } catch(err) { @@ -222,8 +219,7 @@ export class Group { vals3[ldapConfig.group['classes']]=cst; Basics.change("group", gid, "add", vals3).then(res => { if (!res) throw "Erreur lors de l'ajout des valeurs constantes du nouveau groupe."; - }); - }); + }); }); // Ajout groupes parents et fils for (let rel of ["childs","parents"]) { @@ -258,27 +254,7 @@ export class Group { try { // Gestion des catégories en bloc d'abord let profile = await Group.peek(gid); - for (let cat of categories) { - profile[ldapConfig.group[cat]].forEach(async function quickPartRemUser(uid: string) { - // Modification des profils de tous les utilisateurs - let lg = await Tools.get(uid, "user", cat); - // Vérifie que l'utilisateur est pas déjà viré pour users - if (lg.includes(gid)) { - // Supprime tous les groupes - if (!await Basics.change("user", uid, "del", ldapConfig.user[cat])) { - throw "Erreur lors de la suppression de tous les groupes du membre."; - } - // Les rajoute un par un, sauf pour le groupe supprimé - lg.forEach(id => { - if (id!=gid) { - Tools.add(uid, id, cat).then(res => { - if (!res) throw "Erreur lors du ré-ajout des autres groupes"; - }); - } - }); - } - }); - } + for (let cat of categories) profile[ldapConfig.group[cat]].forEach(uid => Tools.remove(uid, gid, cat)); // Elimination if (!await Basics.clear("group",gid)) throw "Erreur lors de la suppression de la feuille dans l'arbre des groupes."; return true; diff --git a/src/ldap/export/user.ts b/src/ldap/export/user.ts index 50eb6c11bd4d64b2aa59f29e60baadedcf10bce7..a9433e28e3243a33c423ae037d073e14e61f373b 100644 --- a/src/ldap/export/user.ts +++ b/src/ldap/export/user.ts @@ -6,7 +6,6 @@ import { ldapConfig, userData, categories } from '../internal/config'; import {Basics} from '../internal/basics'; import {Tools} from '../internal/tools'; -import ldapEscape from 'ldap-escape'; //------------------------------------------------------------------------------------------------------------------------ // Classes à exporter TBT @@ -34,13 +33,7 @@ export class User { */ static async peek(uid: string) : Promise<userData> { try { - let data : userData = await Tools.peek<userData>("user", uid, userData); - // Reconstruction des groupes dont un utilisateur est membre - for (let cat of categories) { - let dn = ldapConfig.user.uid + "=" + ldapEscape.filter("${txt}", { txt: uid }) + "," + ldapConfig.dn.user; - data[cat] = await Basics.searchSingle("group", ldapConfig.group.gid, null, ldapConfig.group[cat] + "=" + dn); - } - return data; + return await Tools.peek<userData>("user", uid, userData); } catch(err) { throw "Error while peeking a user."; @@ -132,17 +125,6 @@ export class User { }); }); - function DFS(uid, gid, cat) { - let to_visit = [gid]; - let tmp = ldapConfig.user[cat]; - while (to_visit.length > 0) { - let cur_gid = to_visit.pop(); - Basics.change("user", uid, "add", { tmp: cur_gid}); - if (cat == "admins") var rel = "childs"; - to_visit.concat(Basics.searchSingle("group", ldapConfig.group[rel], cur_gid)); - } - } - // Ajout dans les groupes à la catégorie voulue for (let cat of categories) { for (let gid of data[cat]) Tools.add(uid, gid, cat).then(res => { @@ -168,33 +150,14 @@ export class User { */ static async delete(uid: string): Promise<boolean> { try { - // Gestion des groupes d'abord + // Gestion des groupes de l'utilisateur d'abord let profil = await User.peek(uid); - for (let cat of categories) { - profil[ldapConfig.user[cat]].forEach(async function (gid: string) { - // Enlever de la liste des membres - let lm = await Tools.get(gid, "group", cat); - if (lm.includes(uid)) { - // Supprime tous les membres - if (!await Basics.change("group", gid, "del", ldapConfig.group[cat])) { - throw "Erreur lors de la suppression de tous les membres du groupe."; - } - // Les rajoute un par un, sauf pour le supprimé - lm.forEach(id => { - if (id!=uid) { - Tools.add(id, gid, cat).then(res => { - if (!res) throw "Erreur lors du ré-ajout d'un autre membre"; - }); - } - }); - } - }); - } + for (let cat of categories) profil[ldapConfig.user[cat]].forEach(gid => Tools.remove(uid, gid, cat)); } catch(err) { throw "Erreur lors de l'obtention des informations de l'utilisateur à supprimer."; } - // Elimination + // Elimination pure et simple if (!Basics.clear("user", uid)) throw "Erreur lors de la suppression de l'utilisateur."; return true; } diff --git a/src/ldap/internal/config.ts b/src/ldap/internal/config.ts index df6f6f5e97f005fadd9b9ae7d60e5b7f700fcb43..4032ac36feb6f1098256ed3989af1fad01ebfb2d 100644 --- a/src/ldap/internal/config.ts +++ b/src/ldap/internal/config.ts @@ -39,16 +39,16 @@ export const categories = ["admins","speakers","members","followers"]; /** * @class partUserData * @desc Interface avec les données visibles au mponde extérieur. - * @var {string?} uid - Identifiant utilisateur - * @var {string?} givenName - Prénom - * @var {string?} lastName - Nom + * @var {string} uid - Identifiant utilisateur + * @var {string} givenName - Prénom + * @var {string} lastName - Nom * @var {string?} gender - Sexe * @var {string?} photo - Bytestring de la photo de l'utilisateur * @var {string?} address - Adresse(s) - * @var {string[]?} admins - Liste des gid (group id, inclus section sportive, binet, PA...) dont l'utilisateur est admin ; pas forcément sous-liste de members - * @var {string[]?} speakers - Liste des gid dont l'utilisateur est porte-parole ; pas forcément sous-liste de members - * @var {string[]?} members - Liste des gid dont l'utilisateur est membre - * @var {string[]?} followers - Liste des gid dont l'utilisateur est sympathisant + * @var {string[]} admins - Liste des gid (group id, inclus section sportive, binet, PA...) dont l'utilisateur est admin ; pas forcément sous-liste de members + * @var {string[]} speakers - Liste des gid dont l'utilisateur est porte-parole ; pas forcément sous-liste de members + * @var {string[]} members - Liste des gid dont l'utilisateur est membre + * @var {string[]} followers - Liste des gid dont l'utilisateur est sympathisant * @memberof LDAP */ export class partUserData { @@ -58,10 +58,10 @@ export class partUserData { gender?: 'M'|'F'|'U'; photo?: string; address?: string; - admins?: string[]; - speakers?: string[]; - members?: string[]; - followers?: string[]; + admins: string[] = []; + speakers: string[] = []; + members: string[] = []; + followers: string[] = []; } /** @@ -71,8 +71,8 @@ export class partUserData { * @var {string?} nickname - Surnom * @var {string?} phone - Numéro(s) de téléphone * @var {string?} mail - Adresse(s) courriel - * @var {string?} birthdate - Date d'anniversaire - * @var {string?} nationality - Nationalité d'origine + * @var {string} birthdate - Date d'anniversaire + * @var {string} nationality - Nationalité d'origine * @memberof LDAP */ export class userData extends partUserData { @@ -87,13 +87,14 @@ export class userData extends partUserData { /** * @class groupData * @var {string} gid - Identifiant du groupe - * @var {string} password - Mot de passe du groupe + * @var {string?} password - Mot de passe du groupe * @var {string} name - Nom du groupe (souvent son nom mais pas nécessairement) - * @var {string} logo - Logo du groupe (en bytestring) - * @var {string} description - Description du groupe (script Markdown) - * @var {string} site - Site web du groupe (URL) + * @var {string?} logo - Logo du groupe (en bytestring) + * @var {string?} description - Description du groupe (script Markdown) + * @var {string?} site - Site web du groupe (URL) * @var {string} category - Statut du groupe ; binet, section sportive... (actuellement juste 'binet' ou 'free') * @var {string[]} parents - Liste des groupes directement parents de celui-ci + * @var {string[]} childs - Liste des groupes directement enfants de celui-ci * @var {string[]} admins - Liste des admins du groupe * @var {string[]} speakers - Liste des porte-parole du groupe * @var {string[]} members - Liste des membres du groupe @@ -109,6 +110,7 @@ export class groupData { site?: string; category: string; parents: string[] = []; + //childs: string[] = []; admins: string[] = []; speakers: string[] = []; members: string[] = []; diff --git a/src/ldap/internal/tools.ts b/src/ldap/internal/tools.ts index 8ed411ee0b4a279930069613831d5ea9c9535649..b75953f3a67f45207b95f5b3b580577dee524330 100644 --- a/src/ldap/internal/tools.ts +++ b/src/ldap/internal/tools.ts @@ -236,9 +236,7 @@ export class Tools { let catName = ldapConfig.group[category]; if (lu.includes(uid)) { // Supprime tous les utilisateurs - if (!await Basics.change("group", gid, "del", catName)) { - throw "Erreur lors de la suppression de tous les membres d'une catégorie du groupe."; - } + if (!await Basics.change("group", gid, "del", catName)) throw "Erreur lors de la suppression de tous les membres d'une catégorie du groupe."; // Les rajoute un par un, sauf pour le supprimé lu.forEach(id => { if (id!=uid) { @@ -258,9 +256,7 @@ export class Tools { let catName = ldapConfig.user[category]; if (lg.includes(gid)) { // Supprime tous les groupes de la catégorie pour l'utilisateur - if (!await Basics.change("user", uid, "del", catName)) { - throw "Erreur lors de la suppression de tous les groupes d'un membre."; - } + if (!await Basics.change("user", uid, "del", catName)) throw "Erreur lors de la suppression de tous les groupes d'un membre."; // Les rajoute un par un, sauf pour le supprimé lg.forEach(id => { if (id!=gid) { @@ -304,9 +300,7 @@ export class Tools { if (category == "members") { let spk = ldapConfig.group.speakers; let lg = await Tools.get(uid, "user", "speakers"); - if (!await Basics.change("user", uid, "del", spk)) { - throw "Erreur lors de la suppression de tous les groupes d'un membre spé X."; - } + if (!await Basics.change("user", uid, "del", spk)) throw "Erreur lors de la suppression de tous les groupes d'un membre spé X."; // Les rajoute un par un, sauf pour le supprimé lg.forEach(id => { if (id!=gid) Tools.add(uid, id, "speakers").then(res => { @@ -323,9 +317,7 @@ export class Tools { && !(uid in await Tools.get(cur_gid, "group", "speakers")) && !(uid in await Tools.get(cur_gid, "group", "members"))) { let lg = await Tools.get(uid, "user", "members"); - if (!await Basics.change("user", uid, "del", mem)) { - throw "Erreur lors de la suppression de tous les groupes d'un membre spé X."; - } + if (!await Basics.change("user", uid, "del", mem)) throw "Erreur lors de la suppression de tous les groupes d'un membre spé X."; // Les rajoute un par un, sauf pour le supprimé lg.forEach(id => { if (id!=gid) Tools.add(uid, id, "admins").then(res => {