diff --git a/docs/BUT.md b/docs/BUT.md index e831aba3..8985502e 100644 --- a/docs/BUT.md +++ b/docs/BUT.md @@ -141,11 +141,11 @@ peuvent entrainer la validation d'UE a posteriori. ### Capitalisation -Les UE sont capitalisables, c'est à dire qu'un étudiant conserve son UE s'il -arrête temporairement ses études ou redouble un semestre. +Les UE sont capitalisables, c'est à dire qu'un étudiant conserve les UEs +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 -résultat antérieur sauf s'il obtient mieux. +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 une meilleure moyenne. ### Moyenne générale diff --git a/docs/Internals.md b/docs/Internals.md index 2347c22f..c485ca2e 100644 --- a/docs/Internals.md +++ b/docs/Internals.md @@ -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 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 - 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 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, défaillant): FormsemestreInscription ModuleImplInscription. -# Vues et décorateurs +## Vues et décorateurs Une vue ordinaire (Web) pourrait ressembler à cela. Noter la présence de 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//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//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, +): + +```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 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 identifiés par un id unique dans le cache Redis. Ce cache est persistant, il diff --git a/docs/ScoDoc9API.md b/docs/ScoDoc9API.md index 80775722..c5534678 100644 --- a/docs/ScoDoc9API.md +++ b/docs/ScoDoc9API.md @@ -61,8 +61,10 @@ flask user-password lecteur_api ... ``` -Si vous êtes intéressé par le développement, voir [la section sur les tests -unitaires de l'API](TestsScoDoc.md#tests-de-lapi-scodoc9). +Si vous êtes intéressé par le développement, voir + +* [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 @@ -125,7 +127,7 @@ version de ScoDoc 9.3.25. ### Accès à l'API REST L'API est accessible à l'adresse: `https://scodoc.monsite.tld/ScoDoc/api/fonction` -(et aussi `https://scodoc.monsite.tld/ScoDoc/api//fonction` pour un +(et aussi `https://scodoc.monsite.tld/ScoDoc//api/fonction` pour un accès avec des droits restreints au département indiqué). #### Authentification @@ -1179,7 +1181,7 @@ mais pas JSON compliant à cause des `NaN`. * **Paramètres:** `dept`, `formsemestre_id` * **Routes:** `/formsemestre//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, * **`ressources`**: liste des ressources (BUT),