mirror of
https://github.com/ae-utbm/sith.git
synced 2025-07-10 11:59:23 +00:00
Rewrite documentation with MkDocs
This commit is contained in:
150
docs/tutorial/devtools.md
Normal file
150
docs/tutorial/devtools.md
Normal file
@ -0,0 +1,150 @@
|
||||
Le projet n'est en aucun cas lié à un
|
||||
quelconque environnement de développement.
|
||||
Il est possible pour chacun de travailler
|
||||
avec les outils dont il a envie et d'utiliser
|
||||
l'éditeur de code avec lequel il est le plus à l'aise.
|
||||
|
||||
Pour donner une idée, Skia a écrit une énorme
|
||||
partie de projet avec l'éditeur *Vim* sur du GNU/Linux
|
||||
alors que Sli a utilisé *Sublime Text* sur MacOS
|
||||
et que Maréchal travaille avec PyCharm
|
||||
sur ~~Windows muni de WSL~~ Arch Linux btw.
|
||||
|
||||
## Configurer les pre-commit hooks
|
||||
|
||||
La procédure habituelle pour contribuer au
|
||||
projet consiste à commit des modifications,
|
||||
puis à les push sur le dépôt distant et
|
||||
à ouvrir une pull request.
|
||||
Cette PR va faire tourner les outils de vérification
|
||||
de la qualité de code.
|
||||
Si la vérification échoue, la PR est bloquée,
|
||||
et il faut réparer le problème
|
||||
(ce qui implique de push un micro-commit
|
||||
ou de push force sur la branche).
|
||||
|
||||
Dans l'idéal, on aimerait donc qu'il soit
|
||||
impossible d'oublier de faire tourner ces vérifications.
|
||||
Pour ça, il existe un mécanisme : les pre-commits hooks.
|
||||
Ce sont des actions qui tournent automatiquement
|
||||
lorsque vous effectuez un `git commit`.
|
||||
Ces dernières vont analyser et éventuellement modifier le code,
|
||||
avant que Git n'ajoute effectivement le commit sur l'arbre git.
|
||||
Voyez ça comme une micro-CI qui tourne en local.
|
||||
|
||||
Les git hooks sont une fonctionnalité par défaut de Git.
|
||||
Cependant, leur configuration peut-être un peu
|
||||
embêtante si vous le faites manuellement.
|
||||
Pour gérer ça plus simplement,
|
||||
nous utilisons le logiciel python [pre-commit](https://pre-commit.com/)
|
||||
qui permet de contrôler leur installation via un seul fichier de configuration,
|
||||
placé à la racine du projet
|
||||
(plus précisément, il s'agit du fichier `.pre-commit-config.yaml`).
|
||||
|
||||
!!!note
|
||||
|
||||
Les pre-commits sont également utilisés dans la CI.
|
||||
Si ces derniers fonctionnent localement, vous avez la garantie que la pipeline ne sera pas fachée. ;)
|
||||
|
||||
C'est une fonctionnalité de git lui-même,
|
||||
mais c'est assez embêtant à gérer manuellement.
|
||||
Pour gérer ça plus simplement,
|
||||
nous utilisons le logiciel python [pre-commit](https://pre-commit.com/)
|
||||
qui permet de contrôller leur installation via un fichier yaml.
|
||||
|
||||
Le logiciel est installé par défaut par poetry.
|
||||
Il suffit ensuite de lancer :
|
||||
|
||||
```bash
|
||||
pre-commit install
|
||||
```
|
||||
Une fois que vous avez fait cette commande, pre-commit
|
||||
tournera automatiquement chaque fois que vous ferez
|
||||
un nouveau commit.
|
||||
|
||||
Il est également possible d'appeler soi-même les pre-commits :
|
||||
|
||||
```bash
|
||||
pre-commit run --all-files
|
||||
```
|
||||
|
||||
|
||||
## Configurer Ruff pour son éditeur
|
||||
|
||||
!!!note
|
||||
|
||||
Ruff est inclus dans les dépendances du projet.
|
||||
Si vous avez réussi à terminer l'installation, vous n'avez donc pas de configuration
|
||||
supplémentaire à effectuer.
|
||||
|
||||
Pour utiliser Ruff, placez-vous à la racine du projet et lancez la commande suivante :
|
||||
|
||||
```bash
|
||||
ruff format # pour formatter le code
|
||||
ruff check # pour linter le code
|
||||
```
|
||||
|
||||
Ruff va alors faire son travail sur l'ensemble du projet puis vous dire
|
||||
si des documents ont été reformatés (si vous avez fait `ruff format`)
|
||||
ou bien s'il y a des erreurs à réparer (si vous avez faire `ruff check`).
|
||||
|
||||
Appeler Ruff en ligne de commandes avant de pousser votre code sur Github
|
||||
est une technique qui marche très bien.
|
||||
Cependant, vous risquez de souvent l'oublier.
|
||||
Or, lorsque le code ne respecte pas les standards de qualité,
|
||||
la pipeline bloque les PR sur les branches protégées.
|
||||
|
||||
Pour éviter de vous faire régulièrement avoir, vous pouvez configurer
|
||||
votre éditeur pour que Ruff fasse son travail automatiquement à chaque édition d'un fichier.
|
||||
Nous tenterons de vous faire ici un résumé pour deux éditeurs de textes populaires
|
||||
que sont VsCode et Sublime Text.
|
||||
|
||||
### VsCode
|
||||
|
||||
Installez l'extension Ruff pour VsCode.
|
||||
Ensuite, ajoutez ceci dans votre configuration :
|
||||
|
||||
```json
|
||||
{
|
||||
"[python]": {
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "charliermarsh.ruff"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Sublime Text
|
||||
|
||||
Vous devez installer ce plugin : https://packagecontrol.io/packages/LSP-ruff.
|
||||
Suivez ensuite les instructions données dans la description du plugin.
|
||||
|
||||
Dans la configuration de votre projet, ajoutez ceci:
|
||||
|
||||
```json
|
||||
{
|
||||
"settings": {
|
||||
"lsp_format_on_save": true,
|
||||
"LSP": {
|
||||
"LSP-ruff": {
|
||||
"enabled": true,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Si vous utilisez le plugin [anaconda](http://damnwidget.github.io/anaconda/),
|
||||
pensez à modifier les paramètres du linter pep8
|
||||
pour éviter de recevoir des warnings dans le formatage
|
||||
de ruff comme ceci :
|
||||
|
||||
```json
|
||||
{
|
||||
"pep8_ignore": [
|
||||
"E203",
|
||||
"E266",
|
||||
"E501",
|
||||
"W503"
|
||||
]
|
||||
}
|
||||
```
|
11
docs/tutorial/etransaction.md
Normal file
11
docs/tutorial/etransaction.md
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
La boutique en ligne nécessite une interaction
|
||||
avec la banque pour son fonctionnement.
|
||||
|
||||
Malheureusement, la manière dont cette interaction marche
|
||||
est trop complexe pour être résumée ici.
|
||||
|
||||
Nous ne pouvons donc que vous redirigez vers la doc du crédit
|
||||
agricole :
|
||||
https://www.ca-moncommerce.com/espace-client-mon-commerce/up2pay-e-transactions/ma-documentation/
|
||||
|
64
docs/tutorial/groups.md
Normal file
64
docs/tutorial/groups.md
Normal file
@ -0,0 +1,64 @@
|
||||
Il existe deux types de groupes sur le site AE :
|
||||
|
||||
- l'un se base sur des groupes enregistrés en base de données pendant le développement,
|
||||
c'est le système de groupes réels.
|
||||
- L'autre est plus dynamique et comprend tous les groupes générés
|
||||
pendant l'exécution et l'utilisation du programme.
|
||||
Cela correspond généralement aux groupes liés aux clubs.
|
||||
Ce sont les méta-groupes.
|
||||
|
||||
## La définition d'un groupe
|
||||
|
||||
Les deux types de groupes sont stockés dans la même table
|
||||
en base de données, et ne sont différenciés que par un attribut `is_meta`.
|
||||
|
||||
### Les groupes réels
|
||||
|
||||
Pour plus différencier l'utilisation de ces deux types de groupe,
|
||||
il a été créé une classe proxy
|
||||
(c'est-à-dire qu'elle ne correspond pas à une vraie table en base de donnée)
|
||||
qui encapsule leur utilisation.
|
||||
`RealGroup` peut être utilisé pour créer des groupes réels dans le code
|
||||
et pour faire une recherche sur ceux-ci
|
||||
(dans le cadre d'une vérification de permissions par exemple).
|
||||
|
||||
### Les méta-groupes
|
||||
|
||||
Les méta-groupes, comme expliqué précédemment,
|
||||
sont utilisés dans les contextes où il est nécessaire de créer un groupe dynamiquement.
|
||||
Les objets `MetaGroup`, bien que dynamiques, doivent tout de même s'enregistrer
|
||||
en base de données comme des vrais groupes afin de pouvoir être affectés
|
||||
dans les permissions d'autres objets, comme un forum ou une page de wiki par exemple.
|
||||
C'est principalement utilisé au travers des clubs,
|
||||
qui génèrent automatiquement deux groupes à leur création :
|
||||
|
||||
- club-bureau : contient tous les membres d'un club **au dessus**
|
||||
du grade défini dans `settings.SITH_MAXIMUM_FREE_ROLE`.
|
||||
- club-membres : contient tous les membres d'un club
|
||||
**en dessous** du grade défini dans `settings.SITH_MAXIMUM_FREE_ROLE`.
|
||||
|
||||
|
||||
## Les groupes réels utilisés
|
||||
|
||||
Les groupes réels que l'on utilise dans le site sont les suivants :
|
||||
|
||||
Groupes gérés automatiquement par le site :
|
||||
|
||||
- `Public` : tous les utilisateurs du site
|
||||
- `Subscribers` : tous les cotisants du site
|
||||
- `Old subscribers` : tous les anciens cotisants
|
||||
|
||||
Groupes gérés par les administrateurs (à appliquer à la main sur un utilisateur) :
|
||||
|
||||
- `Root` : administrateur global du site
|
||||
- `Accounting admin` : les administrateurs de la comptabilité
|
||||
- `Communication admin` : les administrateurs de la communication
|
||||
- `Counter admin` : les administrateurs des comptoirs (foyer et autre)
|
||||
- `SAS admin` : les administrateurs du SAS
|
||||
- `Forum admin` : les administrateurs du forum
|
||||
- `Pedagogy admin` : les administrateurs de la pédagogie (guide des UVs)
|
||||
- `Banned from buying alcohol` : les utilisateurs interdits de vente d'alcool (non mineurs)
|
||||
- `Banned from counters` : les utilisateurs interdits d'utilisation des comptoirs
|
||||
- `Banned to subscribe` : les utilisateurs interdits de cotisation
|
||||
|
||||
|
248
docs/tutorial/install.md
Normal file
248
docs/tutorial/install.md
Normal file
@ -0,0 +1,248 @@
|
||||
## Dépendances du système
|
||||
|
||||
Certaines dépendances sont nécessaires niveau système :
|
||||
|
||||
- poetry
|
||||
- libssl
|
||||
- libjpeg
|
||||
- zlib1g-dev
|
||||
- python
|
||||
- gettext
|
||||
- graphviz
|
||||
|
||||
### Installer WSL
|
||||
|
||||
Si vous utilisez Windows, je suis navré
|
||||
de vous annoncer que, certaines dépendances étant uniquement disponibles sur des sytèmes UNIX,
|
||||
il n'est pas possible de développer le site sur ce système d'exploitation.
|
||||
|
||||
Heureusement, il existe une alternative qui ne requiert pas de désinstaller votre
|
||||
OS ni de mettre un dual boot sur votre ordinateur : `WSL`.
|
||||
|
||||
- **Prérequis:** vous devez être sur Windows 10 version 2004 ou ultérieure (build 19041 & versions ultérieures) ou Windows 11.
|
||||
- **Plus d'info:** [docs.microsoft.com](https://docs.microsoft.com/fr-fr/windows/wsl/install)
|
||||
|
||||
```shell
|
||||
# dans un shell Windows
|
||||
wsl --install
|
||||
|
||||
# afficher la liste des distribution disponible avec WSL
|
||||
wsl -l -o
|
||||
|
||||
# installer WSL avec une distro (ubuntu conseillé)
|
||||
wsl --install -d <nom_distro>
|
||||
```
|
||||
|
||||
Une fois `WSL` installé, mettez à jour votre distribution et
|
||||
installez les dépendances (voir la partie installation sous Ubuntu).
|
||||
|
||||
Pour accéder au contenu d'un répertoire externe à `WSL`,
|
||||
il suffit d'utiliser la commande suivante :
|
||||
|
||||
```bash
|
||||
# oui c'est beau, simple et efficace
|
||||
cd /mnt/<la_lettre_du_disque>/vos/fichiers/comme/dhab
|
||||
```
|
||||
|
||||
!!!note
|
||||
|
||||
A ce stade, si vous avez réussi votre installation de `WSL` ou bien qu'il
|
||||
était déjà installé, vous pouvez effectuer la mise en place du projet en suivant
|
||||
les instructions pour votre distribution.
|
||||
|
||||
### Installer les dépendances
|
||||
|
||||
=== "Linux"
|
||||
|
||||
=== "Debian/Ubuntu"
|
||||
|
||||
Si ce n'est pas déjà fait, installez Python :
|
||||
```bash
|
||||
sudo apt install python3
|
||||
# on sait jamais
|
||||
sudo apt install python-is-python3
|
||||
```
|
||||
Si vous utilisez Ubuntu 22.04 ou Ubuntu 24.04,
|
||||
votre version de Python devrait être compatible
|
||||
par défaut avec celle du projet.
|
||||
Si ce n'est pas le cas, nous vous conseillons
|
||||
d'utiliser [pyenv](https://github.com/pyenv/pyenv)
|
||||
|
||||
Puis installez les autres dépendances :
|
||||
|
||||
```bash
|
||||
sudo apt install build-essentials libssl-dev libjpeg-dev zlib1g-dev python-dev \
|
||||
libffi-dev python-dev-is-python3 libgraphviz-dev pkg-config \
|
||||
gettext git pipx
|
||||
|
||||
pipx install poetry
|
||||
```
|
||||
|
||||
=== "Arch Linux"
|
||||
|
||||
```bash
|
||||
sudo pacman -Syu # on s'assure que les dépôts et le système sont à jour
|
||||
|
||||
sudo pacman -S python
|
||||
|
||||
sudo pacman -S gcc git graphviz gettext graphviz pkgconf python-poetry
|
||||
```
|
||||
|
||||
=== "macOS"
|
||||
|
||||
Pour installer les dépendances, il est fortement recommandé d'installer le gestionnaire de paquets `homebrew <https://brew.sh/index_fr>`_.
|
||||
Il est également nécessaire d'avoir installé xcode
|
||||
|
||||
```bash
|
||||
echo 'export PATH="$(brew --prefix graphviz)/bin:$PATH"' >> ~/.zshrc
|
||||
echo 'export CFLAGS="-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -I $(brew --prefix graphviz)/include"' >> ~/.zshrc
|
||||
echo 'export LDFLAGS="-L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -L $(brew --prefix graphviz)/lib"' >> ~/.zshrc
|
||||
|
||||
brew install git python graphviz pipx
|
||||
pipx install poetry
|
||||
|
||||
# Pour bien configurer gettext
|
||||
brew link gettext # (suivez bien les instructions supplémentaires affichées)
|
||||
```
|
||||
|
||||
!!!note
|
||||
|
||||
Si vous rencontrez des erreurs lors de votre configuration, n'hésitez pas à vérifier l'état de votre installation homebrew avec :code:`brew doctor`
|
||||
|
||||
|
||||
## Finaliser l'installation
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ae-utbm/sith3.git
|
||||
cd sith3
|
||||
|
||||
# Création de l'environnement et installation des dépendances
|
||||
poetry install
|
||||
|
||||
# Activation de l'environnement virtuel
|
||||
poetry shell
|
||||
|
||||
# Installation de Xapian
|
||||
python ./manage.py install_xapian
|
||||
|
||||
# Prépare la base de données
|
||||
python ./manage.py setup
|
||||
|
||||
# Installe les traductions
|
||||
python ./manage.py compilemessages
|
||||
```
|
||||
|
||||
!!!note
|
||||
|
||||
La commande `install_xapian` est longue et affiche beaucoup
|
||||
de texte à l'écran.
|
||||
C'est normal, il ne faut pas avoir peur.
|
||||
|
||||
!!!note
|
||||
|
||||
Pour éviter d'avoir à utiliser la commande `poetry shell`
|
||||
systématiquement, il est possible de consulter [direnv](../howto/direnv.md).
|
||||
|
||||
## Configuration pour le développement
|
||||
|
||||
Lorsqu'on souhaite développer pour le site,
|
||||
il est nécessaire de passer le logiciel en mode debug
|
||||
dans les settings_custom.
|
||||
Il est aussi conseillé de définir l'URL du site sur localhost.
|
||||
Voici un script rapide pour le faire.
|
||||
|
||||
```bash
|
||||
echo "DEBUG=True" > sith/settings_custom.py
|
||||
echo 'SITH_URL = "localhost:8000"' >> sith/settings_custom.py
|
||||
```
|
||||
|
||||
## Démarrer le serveur de développement
|
||||
|
||||
Il faut toujours avoir préalablement activé
|
||||
l'environnement virtuel comme fait plus haut
|
||||
et se placer à la racine du projet.
|
||||
Il suffit ensuite d'utiliser cette commande :
|
||||
|
||||
```bash
|
||||
python manage.py runserver
|
||||
```
|
||||
|
||||
!!!note
|
||||
|
||||
Le serveur est alors accessible à l'adresse
|
||||
[http://localhost:8000](http://localhost:8000) ou bien [http://127.0.0.1:8000/](http://127.0.0.1:8000/).
|
||||
|
||||
## Générer la documentation
|
||||
|
||||
La documentation est automatiquement mise en ligne à chaque envoi de code sur GitHub.
|
||||
Pour l'utiliser en local ou globalement pour la modifier,
|
||||
il existe une commande du site qui génère
|
||||
la documentation et lance un serveur la rendant
|
||||
accessible à l'adresse [http://localhost:8080](http://localhost:8000).
|
||||
Cette commande génère la documentation à
|
||||
chacune de ses modifications,
|
||||
inutile de relancer le serveur à chaque fois.
|
||||
|
||||
!!!note
|
||||
|
||||
Les dépendances pour la documentation sont optionnelles.
|
||||
Avant de commencer à travailler sur la doc, il faut donc les installer
|
||||
avec la commande `poetry install --with docs`
|
||||
|
||||
```bash
|
||||
mkdocs serve
|
||||
```
|
||||
|
||||
## Lancer les tests
|
||||
|
||||
Pour lancer les tests, il suffit d'utiliser
|
||||
la commande suivante :
|
||||
|
||||
```bash
|
||||
# Lancer tous les tests
|
||||
pytest
|
||||
|
||||
# Lancer les tests de l'application core
|
||||
pytest core
|
||||
|
||||
# Lancer les tests de la classe UserRegistrationTest de core
|
||||
pytest core.tests.UserRegistrationTest
|
||||
|
||||
# Lancer une méthode en particulier de cette même classe
|
||||
pytest core.tests.UserRegistrationTest.test_register_user_form_ok
|
||||
```
|
||||
|
||||
!!!note
|
||||
|
||||
Certains tests sont un peu longs à tourner.
|
||||
Pour ne faire tourner que les tests les plus rapides,
|
||||
vous pouvez exécutez pytest ainsi :
|
||||
|
||||
```bash
|
||||
pytest -m "not slow"
|
||||
|
||||
# vous pouvez toujours faire comme au-dessus
|
||||
pytest core -m "not slow"
|
||||
```
|
||||
|
||||
A l'inverse, vous pouvez ne faire tourner que les tests
|
||||
lents en remplaçant `-m "not slow"` par `-m slow`.
|
||||
|
||||
De cette manière, votre processus de développement
|
||||
devrait être un peu plus fluide.
|
||||
Cependant, n'oubliez pas de bien faire tourner
|
||||
tous les tests avant de push un commit.
|
||||
|
||||
|
||||
|
||||
## Vérifier les dépendances Javascript
|
||||
|
||||
Une commande a été écrite pour vérifier les éventuelles mises
|
||||
à jour à faire sur les librairies Javascript utilisées.
|
||||
N'oubliez pas de mettre à jour à la fois le fichier
|
||||
de la librairie, mais également sa version dans `sith/settings.py`.
|
||||
|
||||
```bash
|
||||
# Vérifier les mises à jour
|
||||
python manage.py check_front
|
||||
```
|
198
docs/tutorial/perms.md
Normal file
198
docs/tutorial/perms.md
Normal file
@ -0,0 +1,198 @@
|
||||
|
||||
## Les permissions
|
||||
|
||||
Le site n'utilise pas le système de permissions intégré de Django,
|
||||
mais un système de conception maison.
|
||||
|
||||
### Protéger un modèle
|
||||
|
||||
La gestion des permissions se fait directement par modèle.
|
||||
Il existe trois niveaux de permission :
|
||||
|
||||
- Éditer des propriétés de l'objet
|
||||
- Éditer certaines valeurs l'objet
|
||||
- Voir l'objet
|
||||
|
||||
Chacune de ces permissions est vérifiée par une méthode
|
||||
dédiée de la classe `User` :
|
||||
|
||||
- Editer les propriéts : `User.is_owner(obj)`
|
||||
- Editer les valeurs : `User.can_edit(obj)`
|
||||
- Voir : `User.can_view(obj)`
|
||||
|
||||
Ces méthodes vont alors résoudre les permissions
|
||||
dans cet ordre :
|
||||
|
||||
1. Si l'objet possède une méthode `can_be_viewed_by(user)`
|
||||
(ou `can_be_edited_by(user)`, ou `is_owned_by(user)`)
|
||||
et que son appel renvoie `True`, l'utilisateur a la permission requise.
|
||||
2. Sinon, si le modèle de l'objet possède un attribut `view_groups`
|
||||
(ou `edit_groups`, ou `owner_group`) et que l'utilisateur
|
||||
est dans l'un des groupes indiqués, il a la permission requise.
|
||||
3. Sinon, on regarde si l'utilisateur a la permission de niveau supérieur
|
||||
(les droits `owner` impliquent les droits d'édition, et les droits
|
||||
d'édition impliquent les droits de vue).
|
||||
4. Si aucune des étapes si dessus ne permet d'établir que l'utilisateur
|
||||
n'a la permission requise, c'est qu'il ne l'a pas.
|
||||
|
||||
Voici un exemple d'implémentation de ce système :
|
||||
|
||||
=== "Avec les méthodes"
|
||||
|
||||
```python
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from core.models import User, Group
|
||||
|
||||
# Utilisation de la protection par fonctions
|
||||
class Article(models.Model):
|
||||
|
||||
title = models.CharField(_("title"), max_length=100)
|
||||
content = models.TextField(_("content"))
|
||||
|
||||
# Donne ou non les droits d'édition des propriétés de l'objet
|
||||
# Un utilisateur dans le bureau AE aura tous les droits sur cet objet
|
||||
def is_owned_by(self, user):
|
||||
return user.is_board_member
|
||||
|
||||
# Donne ou non les droits d'édition de l'objet
|
||||
# L'objet ne sera modifiable que par un utilisateur cotisant
|
||||
def can_be_edited_by(self, user):
|
||||
return user.is_subscribed
|
||||
|
||||
# Donne ou non les droits de vue de l'objet
|
||||
# Ici, l'objet n'est visible que par un utilisateur connecté
|
||||
def can_be_viewed_by(self, user):
|
||||
return not user.is_anonymous
|
||||
```
|
||||
|
||||
=== "Avec les groupes de permission"
|
||||
|
||||
```python
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from core.models import User, Group
|
||||
|
||||
class Article(models.Model):
|
||||
title = models.CharField(_("title"), max_length=100)
|
||||
content = models.TextField(_("content"))
|
||||
|
||||
# relation one-to-many
|
||||
# Groupe possédant l'objet
|
||||
# Donne les droits d'édition des propriétés de l'objet
|
||||
owner_group = models.ForeignKey(
|
||||
Group, related_name="owned_articles", default=settings.SITH_GROUP_ROOT_ID
|
||||
)
|
||||
|
||||
# relation many-to-many
|
||||
# Tous les groupes qui seront ajouté dans ce champ auront les droits d'édition de l'objet
|
||||
edit_groups = models.ManyToManyField(
|
||||
Group,
|
||||
related_name="editable_articles",
|
||||
verbose_name=_("edit groups"),
|
||||
blank=True,
|
||||
)
|
||||
|
||||
# relation many-to-many
|
||||
# Tous les groupes qui seront ajouté dans ce champ auront les droits de vue de l'objet
|
||||
view_groups = models.ManyToManyField(
|
||||
Group,
|
||||
related_name="viewable_articles",
|
||||
verbose_name=_("view groups"),
|
||||
blank=True,
|
||||
)
|
||||
```
|
||||
|
||||
### Appliquer les permissions
|
||||
|
||||
#### Dans un template
|
||||
|
||||
Il existe trois fonctions de base sur lesquelles
|
||||
reposent les vérifications de permission.
|
||||
Elles sont disponibles dans le contexte par défaut du
|
||||
moteur de template et peuvent être utilisées à tout moment.
|
||||
|
||||
- `can_edit_prop(obj, user)` : équivalent de `obj.is_owned_by(user)`
|
||||
- `can_edit(obj, user)` : équivalent de `obj.can_be_edited_by(user)`
|
||||
- `can_view(obj, user)` : équivalent de `obj.can_be_viewed_by(user)`
|
||||
|
||||
Voici un exemple d'utilisation dans un template :
|
||||
|
||||
```jinja
|
||||
{# ... #}
|
||||
{% if can_edit(club, user) %}
|
||||
<a href="{{ url('club:tools', club_id=club.id) }}">{{ club }}</a>
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
#### Dans une vue
|
||||
|
||||
Généralement, les vérifications de droits dans les templates
|
||||
se limitent aux urls à afficher puisqu'il
|
||||
ne faut normalement pas mettre de logique autre que d'affichage à l'intérieur
|
||||
(en réalité, c'est un principe qu'on a beaucoup violé, mais promis on le fera plus).
|
||||
C'est donc habituellement au niveau des vues que cela a lieu.
|
||||
|
||||
Notre système s'appuie sur un système de mixin
|
||||
à hériter lors de la création d'une vue basée sur une classe.
|
||||
Ces mixins ne sont compatibles qu'avec les classes récupérant
|
||||
un objet ou une liste d'objet.
|
||||
Dans le cas d'un seul objet,
|
||||
une permission refusée est levée lorsque l'utilisateur
|
||||
n'a pas le droit de visionner la page.
|
||||
Dans le cas d'une liste d'objet,
|
||||
le mixin filtre les objets non autorisés et si aucun ne l'est,
|
||||
l'utilisateur recevra une liste vide d'objet.
|
||||
|
||||
Voici un exemple d'utilisation en reprenant l'objet Article crée précédemment :
|
||||
|
||||
```python
|
||||
from django.views.generic import CreateView, ListView
|
||||
|
||||
from core.views import CanViewMixin, CanCreateMixin
|
||||
|
||||
from com.models import WeekmailArticle
|
||||
|
||||
# Il est important de mettre le mixin avant la classe héritée de Django
|
||||
# L'héritage multiple se fait de droite à gauche et les mixins ont besoin
|
||||
# d'une classe de base pour fonctionner correctement.
|
||||
class ArticlesListView(CanViewMixin, ListView):
|
||||
model = WeekmailArticle
|
||||
|
||||
|
||||
# Même chose pour une vue de création de l'objet Article
|
||||
class ArticlesCreateView(CanCreateMixin, CreateView):
|
||||
model = WeekmailArticle
|
||||
```
|
||||
|
||||
Les mixins suivants sont implémentés :
|
||||
|
||||
- `CanCreateMixin` : l'utilisateur peut-il créer l'objet ?
|
||||
- `CanEditPropMixin` : l'utilisateur peut-il éditer les propriétés de l'objet ?
|
||||
- `CanEditMixin` : L'utilisateur peut-il éditer l'objet ?
|
||||
- `CanViewMixin` : L'utilisateur peut-il voir l'objet ?
|
||||
- `UserIsRootMixin` : L'utilisateur a-t-il les droit root ?
|
||||
- `FormerSubscriberMixin` : L'utilisateur a-t-il déjà été cotisant ?
|
||||
- `UserIsLoggedMixin` : L'utilisateur est-il connecté ?
|
||||
(à éviter ; préférez `LoginRequiredMixin`, fourni par Django)
|
||||
|
||||
!!!danger "Performance"
|
||||
|
||||
Ce système maison de permissions ne rend pas trop mal, d'un point de vue esthétique.
|
||||
Mais d'un point de vue performance, c'est un désastre.
|
||||
Vérifier une seule permission peut demander plusieurs requêtes à la db.
|
||||
Et chaque vérification recommence dès le début.
|
||||
Il n'y a aucune jointure en db.
|
||||
Le mieux qu'on a trouvé comme pansement sur ça, c'est utiliser le cache,
|
||||
mais c'est seulement un pansement, qui ne rattrape pas les erreurs architecturales.
|
||||
|
||||
Sur une vue où on manipule un seul objet, passe encore.
|
||||
Mais sur les `ListView`, on peut arriver à des temps
|
||||
de réponse extrêmement élevés.
|
||||
|
||||
Faites donc doublement, triplement, quadruplement attention,
|
||||
quand vous manipulez le système de permissions.
|
||||
|
207
docs/tutorial/structure.md
Normal file
207
docs/tutorial/structure.md
Normal file
@ -0,0 +1,207 @@
|
||||
## La structure d'un projet Django
|
||||
|
||||
Un projet Django est structuré en applications.
|
||||
Une application est un package Python
|
||||
contenant un ensemble de vues, de modèles, de templates, etc.
|
||||
Sémantiquement, une application représente
|
||||
un ensemble de fonctionnalités cohérentes.
|
||||
Par exemple, dans notre cas, nous avons une application
|
||||
chargée de la gestion des comptoirs, une autre de la gestion
|
||||
des clubs, une autre de la gestion du SAS, etc.
|
||||
|
||||
On trouve généralement dans un projet Django
|
||||
une application principale qui contient les
|
||||
fichiers de configuration du projet,
|
||||
les urls et éventuellement des commandes d'administration.
|
||||
|
||||
## Arborescence du projet
|
||||
|
||||
Le code source du projet est organisé comme suit :
|
||||
|
||||
<div class="annotate">
|
||||
```
|
||||
sith3/
|
||||
├── .github/
|
||||
│ ├── actions/ (1)
|
||||
│ └── workflows/ (2)
|
||||
├── accounting/ (3)
|
||||
│ └── ...
|
||||
├── api/ (4)
|
||||
│ └── ...
|
||||
├── club/ (5)
|
||||
│ └── ...
|
||||
├── com/ (6)
|
||||
│ └── ...
|
||||
├── core/ (7)
|
||||
│ └── ...
|
||||
├── counter/ (8)
|
||||
│ └── ...
|
||||
├── docs/ (9)
|
||||
│ └── ...
|
||||
├── eboutic/ (10)
|
||||
│ └── ...
|
||||
├── election/ (11)
|
||||
│ └── ...
|
||||
├── forum/ (12)
|
||||
│ └── ...
|
||||
├── galaxy/ (13)
|
||||
│ └── ...
|
||||
├── launderette/ (14)
|
||||
│ └── ...
|
||||
├── locale/ (15)
|
||||
│ └── ...
|
||||
├── matmat/ (16)
|
||||
│ └── ...
|
||||
├── pedagogy/ (17)
|
||||
│ └── ...
|
||||
├── rootplace/ (18)
|
||||
│ └── ...
|
||||
├── sas/ (19)
|
||||
│ └── ...
|
||||
├── sith/ (20)
|
||||
│ └── ...
|
||||
├── stock/ (21)
|
||||
│ └── ...
|
||||
├── subscription/ (22)
|
||||
│ └── ...
|
||||
├── trombi/ (23)
|
||||
│ └── ...
|
||||
│
|
||||
├── .coveragerc (24)
|
||||
├── .envrc (25)
|
||||
├── .gitattributes
|
||||
├── .gitignore
|
||||
├── .mailmap
|
||||
├── .env.exemple
|
||||
├── manage.py (26)
|
||||
├── mkdocs.yml (27)
|
||||
├── poetry.lock
|
||||
├── pyproject.toml (28)
|
||||
└── README.md
|
||||
```
|
||||
</div>
|
||||
|
||||
1. Dossier contenant certaines actions réutilisables
|
||||
dans des workflows Github. Par exemple, l'action
|
||||
`setup-project` installe poetry puis appelle
|
||||
la commande `poetry install`.
|
||||
2. Dossier contenant les fichiers de configuration
|
||||
des workflows Github.
|
||||
Par exemple, le workflow `docs.yml` compile
|
||||
et publie la documentation à chaque push sur la branche `master`.
|
||||
3. Application de gestion de la comptabilité.
|
||||
4. Application contenant des routes d'API.
|
||||
5. Application de gestion des clubs et de leurs membres.
|
||||
6. Application contenant les fonctionnalités
|
||||
destinées aux responsables communication de l'AE.
|
||||
7. Application contenant la modélisation centrale du site.
|
||||
On en reparle plus loin sur cette page.
|
||||
8. Application de gestion des comptoirs, des permanences
|
||||
sur ces comptoirs et des transactions qui y sont effectuées.
|
||||
9. Dossier contenant la documentation.
|
||||
10. Application de gestion de la boutique en ligne.
|
||||
11. Application de gestion des élections.
|
||||
12. Application de gestion du forum
|
||||
13. Application de gestion de la galaxie ; la galaxie
|
||||
est un graphe des niveaux de proximité entre les différents
|
||||
étudiants.
|
||||
14. Gestion des machines à laver de l'AE
|
||||
15. Dossier contenant les fichiers de traduction.
|
||||
16. Fonctionnalités de recherche d'utilisateurs.
|
||||
17. Le guide des UEs du site, sur lequel les utilisateurs
|
||||
peuvent également laisser leurs avis.
|
||||
18. Fonctionnalités utiles aux utilisateurs root.
|
||||
19. Le SAS, où l'on trouve toutes les photos de l'AE.
|
||||
20. Application principale du projet, contenant sa configuration.
|
||||
21. Gestion des stocks des comptoirs.
|
||||
22. Gestion des cotisations des utilisateurs du site.
|
||||
23. Gestion des trombinoscopes.
|
||||
24. Fichier de configuration de coverage.
|
||||
25. Fichier de configuration de direnv.
|
||||
26. Fichier généré automatiquement par Django. C'est lui
|
||||
qui permet d'appeler des commandes de gestion du projet
|
||||
avec la syntaxe `python ./manage.py <nom de la commande>`
|
||||
27. Le fichier de configuration de la documentation,
|
||||
avec ses plugins et sa table des matières.
|
||||
28. Le fichier où sont déclarés les dépendances et la configuration
|
||||
de certaines d'entre elles.
|
||||
|
||||
|
||||
## L'application principale
|
||||
|
||||
L'application principale du projet est le package `sith`.
|
||||
Ce package contient les fichiers de configuration du projet,
|
||||
la racine des urls.
|
||||
|
||||
Il est organisé comme suit :
|
||||
|
||||
<div class="annotate">
|
||||
```
|
||||
sith/
|
||||
├── settings.py (1)
|
||||
├── settings_custom.py (2)
|
||||
├── toolbar_debug.py (3)
|
||||
├── urls.py (4)
|
||||
└── wsgi.py (5)
|
||||
```
|
||||
</div>
|
||||
|
||||
1. Fichier de configuration du projet.
|
||||
Ce fichier contient les paramètres de configuration du projet.
|
||||
Par exemple, il contient la liste des applications
|
||||
installées dans le projet.
|
||||
2. Configuration maison pour votre environnement.
|
||||
Toute variable que vous définissez dans ce fichier sera prioritaire
|
||||
sur la configuration donnée dans `settings.py`.
|
||||
3. Configuration de la barre de debug.
|
||||
C'est inutilisé en prod, mais c'est très pratique en développement.
|
||||
4. Fichier de configuration des urls du projet.
|
||||
5. Fichier de configuration pour le serveur WSGI.
|
||||
WSGI est un protocole de communication entre le serveur
|
||||
et les applications.
|
||||
Ce fichier ne vous servira sans doute pas sur un environnement
|
||||
de développement, mais il est nécessaire en production.
|
||||
|
||||
## Les applications
|
||||
|
||||
Les applications sont des packages Python.
|
||||
Dans ce projet, les applications sont généralement organisées
|
||||
comme suit :
|
||||
|
||||
<div class="annotate">
|
||||
```
|
||||
.
|
||||
├── migrations/ (1)
|
||||
│ └── ...
|
||||
├── templates/ (2)
|
||||
│ └── ...
|
||||
├── admin.py (3)
|
||||
├── models.py (4)
|
||||
├── tests.py (5)
|
||||
├── urls.py (6)
|
||||
└── views.py (7)
|
||||
```
|
||||
</div>
|
||||
|
||||
1. Dossier contenant les migrations de la base de données.
|
||||
Les migrations sont des fichiers Python qui permettent
|
||||
de mettre à jour la base de données.
|
||||
cf. [Gestion des migrations](../howto/migrations.md)
|
||||
2. Dossier contenant les templates jinja utilisés par cette application.
|
||||
3. Fichier de configuration de l'interface d'administration.
|
||||
Ce fichier permet de déclarer les modèles de l'application
|
||||
dans l'interface d'administration.
|
||||
4. Fichier contenant les modèles de l'application.
|
||||
Les modèles sont des classes Python qui représentent
|
||||
les tables de la base de données.
|
||||
5. Fichier contenant les tests de l'application.
|
||||
6. Configuration des urls de l'application.
|
||||
7. Fichier contenant les vues de l'application.
|
||||
Dans les plus grosses applications,
|
||||
ce fichier peut être remplacé par un package
|
||||
`views` dans lequel les vues sont réparties entre
|
||||
plusieurs fichiers.
|
||||
|
||||
L'organisation peut éventuellement être un peu différente
|
||||
pour certaines applications, mais le principe
|
||||
général est le même.
|
Reference in New Issue
Block a user