WikiMiNET

La documentation technique et administrative

Outils pour utilisateurs

Outils du site


wiki:services:adh6

ADH6

ADH6 est l'interface de gestion des adhérents.

Histoire

Le projet ADH6 a débuté en l'an 2012 (av JC), rien n'a été fait cette année là mais l'idée avait été lancée. Cette idée a traversé l'histoire des bureaux successifs revenant chaque année tel un running gag.

C'est sous le bureau 2016-2017 que le projet a réellement essayé d'émerger. thunder s'est grandement investi et a rassemblé des gens pour réaliser ce projet. Cela s'est concrétisé par un stage MiNET. Un premier prototype est arrivé et a été rapidement abandonné. Le projet a été repris dans une deuxième version plus aboutie (en 2016) et abandonné en raison des technologies utilisées.

En 2017, une nouvelle vision émerge de Thomas pour la conception d'ADH6 en servant des expériences passées. insolentbacon décide alors de s'investir avec occuria en profitant d'une validation projet JS. Et c'est comme ça que le projet commence à réellement voir le jour.

Les Technos

La Techno Actuelle

Le gros désavantage d'ADH5 est qu'il est difficilement maintenable. Pourquoi ?

  1. C'est un énorme bloc monolithique: 86k lignes…
  2. Cela gère trop de trucs en même temps dont on ne se sert plus: les tickets, les articles…
  3. C'est fait en Ruby on Rails: c'était à la mode, plus maintenant, plus compliqué à maintenir alors. Si tu connais pas c'est austère.

En résumé, ADH5 est un super outil mais trop difficile à maintenir, donc plus à jour.

Le Langage

Lors de la première version sous le règne de thunder, le Python s'est imposé (comme ADH4). Pourquoi ?

  1. C'est plus facile à utiliser
  2. Les nouveaux MiNETiens sont souvent des taupins qui ont déjà touché au Python.
  3. Le prototypage est plus rapide.

Le Framework

Après avoir choisi le python, pour ne pas reproduire les erreurs d'ADH4, l'utilisation d'un framework est devenue obligatoire. Le choix s'est porté sur Django. On peut tout faire avec c'est pratique. Même si la syntaxe est proche du python, le Django c'est particulier, il faut se faire aux fonctions et aux méthodes d'implémentation. Cela demande beaucoup d'apprentissage et cela n'avait pas été anticipé, donc même problème que pour ADH5, d'où l'abandon de la techno.

Une nouvelle façon de concevoir l'application a été pensée lors de la troisième itération, nous détaillons plus précisemment cette idée dans la prochaine partie.

Maintenant, on utilise Flask, qui à l'inverse de Django se contente de gérer son rôle de serveur Web. Pour faciliter la création d'une API on utilise le plugin connexion [pour l'anectdote, c'est une lib développée par Zalando], et pour communiquer avec notre base de donnée, on utilise SQLAlchemy. SQLAlchemy et Flask sont des libs qui sont très connues et réputées en Python.

En plus de ça, on utilise une application web développée en Javascript avec le framework Angular. C'est un framework qui est à la mode à l'heure où j'écris ces lignes.

La nouvelle vision

A partir de la troisième itération, le changement a été radical dans la façon dont a été pensée l'application. A la manière de la philosophie d'Unix on s'est dit que nous allions faire plusieurs applications qui font une seule chose et qui la font bien. Adieu le “gros bloc monolithique” nous allons découper nos fonctions en plusieurs app, et donc utiliser plusieurs technos (et langage).

Il a donc fallut réfléchir au rôle concret d'ADH… C'est un “outil de gestion d'adhérents”, ça gère donc des adhérents et leurs appareils. La gestion du livre journal comptable, la gestion de l'authentification et la gestion des droits des admins, devaient être déplacées dans une autre service. Comme fonctions principales on a dégagé (en découpant finement, mais pas trop):

  • L'enregistrement des adhérents, de leurs machines et la gestion de leur port/chambre
  • La gestion de la comptabilité
  • L'authentification des administrateurs d'ADH
  • Le frontend, la jolie interface graphique quoi.

Ce qui est cool avec cette infra, c'est que chacun des composants sont remplaçable/substituable, par exemple, si un jour quelqu'un décide de faire une autre interface web (parce que Angular est devenu déprécié ou autre) il peut remplacer facil ement. De plus on peut avoir deux interfaces webs connectées à la même API. Ainsi, si on veut faire évoluer une partie du tout, nous n'avons pas à tout réécrire (comme pour ADH5→ADH6)

Par ailleurs, chacun des éléments vise à être le plus simple possible. Si quelqu'un veut modifier l'authentification, par exemple, il sait où aller modifier et si il a à toucher un code simple. ( Keep it simple, stupid!)

Pour faire communiquer ces différents composants unitaires, nous avons fait le choix de faire des APIs (voir schéma explicatif ci-dessous). Encore une fois, c'est un concept à la mode et qui semble pérenne. Plus précisemment, nous avons fait des API REST là où nous le pouvions.

