[![pipeline status](https://gitlab.binets.fr/br/sigma-backend/badges/master/pipeline.svg)](https://gitlab.binets.fr/br/sigma-backend/commits/master)

# 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.

Pour obtenir une copie de ce dépôt, clonez-le avec

    git clone git@gitlab.binets.fr:br/sigma-backend.git

ou `git clone https://gitlab.binets.fr/br/sigma-backend.git`, puis installez les dépendances JavaScript avec `npm install`.

À terme, ce projet doit tourner sur un serveur du BR et servir d'API à un _frontend_ React *au code séparé et documenté séparément* toute les données nécessaires à son bon fonctionnement (authentification, appartenance à un groupe, droits de visibilité...). Le dépôt pour le serveur front se trouve ici : <https://gitlab.binets.fr/br/sigma-frontend> (on l'appellera indifféremment serveur front, front ou frontend...)

Ce document détaille les différentes dépendances du projet, sa structure générale, détaille un peu plus des éléments sur la base de données et la documentation ; le code est également commenté en détail.

## Image Docker

L'image Docker est définie dans [`Dockerfile`](./Dockerfile). Il s'agit d'une distro Alpine avec Node.js et libstdc++. Lors du _build_ les dépendances _runtime_ dont dépend le `bundle.js` sont installées.

Compiler l'image :

    docker build -t sigma-api .

Faire tourner le conteneur :

    docker run sigma-api

avec un LDAP custom :

    docker run -e LDAP_URI=ldap://172.17.0.1:8389 sigma-api

## Dépendances

Une dépendance, c'est un librairie JavaScript dont dépend le code source, soit pour le faire tourner soit pour faire tourner les outils dévs. Les dépendances développeur servent à tester par exemple. On trouve la liste des dépendances dans [`package.json`](./package.json). Express est un exemple de dépendance normale, nodemon et ESLint (voir infra) sont des dépendances dev (`devDependencies`).

Les dépendances s'installent avec `npm install`. Par défaut, toutes les dépendances sont installées. Si la variable `NODE_ENV` est configurée (vérifier avec la commande `echo "$NODE_ENV"`),

* la valeur `development` installe tout
* la valeur `production` n'installe pas les dépendances développeur

Certaines d'entre elles comme KnexJS ou Webpack doivent être installées globalement :

```bash
npm install -g knex
npm install -g webpack
npm install -g eslint
```

Les dépendances les plus importantes sont knex.js, notre outil de gestion de BDD locale, GraphQL qui sert à communiquer entre serveurs, ldap.js qui interroge le LDAP avec la plupart des données, webpack qui sert à la gestion du serveur. ESlint est un outil de vérification syntaxique.

Le serveur utilisé est [express.js](https://expressjs.com/) ; il est configuré dans [`app.ts`](../src/app.ts) puis lancé sur le port 3000 dans [`index.ts`](../src/index.ts).

## 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.

### 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/config.ts](src/ldap/config.ts).
* Si la variable d'environnement `LDAP_URI` est définie, l'adresse où trouver le LDAP est remplacée.

**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 au path `/adminview/admin` ; n'importe quel path devrait rediriger dessus, ou alors vers `/adminview/login`. Les identifiants à utiliser sont ceux de Frankiz. L'authentification se fait par le LDAP Frankiz.

### Accès direct à la BDD via knex

Le panneau d'administration sert (ou plutôt, servira à terme) à accéder directement à la BDD propre de sigma. On accède à la table `table_name` par une requête GET à `/adminview/db/table_name`' et aux colonnes `columns` de cette table par une requête GET à `/adminview/db/table_name`?columns=`columns`.
Ces pages sont protégées pour n'être accessibles qu'en étant authentifié.

### GraphQL Playground et Voyager

Accéder via un navigateur à `/graphql` et `/voyager` respectivement renvoie les apps GraphQL Playground et GraphQL Voyager. 

Il s'agit du même `/graphql` que l'_endpoint_ de l'API, mais le serveur est configuré de sorte à renvoyer Playground lorsqu'il détecte un accès via navigateur. Les requêtes dans le Playground sont donc soumises au mêmes permissions que dans l'API.

L'app Voyager permet de visualiser le « graphe » sous-jacent à la structure de l'API. Cet _endpoint_ devrait être protégé **en prod**.

**En production**, 

## Scripts

Les scripts sont des instructions en ligne de commande que l'on peut faire tourner avec la commande `npm run`. Ce sont des raccourcis pour gagner du temps sur des opérations un peu longues. Ils sont définis dans [`package.json`](../package.json).

Les plus importants sont détaillées ci-dessous (ne pas oublier `npm install` déjà mentionné plus tôt) :

On utilisera Webpack pour transpiler le fichier source [`src/index.js`](../src/index.js) en [`build/bundle.js`](../build/bundle.js) qui est suit la syntaxe ES5 compatible Node. Pour ça, on utilise :

* `npm run build` qui exécute la commande `webpack` avec le fichier de configuration `webpack.config.js`, ou
* `npm run watch` qui recompile automatiquement dès que le code est modifié.

### Démarrer le serveur

Pour faire tourner le serveur, lancer

    npm start

démarre le serveur compilé [`build/bundle.js`](build/bundle.js) avec [nodemon](https://nodemon.io/), outil dév, et le redémarre automatiquement après modification.

Donc, lancer `npm run watch` dans un terminal et `npm start` dans un autre permet de recompiler le serveur __et__ le relance automatiquement.

Le script pour faire tourner [JSDoc](http://usejsdoc.org/index.html) et régénérer la documentation est : `npm run doc`

## Documentation

La documentation détaillée du projet est [ici](./doc/index.html). Elle a été compilée avec [JSDoc](http://usejsdoc.org/index.html) sous format hmtl selon le fichier de configuration [`configfile_doc.json`](../configfile_doc.json) à la racine du projet.

Les fichiers compilés se situent dans [`doc`](.) avec leurs fichiers image. Par nature de l'outil JSDoc il est facile de documenter en détail des fonctions .js mais plus compliqué de documenter un fichier.

A la fin de ce fichier JSDoc rajoute les commentaires placés dans chacun des fichiers et des hyperliens pour y accéder.