mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-04-30 02:21:37 +00:00
Update Droits
parent
334ecfbd29
commit
b9f287e344
137
Apps/Droits.md
137
Apps/Droits.md
@ -8,73 +8,108 @@ Ce Role est relié a la responsabilité/fonction de la personne dans un Club. Il
|
||||
|
||||
## Permission
|
||||
|
||||
Une permission est, intuitivement, une formule logique indiquant si un utilisateur a le droit d'intéragir avec un modèle ou non. Cela peut concerner uniquement un champ d'un modèle.
|
||||
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` : Requete sur la cible, encodé en JSON, traduit en un Q object (cf [Query](#compilation-de-la-query)
|
||||
* `field` : le champ cible qui pourra etre modifié. (tous les champs si vide)
|
||||
|
||||
Les différents types d'interaction sont : voir (`view`), modifier (`change`), ajouter (`add`) et supprimer (`delete`).
|
||||
Pour savoir si un utilisateur a le droit sur un modèle ou non, la requête est compilée (voir ci-dessous) en un fitre de requête dans la base de données, un objet de la classe `Q` (En SQL l'objet Q s'interprete 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 officiel](https://docs.djangoproject.com/fr/2.2/topics/db/queries/#complex-lookups-with-q-objects) )
|
||||
|
||||
Pour savoir si un utilisateur a le droit sur un modèle ou non, la requête est compilée (voir ci-dessous) en un fitre de requête dans la base de données, un objet de la classe `Q`. Ensuite, il suffit d'appliquer ce filtre sur une requête à la base de données du modèle considéré, et voir si l'objet recherché est trouvé ou non.
|
||||
Ce Q object sera donc utilisé pour savoir si l'instance que l'on veux 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 requête
|
||||
## Compilation de la query
|
||||
|
||||
La requête est enregistrée sous un format JSON, puis est traduite en requête `Q` récursivement en appliquant certains paramètres (on note `about` la fonction de traduction) :
|
||||
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 differents opérations :
|
||||
|
||||
* `[] | {} -> Q(pk=F("pk"))` Une liste ou un objet vide représente tous les objets
|
||||
* `["AND", query, …] -> about(query) & … ` Conjonction de requêtes
|
||||
* `["OR", query, …] -> about(query) | … ` Disjonction de requêtes
|
||||
* `["NOT", query] -> ~about(query) ` Négation d'une requête
|
||||
* `{key: value, …} -> Q(key=value, …) ` Liste de champs et de valeurs dans un objet Q
|
||||
* `key` est une chaîne de caractères,représentant le nom du champ
|
||||
* `value` peut être de plusieurs natures :
|
||||
* Un nombre, une chaîne de caractères, un booléen, `null` pour représenter des valeurs littérales
|
||||
* Si c'est une liste, c'est interprété comme un paramètre
|
||||
* Le premier argument de la liste représente le nom du paramètre. Ce peut être l'objet utilisateur `user`, l'objet club `club` ou des objets de classe (`Note`, ...).
|
||||
* S'il y a des arguments suivants dans la liste, ils vont être interprétés comme des sous-attributs du paramètre initial.
|
||||
* Si un argument est une liste, alors c'est interprété comme une fonction à appeler, dont les arguments sont donnés par les autres éléments de la liste. Si cette liste contient un dictionnaire, le dictionnaire est passé en argument à la fonction sous la forme de kwargs.
|
||||
* Les exemples seront plus clairs.
|
||||
* Si c'est un dictionnaire de la forme {"F": oper}, alors c'est interprété comme un objet `F`.
|
||||
* Si `oper` est un littéral, il est interprété tel quel.
|
||||
* Si `oper = ["ADD", oper1, oper2, …]`, le résultat est la somme des objets `F` calculés d'après le reste de la liste.
|
||||
* Si `oper = ["SUB", oper1, oper2,]`, le résultat est la différence des deux objets `F`.
|
||||
* Si `oper = ["MUL", oper1, oper2, …]`, le résultat est le produit des objets `F` calculés d'après le reste de la liste.
|
||||
* Si `oper = ["F", name]`, le résultat est F(name).
|
||||
* Dans les autres cas, `oper` est un paramètre calculé comme précédemment.
|
||||
| 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))` |
|
||||
|
||||
De plus value peux être utilisé de différetentes manières:
|
||||
* Un nombre, une chaîne de caractères, un booléen, `null` pour représenter des valeurs littérales
|
||||
* Si c'est une liste, c'est interprété comme un paramètre
|
||||
* Le premier argument de la liste représente le nom du paramètre. Ce peut être l'objet utilisateur `user`, l'objet club `club` ou des objets de classe (`Note`, ...).
|
||||
* S'il y a des arguments suivants dans la liste, ils vont être interprétés comme des sous-attributs du paramètre initial.
|
||||
* Si un argument est une liste, alors c'est interprété comme une fonction à appeler, dont les arguments sont donnés par les autres éléments de la liste. Si cette liste contient un dictionnaire, le dictionnaire est passé en argument à la fonction sous la forme de kwargs.
|
||||
* Si c'est un dictionnaire de la forme {"F": oper}, alors c'est interprété comme un objet `F`.
|
||||
* Si `oper` est un littéral, il est interprété tel quel.
|
||||
* Si `oper = ["ADD", oper1, oper2, …]`, le résultat est la somme des objets `F` calculés d'après le reste de la liste.
|
||||
* Si `oper = ["SUB", oper1, oper2,]`, le résultat est la différence des deux objets `F`.
|
||||
* Si `oper = ["MUL", oper1, oper2, …]`, le résultat est le produit des objets `F` calculés d'après le reste de la liste.
|
||||
* Si `oper = ["F", name]`, le résultat est F(name).
|
||||
* Dans les autres cas, `oper` est un paramètre calculé comme précédemment.
|
||||
|
||||
Vous n'avez rien compris ? Voilà des exemples:
|
||||
## Exemples
|
||||
|
||||
Cette définition n'étant pas claire, voici quelques exemples facilitant la compréhension :
|
||||
* Permission sur le model `User` avec comme query:
|
||||
```js
|
||||
{"is_superuser": true}
|
||||
```
|
||||
> si l'utilisateur cible est un super utilisateur.
|
||||
|
||||
```js
|
||||
Modèle : User
|
||||
Q(is_superuser=True) := {"is_superuser": true}
|
||||
Permission accordée si l'utilisateur cible est un super utilisateur.
|
||||
```
|
||||
* sur le model `Note`:
|
||||
```js
|
||||
{"pk":
|
||||
["user","note", "pk"]
|
||||
}
|
||||
```
|
||||
> si l'identifiant de la note cible est l'identifiant de l'utilisateur dont on regarde la permission.
|
||||
|
||||
```js
|
||||
Modèle : Note
|
||||
Q(pk=user.note.pk) := {"pk": ["user", "note", "pk"]}
|
||||
Permission accordée si l'identifiant de la note cible est l'identifiant de l'utilisateur dont on regarde la permission.
|
||||
```
|
||||
* sur le model `Transaction`:
|
||||
|
||||
```js
|
||||
Modèle : Transaction
|
||||
["AND", {"source": ["user", "note"]}, {"amount__lte": ["user", "note", "balance"]}]
|
||||
Permission accordée si la source est la note de l'utilisateur et si le montant est inférieur à son solde.
|
||||
```
|
||||
```js
|
||||
["AND",
|
||||
{"source":
|
||||
["user", "note"]},
|
||||
{"amount__lte":
|
||||
["user", "note", "balance"]}
|
||||
]
|
||||
```
|
||||
> si la source est la note de l'utilisateur et si le montant est inférieur à son solde.
|
||||
|
||||
```js
|
||||
Modèle : Alias
|
||||
["OR", {"note__in": ["NoteUser", "objects", ["filter", {"user__membership__club__name": "Kfet"}], ["all"]]}, {"note__in": ["NoteClub", "objects", ["all"]]}]
|
||||
Permission accordée si l'alias appartient à une note de club ou s'il appartient à la note d'un utilisateur membre du club Kfet.
|
||||
```
|
||||
* Sur le model `Alias`
|
||||
|
||||
```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 utilisateur membre du club Kfet.
|
||||
|
||||
* sur le model `Transaction`
|
||||
|
||||
```js
|
||||
["AND",
|
||||
{"destination": ["club", "note"]},
|
||||
{"amount__lte":
|
||||
{"F": [
|
||||
"ADD",
|
||||
["F", "source__balance"],
|
||||
5000]
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
> si la destination est la note du club dont on est membre et si le montant est inférieur au solde de la source + 50 €, autrement dit le solde final est au-dessus de -50 €.
|
||||
|
||||
```js
|
||||
Modèle : Transaction
|
||||
["AND", {"destination": ["club", "note"]}, {"amount__lte": {"F": ["ADD", ["F", "source__balance"], 5000]}}]
|
||||
Permission accordée si la destination est la note du club dont on est membre et si le montant est inférieur au solde de la source + 50 €, autrement dit le solde final est au-dessus de -50 €.
|
||||
```
|
||||
|
||||
## Masques de permissions
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user