Détails sur la programmation API
This commit is contained in:
parent
8934fe840d
commit
cedd37d4b4
@ -141,11 +141,11 @@ peuvent entrainer la validation d'UE a posteriori.
|
|||||||
|
|
||||||
### Capitalisation
|
### Capitalisation
|
||||||
|
|
||||||
Les UE sont capitalisables, c'est à dire qu'un étudiant conserve son UE s'il
|
Les UE sont capitalisables, c'est à dire qu'un étudiant conserve les UEs
|
||||||
arrête temporairement ses études ou redouble un semestre.
|
obtenues (avec moyenne > 10/20) s'il arrête temporairement ses études ou redouble un semestre.
|
||||||
|
|
||||||
En cas de redoublement, l'étudiant qui choisi de répéter une UE conserve le
|
En cas de redoublement, l'étudiant qui choisi de répéter une UE capitalisée conserve le
|
||||||
résultat antérieur sauf s'il obtient mieux.
|
résultat antérieur sauf s'il obtient une meilleure moyenne.
|
||||||
|
|
||||||
### Moyenne générale
|
### Moyenne générale
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Code de ScoDoc 9
|
# Quelques informations pour les développeurs
|
||||||
|
|
||||||
Quelques informations pour les développeurs.
|
## Composants logiciels
|
||||||
|
|
||||||
- le code est écrit en Python 3.9 (passage à 3.10 prévu avec Debian 12).
|
- le code est écrit en Python 3.9 (passage à 3.10 prévu avec Debian 12).
|
||||||
- le code doit être formatté par [black](https://pypi.org/project/black/) qui
|
- le code doit être formatté par [black](https://pypi.org/project/black/) qui
|
||||||
@ -17,7 +17,7 @@ Quelques informations pour les développeurs.
|
|||||||
- [gunicorn](https://gunicorn.org/) WSGI HTTP server
|
- [gunicorn](https://gunicorn.org/) WSGI HTTP server
|
||||||
- et bien sûr Linux (Debian 11 en 2021-2022) et systemd.
|
- et bien sûr Linux (Debian 11 en 2021-2022) et systemd.
|
||||||
|
|
||||||
# Principaux objets
|
## Principaux objets
|
||||||
|
|
||||||
Les objets manipulés par ScoDoc sont pour la plupart stockés en base postgres et
|
Les objets manipulés par ScoDoc sont pour la plupart stockés en base postgres et
|
||||||
accédé soit directement en SQL (anciennes parties de ScoDoc), soit à travers
|
accédé soit directement en SQL (anciennes parties de ScoDoc), soit à travers
|
||||||
@ -41,7 +41,7 @@ Principales classes (les noms des classes Python sont en `CamelCase`).
|
|||||||
- Inscriptions: tables d'association avec codes et/ou état (démission,
|
- Inscriptions: tables d'association avec codes et/ou état (démission,
|
||||||
défaillant): FormsemestreInscription ModuleImplInscription.
|
défaillant): FormsemestreInscription ModuleImplInscription.
|
||||||
|
|
||||||
# Vues et décorateurs
|
## Vues et décorateurs
|
||||||
|
|
||||||
Une vue ordinaire (Web) pourrait ressembler à cela. Noter la présence de
|
Une vue ordinaire (Web) pourrait ressembler à cela. Noter la présence de
|
||||||
décorateurs:
|
décorateurs:
|
||||||
@ -74,11 +74,92 @@ def un_exemple():
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
# Caches
|
## Vues de l'API et permissions
|
||||||
|
|
||||||
|
L'API REST est documentée ici : [ScoDoc9API](ScoDoc9API.md).
|
||||||
|
|
||||||
|
Les fonctions de l'API sont donc accessibles via les routes de la forme
|
||||||
|
`https://scodoc.monsite.tld/ScoDoc/api/fonction`
|
||||||
|
et aussi `https://scodoc.monsite.tld/ScoDoc/api/<dept_acronyme>/fonction`.
|
||||||
|
La seconde forme précise un département.
|
||||||
|
|
||||||
|
La seconde forme est notamment utilisée par les pages web de ScoDoc. Elle permet
|
||||||
|
un calcul des permissions liées à un département: l'idée est de donner accès à
|
||||||
|
l'API à un utilisateur qui n'ait pas la permission (par ex. `ScoView`) dans tous les
|
||||||
|
départements, ce qui est en général le cas des utilisateurs Web, mais est aussi
|
||||||
|
utile pour sécuriser certains usages de l'API.
|
||||||
|
|
||||||
|
Une vue API (avec accès via token API et/ou cookie Web) se déclare donc ainsi:
|
||||||
|
|
||||||
|
```py
|
||||||
|
@bp.route("/formsemestres/query")
|
||||||
|
@api_web_bp.route("/formsemestres/query")
|
||||||
|
@login_required
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
def formsemestres_query():
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Son usage par un utilisateur n'ayant accès qu'à un seul département passera par
|
||||||
|
la route départementale
|
||||||
|
`http://scodoc.monsite.tld:5000/ScoDoc/<dept_acronyme>/api/formsemestres/query`.
|
||||||
|
|
||||||
|
### Exemple complet d'usage
|
||||||
|
|
||||||
|
Création du rôle, de l'utilisateur, association à un département, requêtage.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flask create-role LecteurAPI2 # 2 car LecteurAPi était déjà pris sur mon serveur de test
|
||||||
|
flask edit-role -a ScoView LecteurAPI2
|
||||||
|
flask user-create lecteur_rt LecteurAPI2 RT # Seulement dans dept RT
|
||||||
|
flask user-password lecteur_rt
|
||||||
|
```
|
||||||
|
|
||||||
|
puis
|
||||||
|
|
||||||
|
```bash
|
||||||
|
http -a lecteur_rt:azer POST 'http://localhost:5000/ScoDoc/api/tokens'
|
||||||
|
# récupérer le token...
|
||||||
|
|
||||||
|
http GET http://localhost:5000/ScoDoc/api/RT/formsemestres/query "Authorization:Bearer xxxxxxxxxxx"
|
||||||
|
# -> réponse ok
|
||||||
|
|
||||||
|
http GET http://localhost:5000/ScoDoc/api/formsemestres/query "Authorization:Bearer xxxxxxxxxxx"
|
||||||
|
# -> 401, "Non autorise (logic)"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Côté programmation serveur
|
||||||
|
|
||||||
|
Reprenons le même exemple (voir app/api/formsemestres.py ligne 91,
|
||||||
|
<https://scodoc.org/git/ScoDoc/ScoDoc/src/branch/master/app/api/formsemestres.py#L91>):
|
||||||
|
|
||||||
|
```py
|
||||||
|
@bp.route("/formsemestres/query")
|
||||||
|
@api_web_bp.route("/formsemestres/query")
|
||||||
|
@login_required
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
def formsemestres_query():
|
||||||
|
...
|
||||||
|
formsemestres = FormSemestre.query
|
||||||
|
if g.scodoc_dept:
|
||||||
|
formsemestres = formsemestres.filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
En effet, `g.scodoc_dept` et `g.scodoc_dept_id` sont positionnés par le
|
||||||
|
décorateur si on a un appel via la route départementale.
|
||||||
|
|
||||||
|
Il est donc important, pour toutes les vues API, de prendre soin de ne pas
|
||||||
|
divulguer d'informations hors du département spécifié, en filtrant la ou les
|
||||||
|
requêtes si `g.scodoc_dept` est non `None`.
|
||||||
|
|
||||||
|
## Caches
|
||||||
|
|
||||||
Il est bon de savoir que les requêtes SQL de SQLAlchemy ne sont pas cachées: ni
|
Il est bon de savoir que les requêtes SQL de SQLAlchemy ne sont pas cachées: ni
|
||||||
la requête elle même (construction du SQL à partir des appels à l'ORM), ni son
|
la requête elle même (construction du SQL à partir des appels à l'ORM), ni son
|
||||||
résultat.
|
résultat.
|
||||||
|
|
||||||
Le module `sco_cache.py` offre la possibilité de cacher des objets python
|
Le module `sco_cache.py` offre la possibilité de cacher des objets python
|
||||||
identifiés par un id unique dans le cache Redis. Ce cache est persistant, il
|
identifiés par un id unique dans le cache Redis. Ce cache est persistant, il
|
||||||
|
@ -61,8 +61,10 @@ flask user-password lecteur_api
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
Si vous êtes intéressé par le développement, voir [la section sur les tests
|
Si vous êtes intéressé par le développement, voir
|
||||||
unitaires de l'API](TestsScoDoc.md#tests-de-lapi-scodoc9).
|
|
||||||
|
* [la section sur les tests unitaires de l'API](TestsScoDoc.md#tests-de-lapi-scodoc9);
|
||||||
|
* [la documentation interne](Internals.md#vues-de-lapi-et-permissions).
|
||||||
|
|
||||||
## Essais avec HTTPie
|
## Essais avec HTTPie
|
||||||
|
|
||||||
@ -125,7 +127,7 @@ version de ScoDoc 9.3.25.
|
|||||||
### Accès à l'API REST
|
### Accès à l'API REST
|
||||||
|
|
||||||
L'API est accessible à l'adresse: `https://scodoc.monsite.tld/ScoDoc/api/fonction`
|
L'API est accessible à l'adresse: `https://scodoc.monsite.tld/ScoDoc/api/fonction`
|
||||||
(et aussi `https://scodoc.monsite.tld/ScoDoc/api/<dept_acronyme>/fonction` pour un
|
(et aussi `https://scodoc.monsite.tld/ScoDoc/<dept_acronyme>/api/fonction` pour un
|
||||||
accès avec des droits restreints au département indiqué).
|
accès avec des droits restreints au département indiqué).
|
||||||
|
|
||||||
#### Authentification
|
#### Authentification
|
||||||
@ -1179,7 +1181,7 @@ mais pas JSON compliant à cause des `NaN`.
|
|||||||
* **Paramètres:** `dept`, `formsemestre_id`
|
* **Paramètres:** `dept`, `formsemestre_id`
|
||||||
* **Routes:** `/formsemestre/<int:formsemestre_id>/programme`
|
* **Routes:** `/formsemestre/<int:formsemestre_id>/programme`
|
||||||
* **Exemple d'utilisation:** `/ScoDoc/api/formsemestre/1/programme`
|
* **Exemple d'utilisation:** `/ScoDoc/api/formsemestre/1/programme`
|
||||||
* **Résultat:** Retourne la struture d'un formsemestre sous 5 entrées d'un dictionnaire:
|
* **Résultat:** Retourne la structure d'un formsemestre sous 5 entrées d'un dictionnaire:
|
||||||
|
|
||||||
* **`ues`**: liste des UEs,
|
* **`ues`**: liste des UEs,
|
||||||
* **`ressources`**: liste des ressources (BUT),
|
* **`ressources`**: liste des ressources (BUT),
|
||||||
|
Loading…
Reference in New Issue
Block a user