mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 15:50:03 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			152 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| Droits
 | |
| ======
 | |
| 
 | |
| Le système de droit par défaut de Django n'est pas suffisamment granulaire pour les besoins de la Note Kfet 2020.
 | |
| Un système personnalisé a donc été développé.
 | |
| 
 | |
| Il permet la création de Permission, qui autorise ou non a faire une action précise sur un ou des objets
 | |
| de la base de données.
 | |
| 
 | |
| Plusieurs permissions peuvent être regroupé dans un Role.
 | |
| Ce Role est relié a la responsabilité/fonction de la personne dans un Club. Ils sont valable au maximum tant que la
 | |
| personne est adhérente du Club concerné, mais ce rôle peut être modifié/supprimé avant le terme.
 | |
| 
 | |
| Permission
 | |
| ----------
 | |
| 
 | |
| Une permission est un Model Django dont les principaux attributs sont :
 | |
| 
 | |
| * ``model`` : Le model sur lequel cette permission va s'appliquer
 | |
| * ``type``  : Les différents types d'interaction sont : voir (``view``), modifier (``change``), ajouter (``add``)
 | |
|   et supprimer (``delete``).
 | |
| * ``query`` : Requête sur la cible, encodé en JSON, traduit en un Q object (cf `Query <#compilation-de-la-query>`_)
 | |
| * ``field`` : le champ cible qui pourra être modifié. (tous les champs si vide)
 | |
| 
 | |
| Pour savoir si un⋅e utilisateur⋅rice a le droit sur un modèle ou non, la requête est compilée (voir ci-dessous) en un filtre
 | |
