mixins.py 6.9 KB
Newer Older
1 2 3 4 5
# -*- mode: python; coding: utf-8 -*-
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il
# se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics.
#
6
# Copyright © 2018  Gabriel Détraz
7
# Copyright © 2017  Charlie Jacomme
8 9 10 11 12 13 14 15 16 17 18 19 20 21
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 23 24
"""re2o.mixins
A set of mixins used all over the project to avoid duplicating code
"""
25

26
from reversion import revisions as reversion
27
from django.db import transaction
28
from django.utils.translation import ugettext as _
29 30 31


class RevMixin(object):
32 33 34
    """ A mixin to subclass the save and delete function of a model
    to enforce the versioning of the object before those actions
    really happen """
35
    def save(self, *args, **kwargs):
36
        """ Creates a version of this object and save it to database """
37
        if self.pk is None:
38
            with transaction.atomic(), reversion.create_revision():
39
                reversion.set_comment("Creation")
40
                return super(RevMixin, self).save(*args, **kwargs)
41 42 43
        return super(RevMixin, self).save(*args, **kwargs)

    def delete(self, *args, **kwargs):
44
        """ Creates a version of this object and delete it from database """
45
        with transaction.atomic(), reversion.create_revision():
46
            reversion.set_comment("Deletion")
47
            return super(RevMixin, self).delete(*args, **kwargs)
48 49 50


class FormRevMixin(object):
51 52
    """ A mixin to subclass the save function of a form
    to enforce the versionning of the object before it is really edited """
53
    def save(self, *args, **kwargs):
54
        """ Create a version of this object and save it to database """
55
        if reversion.get_comment() != "" and self.changed_data != []:
Maël Kervella's avatar
Maël Kervella committed
56 57 58 59
            reversion.set_comment(
                reversion.get_comment() + ",%s"
                % ', '.join(field for field in self.changed_data)
            )
60
        elif self.changed_data:
Maël Kervella's avatar
Maël Kervella committed
61
            reversion.set_comment(
62
                "Field(s) altered : %s"
Maël Kervella's avatar
Maël Kervella committed
63 64
                % ', '.join(field for field in self.changed_data)
            )
65 66 67
        return super(FormRevMixin, self).save(*args, **kwargs)


68
class AclMixin(object):
Gabriel Detraz's avatar
Gabriel Detraz committed
69 70 71
    """This mixin is used in nearly every class/models defined in re2o apps.
    It is used by acl, in models (decorators can_...) and in templates tags
    :get_instance: Applied on a class, take an id argument, return an instance
Maël Kervella's avatar
Maël Kervella committed
72 73 74 75 76 77 78 79 80 81
    :can_create: Applied on a class, take the requested user, return if the
        user can do the creation
    :can_edit: Applied on an instance, return if the user can edit the
        instance
    :can_delete: Applied on an instance, return if the user can delete the
        instance
    :can_view: Applied on an instance, return if the user can view the
        instance
    :can_view_all: Applied on a class, return if the user can view all
        instances"""
Gabriel Detraz's avatar
Gabriel Detraz committed
82

83 84
    @classmethod
    def get_classname(cls):
85
        """ Returns the name of the class where this mixin is used """
86 87 88 89
        return str(cls.__name__).lower()

    @classmethod
    def get_modulename(cls):
90
        """ Returns the name of the module where this mixin is used """
91 92
        return str(cls.__module__).split('.')[0].lower()

93
    @classmethod
94
    def get_instance(cls, *_args, **kwargs):
95 96 97 98 99 100
        """Récupère une instance
        :param objectid: Instance id à trouver
        :return: Une instance de la classe évidemment"""
        object_id = kwargs.get(cls.get_classname() + 'id')
        return cls.objects.get(pk=object_id)

101
    @classmethod
102
    def can_create(cls, user_request, *_args, **_kwargs):
103 104
        """Verifie que l'user a les bons droits pour créer
        un object
105 106
        :param user_request: instance utilisateur qui fait la requête
        :return: soit True, soit False avec la raison de l'échec"""
Maël Kervella's avatar
Maël Kervella committed
107 108 109 110
        return (
            user_request.has_perm(
                cls.get_modulename() + '.add_' + cls.get_classname()
            ),
111 112
            (_("You don't have the right to create a %s object.")
                % cls.get_classname())
Maël Kervella's avatar
Maël Kervella committed
113
        )
114

115
    def can_edit(self, user_request, *_args, **_kwargs):
116 117 118
        """Verifie que l'user a les bons droits pour editer
        cette instance
        :param self: Instance à editer
119 120
        :param user_request: Utilisateur qui fait la requête
        :return: soit True, soit False avec la raison de l'échec"""
Maël Kervella's avatar
Maël Kervella committed
121 122 123 124
        return (
            user_request.has_perm(
                self.get_modulename() + '.change_' + self.get_classname()
            ),
125 126
            (_("You don't have the right to edit a %s object.")
                % self.get_classname())
Maël Kervella's avatar
Maël Kervella committed
127
        )
128

129
    def can_delete(self, user_request, *_args, **_kwargs):
130 131 132
        """Verifie que l'user a les bons droits pour delete
        cette instance
        :param self: Instance à delete
133 134
        :param user_request: Utilisateur qui fait la requête
        :return: soit True, soit False avec la raison de l'échec"""
Maël Kervella's avatar
Maël Kervella committed
135 136 137 138
        return (
            user_request.has_perm(
                self.get_modulename() + '.delete_' + self.get_classname()
            ),
139 140
            (_("You don't have the right to delete a %s object.")
                % self.get_classname())
Maël Kervella's avatar
Maël Kervella committed
141
        )
142 143

    @classmethod
144
    def can_view_all(cls, user_request, *_args, **_kwargs):
145
        """Vérifie qu'on peut bien afficher l'ensemble des objets,
146 147 148
        droit particulier view objet correspondant
        :param user_request: instance user qui fait l'edition
        :return: True ou False avec la raison de l'échec le cas échéant"""
Maël Kervella's avatar
Maël Kervella committed
149 150 151 152
        return (
            user_request.has_perm(
                cls.get_modulename() + '.view_' + cls.get_classname()
            ),
153 154
            (_("You don't have the right to view every %s object.")
                % cls.get_classname())
Maël Kervella's avatar
Maël Kervella committed
155
        )
156

157
    def can_view(self, user_request, *_args, **_kwargs):
158 159
        """Vérifie qu'on peut bien voir cette instance particulière avec
        droit view objet
160
        :param self: instance à voir
161 162
        :param user_request: instance user qui fait l'edition
        :return: True ou False avec la raison de l'échec le cas échéant"""
Maël Kervella's avatar
Maël Kervella committed
163 164 165 166
        return (
            user_request.has_perm(
                self.get_modulename() + '.view_' + self.get_classname()
            ),
167 168
            (_("You don't have the right to view a %s object.")
                % self.get_classname())
Maël Kervella's avatar
Maël Kervella committed
169
        )
170