diff --git a/docs/BUTExempleInfo.md b/docs/BUTExempleInfo.md index 5200274f1..e2c8f9ecc 100644 --- a/docs/BUTExempleInfo.md +++ b/docs/BUTExempleInfo.md @@ -199,7 +199,7 @@ Dans chaque module, on peut régler les inscriptions: - [Le BUT: détails et calculs](BUT.md) - [Guide du responsable de formation](GuideAdminFormation/md) - - [Édition des programmes de formation](VersionProgrammes.md) + - [Programmes de formation](Formations.md) - [Guide utilisateur](GuideUtilisateur.md) - [Tutoriels vidéo](https://www.youtube.com/channel/UCb0JYCBRi0CsE4XFp4ByhXg) - [Gestion des UE Bonus](https://www.youtube.com/watch?v=SVbjuDpq-lI) diff --git a/docs/CapitalisationUE.md b/docs/CapitalisationUE.md index b00df2753..611ec128a 100644 --- a/docs/CapitalisationUE.md +++ b/docs/CapitalisationUE.md @@ -1,6 +1,8 @@ # Capitalisation des UEs de DUT Brève note expliquant le système de capitalisation de UE dans le cadre des DUT. +Pour le Bachelor (BUT), voir [Capitalisation des Unités d'Enseignement en +BUT](BUTCapitalisationUE.md). ## Principe diff --git a/docs/DevAPIPermissions.md b/docs/DevAPIPermissions.md index fdaefae52..7ce53fc43 100644 --- a/docs/DevAPIPermissions.md +++ b/docs/DevAPIPermissions.md @@ -6,9 +6,11 @@ Dans ScoDoc, les permissions sont liées à des rôles. Un utilisateur a un ou p rôles, dans un ou tous les départements (si le département est null, on considère que le rôle est donnés dans tous les départements). -Dans ScoDoc Web, toutes les routes sont liées à des départements +Dans ScoDoc Web, toutes les routes sont liées à des départements +```txt /ScoDoc//Scolarite/ +``` sauf la page d'accueil (`/ScoDoc/index`), les pages de configuration générale (`ScoDoc/configuration`) et les pages "entreprises" (`ScoDoc/entreprises/`). @@ -19,6 +21,7 @@ et peuvent se retrouver dans plusieurs départements, notamment en cas de transfert d'un étudiant d'un département à un autre). ## Contrôle des permissions par l'API et départements + Ainsi, une route API comme `/partition/` n'est pas ambigüe. Toutefois, ScoDoc doit déterminer si l'utilisateur a le droit d'accéder (ou de modifier) cet objet. Pour cela, ScoDoc a besoin de connaitre le département. @@ -28,7 +31,8 @@ relation avec `formsemestre`, lui même lié à son département: on écrit Cependant, le contrôle de l'accès est plus facile à exprimer (donc plus sûr, moins de risque d'erreurs) avec un décorateur: on écrit typiquement les vues: -``` + +```py @permission_required(Permission.ScoView) def ma_vue( arg ): ... @@ -36,32 +40,38 @@ def ma_vue( arg ): Comme nous l'avons dit, pour les vues Web (voir sources dans `app/view/*.py`), le département est dans la route (URL): ainsi le tableau de bord d'un -fomsemestre est -``` +formsemestre est + +```txt ScoDoc//Scolarite/Notes/formsemestre_status ``` + La vue s'écrit -``` +```py @bp.route("/formsemestre_status") @scodoc @permission_required(Permission.ScoView) def formsemestre_status(formsemestre_id:int): ... ``` + Le décorateur `scodoc` (défini dans `app/scodoc/decorators.py`) récupère le -département présent dans la route et affecte deux attributs dans la requête -``` +département présent dans la route et affecte deux attributs dans la requête + +```py g.scodoc_dept = "RT" # l'acronyme du dept g.scodoc_dept_id = 5 # l'id du dept ``` Le décorateur suivant, `permission_required` peut ainsi vérifier que la -permission est bien accordée dans ce département. +permission est bien accordée dans ce département. Pour l'API, on a deux routes: -``` + +```py /ScoDoc/api/partition/ ``` + Dans ce cas, le décorateur `scodoc` ne récupère pas de département (`g.scodoc_dept`est mis à `None`), et `permission_required`exige alors que la permission soit accordé dans *tous les départements* (`dept`à `None`). @@ -69,27 +79,34 @@ permission soit accordé dans *tous les départements* (`dept`à `None`). Lorsque l'API est utilisée depuis une vue web de ScoDoc, donc par un utilisateur ordinaire n'ayant de rôles que dans son (ou ses) départements, ce mécanisme échoue. On propose donc une autre route, de la forme -``` + +```txt /ScoDoc//api/partition/ ``` + Les décorateurs fonctionnent alors bien. ## Écriture d'une vue API + Il reste à la charge des fonctions de l'API d'effectuer la vérification que les objets demandés sont bien dans le département donné par la route (point de vigilance: risque de fuite de données si mal codé). Dans la plupart des cas, il faut pour cela ajouter une jointure. par exemple, pour demander une partition, on écrira non pas -``` + +```py p = Partition.query.get(partition_id) ``` + mais plutôt -``` + +```py p = Partition.query.filter_by(id=partition_id).join(FormSemestre).filter_by(dept_id=g.scodoc_dept_id) ``` Écriture d'une vue de l'API accessible en mode web et API: -``` + +```py @api_bp.route("/api_function/") @api_web_bp.route("/api_function/") @login_required @@ -103,11 +120,11 @@ def api_function(arg: int): ## Fonctionnement interne du contrôle d'accès ScoDoc Les accès ScoDoc sont gérés avec `flask-login`. L'authentification est faite -soit par un cookie de session (web), soit par un jeton jwt (API). +soit par un cookie de session (web), soit par un jeton `jwt` (API). -Ce décodage/contrôle est fait par la fonction +Ce décodage/contrôle est fait par la fonction `app.auth.logic.load_user_from_request()`. En cas de refus (jeton ou cookie absent ou invalide), on a une redirection vers la page de login (en mode web), ou un message d'erreur JSON 401 pour l'API -(voir `app.auth.logic.unauthorized_handler`). +(voir `app.auth.logic.unauthorized_handler`). diff --git a/docs/ApiCreationParcours.md b/docs/DevCursus.md similarity index 96% rename from docs/ApiCreationParcours.md rename to docs/DevCursus.md index 688ef7718..7477462fc 100644 --- a/docs/ApiCreationParcours.md +++ b/docs/DevCursus.md @@ -1,4 +1,3 @@ - # Cursus ScoDoc Les cursus pédagogiques sont définis dans ScoDoc par des classes de "cursus" qui @@ -43,7 +42,7 @@ ALLOW_SEM_SKIP| `bool` | passage: autorise-t-on les sauts de semestres ? (`False SESSION_NAME| `string` | nom des sessions (`'semestre'`) SESSION_ABBRV | `string` | `'S' -> S1, S2, ...` UNUSED_CODES | `set` | ensemble des codes jury non autorisés dans ce parcours (`set()`) -UE_IS_MODULE| `bool` | un seul module par UE (si plusieurs modules, etudiants censéments inscrits à un seul d'entre eux) (`False`) +UE_IS_MODULE| `bool` | un seul module par UE (si plusieurs modules, étudiants censéments inscrits à un seul d'entre eux) (`False`) ECTS_ONLY| `bool` | parcours avec progression basée uniquement sur les ECTS (`False`) ALLOWED_UE_TYPES | `set` | types d'UE autorisés dans ce parcours diff --git a/docs/DevGit.md b/docs/DevGit.md new file mode 100644 index 000000000..cd1feaed9 --- /dev/null +++ b/docs/DevGit.md @@ -0,0 +1,396 @@ +# Utilisation de git pour ScoDoc + +Le dépôt est + +La branche `master` est celle de ScoDoc 9, d'où sont issues les paquets +distribués (*releases*). Les développements ont lieu sur d'autres branches +(`api`, `dev92`, `entreprises`, ...) avant d'être intégrés après tests. La +branche `Scodoc7` était l'ancienne (jusqu'à septembre 2021) version de ScoDoc. + +Ci-dessous quelques pense-bête qui peuvent servir. + +## Hot fixes (internes) + +Pour les développeurs internes (écriture sur le dépôt master), un exemple +basique illustrant le cycle de développement: + +```bash + # Créer une branche + # si besoin (travail en cours), utiliser git stash avant + git checkout master + git branch hotfix + git checkout hotfix + ... dev, test ... + git add ... + git commit -m "fixed ..." + git checkout master + git merge hotfix + git branch -d hotfix + # publication + + # éventuellement: git stash pop +``` + +Dans la plupart des cas, on travaillera sur son propre dépôt (clone du dépôt +origine), et on proposera une *pull request* (PR, *demande d'ajout* en français). + +## Mettre à jour votre branche + +Quand vous travaillez dans votre branche `ma_branche`, pour lui appliquer les +mises à jour de `master` (remote), faire: + +```bash + git pull origin master +``` + +## Autre exemple + +Vous travaillez sur un clone du dépôt principal ("origin"), obtenu par exemple via + +```bash +git clone https://scodoc.org/git/ScoDoc/ScoDoc.git +``` + +remplacer par l'URL de votre dépôt sur gitea au besoin. Si vous avez votre +propre dépôt sur gitea, utilisez deux "remote": l'un pour votre dépôt gitea (ici +nommé `mon_origin`), l'autre pour le dépôt principal ScoDoc (ici nommé +`origin`). + +```bash +git remote add origin https://scodoc.org/git/viennet/ScoDoc.git +git remote -v +mon_origin https://xxx.xxx (fetch) +mon_origin https://xxx.xxx (push) +origin https://scodoc.org/git/viennet/ScoDoc.git (fetch) +origin https://scodoc.org/git/viennet/ScoDoc.git (push) +``` + +Ensuite, tout est prêt, vous créez votre branche: + +```bash +git checkout -b ma_branche +``` + +et la poussez sur votre dépôt: (remplacer `mon_origin`au besoin) + +```bash +git push -u mon_origin ma_branche +``` + +Ajoutez au fur et à mesure vos commits comme d'habitude. Mais régulièrement +(chaque jour), mettez à jour pour éviter de diverger de la branche `master` (ou +autre suivant les cas) de ScoDoc: + +```bash +git pull origin master +``` + +Vous pouvez alors à tout moment soumettre une PR propre. + +## Commandes utiles, en vrac + +- `git log -L:fonction_python:fichier.py` +- Commits locaux: `git log @{u}..` + +### Refactoring + +Lint tous les fichiers modifiés: + +```bash + git status | grep modified | grep .py | awk '{print $2}' | xargs pylint -E +``` + +Affiche les variables non définies dans un fichier: + +```bash + pylint --disable=all -e E sco_parcours_dut.py | grep undefined-variable | awk '{print $4;}' | sort | uniq | tr -d \' +``` + +Prépare un sed pour renommer les variables non définies: + +```bash + for f in *.py + do + pylint --disable=all -e E "$f" | grep undefined-variable | awk '{print "sed -i .bak s/"$4"/scu."$4"/ '$f'";}' | sort | uniq | tr -d \' + done +``` + +Restore les modes au besoin (SAMBA les changent parfois): + +```bash + git diff -p -R --no-color | grep -E "^(diff|(old|new) mode)" --color=never | git apply +``` + +Note pour travailler sur VirtualBox: + +```text + addgroup scodoc vboxsf +``` + +## Préparation d'une PR (Pull Request) (niveau avancé) + +### Principes généraux + +Les remarques de cette section visent à obtenir une relecture facile de votre +demande d'ajout (*pull request*, dite "PR"): + +- Éviter les modifications de forme qui ne changent pas le sens du code. L'utilisation de + [`black`](https://black.readthedocs.io/) est obligatoire : elle permet de normaliser la présentation + du code. Cela évite de générer des différences ne représentant que des + changements de mise en forme (indentation, passages à la ligne). Cela évite + aussi au développeur d'avoir à y réfléchir, autant de temps gagné ! + +- Avoir un nombre d'étapes de validation faible (idéalement un seul commit pour + les PR courantes - peu volumineuses). + +- La PR doit toujours être énoncée par rapport au dernier commit de la branche + que vous visez (en général `master` du dépôt original). + +### Manipulations + +Les manipulations sont décrites selon quatre phases du développement : l'installation, +la mise en place, le suivi et la livraison. + +#### L'installation + +Il est pratique d'avoir en ligne les deux dépôts git distants que vous pouvez +utiliser : votre dépôt personnel (`https://scodoc.org/git//.git`) et +le dépôt officiel (`https://scodoc.org/git/ScoDoc/ScoDoc.git`). + +pour ajouter une référence (et lui donner un nom) vers un dépôt distant, entrez +la commande: + +```bash + git remote add nom_remote https://scodoc.org/git/ScoDoc/.git +``` + +Par la suite vous aurez donc une référence vers votre dépôt personnel (`perso`) +et une référence vers le dépôt officiel (`officiel`). Si vous avez initialement +cloné l'un des deux dépôts, la référence vers le dépôt d'origine existe et a pour nom +`origin`. + +La commande vous exposant tous les dépôts connus est : + +```bash + git remote -v +``` + +### Mise en place + +L'objectif de ce paragraphe est de créer une branche locale basée sur le master +du dépôt officiel et bien sur de lui donner un nom. + +pour cela (**attention cela va écraser les éventuels fichiers modifiés**. Si +vous souhaitez conserver les modifications en cours, encadrez les lignes +suivantes par `git stash` (avant) et `git stash apply` (après) : + +```bash + git reset --hard officiel/master + git checkout -b ma_modif +``` + +À partir de là, vous pouvez modifier, tester, développer et commit votre travail. + +### Suivi + +Si votre développement prend plusieurs jours, il est probable que la branche +principale évolue pendant ce temps. + +Pour garder la cohérence, il est nécessaire de réintégrer en local les +modifications de la branche principale. Ceci peut se faire de deux façons. + +- Une fusion (`merge`) applique toutes les modifications en un seul commit). + C'est la méthode couramment utilisée. + +- Un `rebase` rejoue tous les commits de la nouvelle branche par dessus l'état + le plus à jour de la branche principale (il en résulte un historique plus + linéaire). + +Les commandes git correspondantes : + +```bash + git pull officiel master +``` + +ou encore +```bash + git fetch officiel + git merge officiel/master +``` + +Pour un rebase (à éviter en temps normal): + +```bash + git fetch officiel + git rebase officiel/merge +``` + +### La livraison + +Ça y est. Vous avez terminé le développement. IL n'y a plus qu'à demander +l'intégration. Ceci se fait en plusieurs étapes (vous êtes bien sûr toujours sur +la branche locale `ma_modif` et toutes vos modifications ont été commitées). + +#### Étape 1 : faire l'inventaire des fichiers impliqués + +```bash + git fetch officiel/master + git diff --name-only officiel/master +``` + +#### Étape 2 : passer black sur les fichiers modifiés + +Cette étape est automatique avec les bons réglages sous VSCode (pas trouvé +l'équivalent sous *pyCharm*). + +À défaut les lignes suivantes réalisent le même travail : + +```bash + for fn in $(git diff --name-only officiel/master) + do + python3 -m black $fn + done +``` + +Faire une première lecture rapide pour vérifier qu'il ne reste pas de fichiers +modifiés accidentellement. + +Pour obtenir la modification sur un fichier spécifique (`app/fichier.py` par +exemple): + +```bash + git diff officiel/master app/fichier.py +``` + +Utilisateurs Windows : Vérifiez bien que les réglages de fin de ligne suivent +bien les règles Linux: pas de retour chariot (noté CR ou `\r`) en fin de ligne +mais un seul caractère line feed (noté LF ou `\n`). Le cas échéant, réglez +votre IDE pour cela. + +À ce niveau là de la procédure, vous n'avez plus dans votre branche locale que +les différences strictement nécessaires à votre correctif. + +#### Étape 3 : résumez tous les commits depuis le point de divergence en un seul commit + +**Rarement nécessaire, uniquement si vous avez de nombreux petits commits.** + +Repérez le point de divergence de votre branche locale avec officiel/master +(normalement `git merge-base HEAD officiel/master`) + +Demander un `rebase` interactif depuis ce point : + +```bash + git rebase -i $(git merge-base HEAD officiel/master) +``` + +*Explications*: Le rebase interactif permet d'enregistrer un suite de +manipulation de commit dans un seul fichier texte. Le fichier texte qui reprend +tels quels tous les commits concernés (et donc qui ne fait rien) est préparé par +la commande `-i` de la commande_ `git rebase`. + +Vous pouvez ensuite modifier ce fichier dans votre éditeur favori (ou pas) (à +régler par `git config`) pour décrire_ _votre intention (réordonner, changer le +message, fusionner, ...) sur l'ensemble des commits. + +Quand votre édition est terminée, git reprend la main est exécute chacune de vos +opérations. Il est possible (bien que très rare) que des conflits apparaissent +à ce moment-là. Les commandes habituelles de correction accompagnées des +commandes : + +```bash +git rebase --continue # pour poursuivre le processus +git rebase --abort # pour tout abandonner +``` + +*vous permettront de résoudre ces problèmes exceptionnels*. + +Application: + +```bash +git rebase -i $(git merge-base HEAD officiel/master) +``` + +Vous devez obtenir dans un éditeur de texte la liste des commits opéré depuis le +début du développement sous cette forme (c'est un exemple : le nombre de lignes +peut varier) : + +```bash +pick eb8cbec modif 1 +pick 83eb79e modif 2 + +# Rebase 5ffd074..83eb79e onto 5ffd074 (2 commands) +# +# Commands: +# p, pick = use commit +# r, reword = use commit, but edit the commit message +# e, edit = use commit, but stop for amending +# s, squash = use commit, but meld into previous commit +# f, fixup [-C | -c] = like "squash" but keep only the previous +# commit's log message, unless -C is used, in which case +# keep only this commit's message; -c is same as -C but +# opens the editor +# x, exec = run command (the rest of the line) using shell +# b, break = stop here (continue rebase later with 'git rebase --continue') +# d, drop = remove commit +# l, label