| **Website** is available here https://ae.utbm.fr/.
| **Documentation** is available here https://sith-ae.readthedocs.io/.
...
...
@@ -34,27 +26,4 @@ Sith AE
This project is licenced under GNU GPL, see the LICENSE file at the top of the repository for more details.
Controlling the rights
~~~~~~~~~~~~~~~~~~~~~~
When you need to protect an object, there are three levels:
* Editing the object properties
* Editing the object various values
* Viewing the object
Now you have many solutions in your model:
* You can define a :bash:`is_owned_by(self, user)`, a :bash:`can_be_edited_by(self, user)`, and/or a :bash:`can_be_viewed_by(self, user)` method, each returning True is the user passed can edit/view the object, False otherwise.
* This allows you to make complex request when the group solution is not powerful enough.
* It's useful too when you want to define class-wide permissions, e.g. the club members, that are viewable only for Subscribers.
* You can add an :bash:`owner_group` field, as a ForeignKey to Group. Second is an :bash:`edit_groups` field, as a ManyToMany to Group, and third is a :bash:`view_groups`, same as for edit.
Finally, when building a class based view, which is highly advised, you just have to inherit it from CanEditPropMixin,
CanEditMixin, or CanViewMixin, which are located in core.views. Your view will then be protected using either the
appropriate group fields, or the right method to check user permissions.
The code is written only in english but the documentation is written in french for comprehension reasons. It will not be written in english because it's too much work.
Lagestiondesdroitsdansl'association étant très complexe, le système de permissions intégré dans Django ne suffisait pas, il a donc fallu créer et intégrer le notre.
La gestion des permissions se fait directement sur un modèle, il existe trois niveaux de permission :
# Tous les groupes qui seront ajouté dans ce champ auront les droits d'éditiondel'objet
edit_group = models.ManyToManyField(
edit_groups = models.ManyToManyField(
Group,
related_name="editable_articles",
verbose_name=_("edit groups"),
blank=True,
)
)
# Doit être une liste
# 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,
)
Voicimaintenantcommentfaireendéfinissantdesfonctionspersonnalisées.Cettedeuxièmesolutionpermet,danslecasoùlapremièren'est pas assez puissante, de créer des permissions complexes et fines. Attention à bien les rendre lisibles et de bien documenter.
.. code-block:: python
from django.db import models
from django.utils.translation import ugettext_lazy as _
from core.views import *
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'éditiondespropriétésdel'objet
# Un utilisateur dans le bureau AE aura tous les droits sur cet objet
# Ici, l'objetn'est visible que par un utilisateur connecté
def can_be_viewed_by(self, user):
return not user.user.is_anonymous
.. note::
Si un utilisateur est autorisé à un niveau plus élevé que celui auquel il est testé, le système le détectera automatiquement et les droits lui seront accordé. Par défaut, les seuls utilisateur ayant des droits quelconques sont les *superuser* de Django et les membres du bureau AE qui sont définis comme *owner*.
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.
Tout d'abord,voicileurdocumentationetleurprototype.
..autofunction::core.views.can_edit_prop
..autofunction::core.views.can_edit
..autofunction::core.views.can_view
Voiciunexempled'utilisation dans un template :
.. code-block:: html+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 au liens à afficher puisqu'ilnefautpasmettredelogiqueautrequed'affichage à l'intérieur.C'est donc généralement au niveau des vues que cela a lieu.
Notre système s'appuiesurunsystèmedemixinàhériterlorsdelacréationd'une vue basée sur une classe. Ces mixins ne sont compatibles qu'aveclesclassesrécupérantunobjetouunelisted'objet. Dans le cas d'unseulobjet,unepermissionrefuséeestlevéelorsquel'utilisateur n'aspasledroitdevisionnerlapage.Dansled'une liste d'objet,lemixinfiltrelesobjetsnonautorisésetsiaucunnel'est l'utilisateurrecevraunelistevided'objet.
Voici un exemple d'utilisationenreprenantl'objet Article crée précédemment :
.. code-block:: python
from django.views.generic import CreateView, ListView
from core.views import CanViewMixin, CanCreateMixin
from .models import Article
...
# Il est important de mettre le mixin avant la classe héritée de Django