En clair, quand vous vous connectez, vous téléchargez une application (une page HTML/CSS/Javascript). Vous exécutez le code qui va faire des requêtes HTTP vers les différentes API pour interagir avec (s'authent, avoir la liste des membres, ajouter un membre etc.)

Les différents composants

L'API

L'API est un serveur web. Il renvoie des données (sous forme JSON) selon les pages qu'on demande. Il permet aussi de modifier des données selon la méthode HTTP utilisée (GET, POST, PUT, DELETE, etc). En clair c'est l'interface entre la base de données et le monde.

Open API Pour définir la spécification de cette API, nous avons utilisé une norme appelée OpenAPI2 (ou de façon un peu moins stylée Swagger).

Cette spécification est écrite dans un fichier (sous le format YAML), et définit toutes les adresses de l'API (appelées endpoints dans le jargon), les variables qui peuvent être passées en paramètre et les valeurs de retour. C'est une spécification, elle définit les entrées et sorties, elle ne définit en aucun cas le comportement de l'API (genre la connexion au SQL), ça, c'est le rôle de l'implémentation.

Franchement, manipuler du YAML c'est dégueulasse. Si vous voulez une interface cool pour bosser avec, vous pouvez aller sur SwaggerHub où vous aurez une jolie interface pour visualiser l'API après avoir collé le YAML.

Pour implémenter facilement la spécification avec Flask, nous utilisons un plugin appelé connexion qui permet de prendre un fichier OpenAPI 2 (sous forme YAML) et de nous faciliter la tâche. Nous avons juste plus qu'à implémenter les méthodes sous forme d'un code simpliste du genre:

def monEndpoint(monParam1, monParam2):
    return Contenu, codeD'Erreur

Bref, ça nous fait un code court, simple à comprendre et donc ça fait moins de bugs.

Et surtout, connexion fait tout un tas de checks pour nous avant. Genre typiquement il vérifie que les arguments required sont bien inclus dans la requête, et si c'est pas le cas il répond directement au client avec le bon code d'erreur. De même il vérifie le type des variables.

SQL Maintenant que nous avons évoqué comment l'API communique avec le monde, il faut que nous comprenions qu'est ce qu'elle fait.

Presque tous les endpoints de l'API se contente de faire des requêtes sur la base de donnée SQL. Pour cela nous utilisons une bibliothèque appelée  SQLALchemy, un truc béton pour gérer les base de données (le terme pour se la péter c'est ORM. Ça nous permet d'éviter de faire des requêtes SQL (donc d'introduire des failles SQL [Même si c'est pas pour autant qu'on y est immunisé!]).

Je ne vais pas détailler comment SQLAlchemy fonctionne, la syntaxe et tout. C'est pas le lieu pour, si vous voulez en savoir plus allez sur le site d'SQLAlchemy dans la partie tutoriel de l'ORM, ici à l'heure où j'écris ces lignes.

C'est peut-être le truc le plus compliqué à comprendre de cette application (Et pourtant c'est simple!)

Sinon, on fait des requêtes SNMP vers les switchs pour interagir avec les ports (désactiver l'authent', activer désactiver les ports, check le status d'un port [si il est branché ou non]). Je vais pas vous faire un cours sur SNMP, je vous invite à vous documenter vous même (mais seulement si vous avez un truc à réparer parce que c'est pas franchement passionnant :D). C'est un truc qui a été repris d'ADH5.

Le frontend

Pour le frontend on utilise Angular 7(version à l'heure à laquelle j'écris cette page). Il y a un gestionnaire de paquet appelé npm. Après avoir cloné le projet, rien de plus simple que:

sudo npm install -g @angular/cli # Pour installer l'outil angular sur votre PC
npm install # Pour installer les dépendances du projet
sh generate_api_services.sh # Pour générer les fichiers de l'API
ng serve # Pour lancer le serveur

En gros generate_api_services.sh permet de générer des "services" à partir de l'API, donc les fonctions pour communiquer avec l'API sont déjà toutes faites, ça enlève une grosse partie du boulot. Il n'y a plus qu'à définir chaque “component” pour chaque page. Un component distingue l'html, le css et le ts (TypeScript).

L'authentification

Pour s'authentifier, nous utilisons le protocole OAuth 2. C'est encore une fois un truc à la mode, qui semble durer (c'est ce qui est utilisé quand vous cliquez sur les boutons “Sign in with Facebook/Google/Gitlab”). C'est particulièrement adapté pour les API et c'est 100% compatible avec OpenAPI2. De plus connexion gère nativement ce protocole.

Pour implémenter le serveur d'OAuth, (parce que oui on va pas mettre de bouton Sign in with Google/Facebook/BigBrother), nous avons choisi de ne pas le réimplémenter nous même mais plutôt d'utiliser un outil libre et sécurisé: CAS. CAS est utilisé par l'école pour authentifier les élèves à E-Campus, c'est stable et on peut l'intégrer à notre LDAP.

Si ça vous intéresse de savoir comment ça se passe au niveau du navigateur pour s'authent', nous utilisons l'Implicit Grant. Allez voir la RFC si ça vous intéresse, sinon il y a plein de jolis schémas si vous allez chercher sur votre moteur de recherche préféré.

Glossaire des technos

  • API: Truc sur lequel on fait des requêtes pour effectuer les actions d'ADH6
  • API REST: API sur laquelle on fait des requêtes HTTP, en utilisant pleinement toutes les fonctinnalités d'HTTP (genre en faisant des GET, POST, PUT, etc)
  • OpenAPI 2.0/Swagger: C'est une façon de spécifier l'API
  • Flask: Bibliothèque pour faire un serveur web en python
  • connexion: Bibliothèque python se à ajouter à Flask pour faire un serveur d'API très facilement à partir d'une specification
  • SQLAlchemy: Bibliothèque python pour interagir avec la base de donnée SQL facilement
  • OAuth2: Protocole pour authentifier quelqu'un
  • AuthLib: Bibliothèque python se mettant sur Flask pour implémenter OAuth2 facilement
  • Angular: Framework javascript que nous avons utilisé pour faire le frontend
wiki/services/adh6.txt · Dernière modification: 2020/06/27 18:16 (modification externe)