| de requête dans la base de données, un objet de la classe ``Q`` (En SQL l'objet Q s'interprète comme tout ce qui suit
 | |
| un ``WHERE ...`` Ils peuvent être combiné à l'aide d'opérateurs logiques. Plus d'information sur les Q object dans la
 | |
| `documentation officielle <https://docs.djangoproject.com/fr/2.2/topics/db/queries/#complex-lookups-with-q-objects>`_.
 | |
| 
 | |
| Ce Q object sera donc utilisé pour savoir si l'instance que l'on veut modifier est concernée par notre permission.
 | |
| 
 | |
| Exception faite sur l'ajout d'objets : l'objet n'existant pas encore en base de données, il est ajouté puis supprimé
 | |
| à la volée, en prenant soin de désactiver les signaux.
 | |
| 
 | |
| Compilation de la query
 | |
| -----------------------
 | |
| 
 | |
| La query est enregistrée sous un format JSON, puis est traduite en requête ``Q`` récursivement en appliquant certains paramètres.
 | |
| Le fonctionnemente de base des permission peux être décris avec les différents opérations :
 | |
| 
 | |
| +----------------+-----------------------------+-------------------------------------+
 | |
| | opérations     | JSON                        | Q object                            |
 | |
| +================+=============================+=====================================+
 | |
| | ALL            | ``[]`` ou ``{}``            | ``.objects.get(Q(pk=F("pk"))``      |
 | |
| +----------------+-----------------------------+-------------------------------------+
 | |
| | ET             | ``["AND", Q_1, Q_2, ... ]`` | ``.objects.get(Q_1 & Q_2 & ...)``   |
 | |
| +----------------+-----------------------------+-------------------------------------+
 | |
| | OU             | ``["OR", Q_1, Q_2, ...]``   | ``.objects.get(Q_1 \| Q_2 \| ...)`` |
 | |
| +----------------+-----------------------------+-------------------------------------+
 | |
| | NON            | ``["NOT", Q_1]``            | ``.objects.get(~Q_1)``              |
 | |
| +----------------+-----------------------------+-------------------------------------+
 | |
| | key == value   | ``{key: value}``            | ``.objects.get(Q(key = value))``    |
 | |
| +----------------+-----------------------------+-------------------------------------+
 | |
| 
 | |
| 
 | |
| Vous n'avez rien compris ? Voilà des exemples :
 | |
| 
 | |
| Exemples
 | |
| --------
 | |
| 
 | |
| * Permission sur le model ``User`` avec comme query:
 | |
| 
 | |
|   .. code:: js
 | |
| 
 | |
|     {"is_superuser": true}
 | |
| 
 | |
|   | si l'utilisateur⋅rice cible est un⋅e super utilisateur⋅rice.
 | |
| 
 | |
| * sur le model ``Note`` :
 | |
| 
 | |
|   .. code:: js
 | |
| 
 | |
|     {"pk":
 | |
|       ["user","note", "pk"]
 | |
|     }
 | |
| 
 | |
|   |  si l'identifiant de la note cible est l'identifiant de l'utilisateur⋅rice dont on regarde la permission.
 | |
| 
 | |
| * sur le model ``Transaction``:
 | |
| 
 | |
|   .. code:: js
 | |
| 
 | |
|     ["AND",
 | |
|       {"source":
 | |
|         ["user", "note"]},
 | |
|       {"amount__lte":
 | |
|         ["user", "note", "balance"]}
 | |
|     ]
 | |
| 
 | |
|   | si la source est la note de l'utilisateur⋅rice et si le montant est inférieur à son solde.
 | |
| 
 | |
| * Sur le model ``Alias``
 | |
| 
 | |
|   .. code:: js
 | |
| 
 | |
|     ["OR",
 | |
|       {"note__in":
 | |
|         ["NoteUser", "objects",[
 | |
|           "filter",{
 | |
|             "user__membership__club__name": "Kfet"
 | |
|           }],
 | |
|           ["all"]
 | |
|         ]},
 | |
|       {"note__in":
 | |
|         ["NoteClub", "objects", ["all"]]
 | |
|       }
 | |
|     ]
 | |
| 
 | |
|   | si l'alias appartient à une note de club ou s'il appartient à la note d'un⋅e utilisateur⋅rice membre du club Kfet.
 | |
| 
 | |
| * sur le model ``Transaction``
 | |
| 
 | |
|   .. code:: js
 | |
| 
 | |
|     ["AND",
 | |
|       {"destination": ["club", "note"]},
 | |
|       {"amount__lte":
 | |
|          {"F": [
 | |
|            "ADD",
 | |
|            ["F", "source__balance"],
 | |
|            2000]
 | |
|          }
 | |
|        }
 | |
|     ]
 | |
| 
 | |
|   | si la destination est la note du club dont on est membre et si le montant est inférieur au solde de la source + 20 €,
 | |
|     autrement dit le solde final est au-dessus de -20 €.
 | |
| 
 | |
| 
 | |
| Masques de permissions
 | |
| ----------------------
 | |
| 
 | |
| Chaque permission est associée à un masque. À la connexion, l'utilisateur⋅rice choisit le masque de droits avec lequel iel
 | |
| souhaite se connecter. Les masques sont ordonnés totalement, et l'utilisateur⋅rice aura effectivement une permission si iel est
 | |
| en droit d'avoir la permission et si son masque est suffisamment haut.
 | |
| 
 | |
| Par exemple, si la permission de voir toutes les transactions est associée au masque « Droits note uniquement »,
 | |
| se connecter avec le masque « Droits basiques » n'octroiera pas cette permission tandis que le masque « Tous mes droits » oui.
 | |
| 
 | |
| Signaux
 | |
| -------
 | |
| 
 | |
| À chaque fois qu'un modèle est modifié, ajouté ou supprimé, les droits sont contrôlés. Si les droits ne sont pas
 | |
| suffisants, une erreur est lancée. Pour ce qui est de la modification, on ne contrôle que les champs réellement
 | |
| modifiés en comparant l'ancienne et la nouvelle instance.
 | |
| 
 | |
| Graphe des modèles
 | |
| ------------------
 | |
| 
 | |
| .. image:: ../_static/img/graphs/permission.svg
 | |
|    :alt: Graphe de l'application permission
 |