Projet

Général

Profil

0002-rbac-use-an-Operation-model-from-a2_rbac-58829.patch

Paul Marillonnet, 08 décembre 2021 10:27

Télécharger (26 ko)

Voir les différences:

Subject: [PATCH 2/3] rbac: use an Operation model from a2_rbac (#58829)

 src/authentic2/a2_rbac/apps.py                |   2 +
 src/authentic2/a2_rbac/managers.py            |  87 ++++++++++++-
 .../migrations/0024_fix_self_admin_perm.py    |   3 +-
 .../migrations/0026_auto_20211206_1604.py     |  31 +++++
 src/authentic2/a2_rbac/models.py              | 117 +++++++++++++++---
 src/authentic2/a2_rbac/signal_handlers.py     |  19 ++-
 src/authentic2/a2_rbac/utils.py               |  17 +--
 src/authentic2/data_transfer.py               |  10 +-
 .../management/commands/check-and-repair.py   |   4 +-
 src/authentic2/manager/forms.py               |   3 +-
 tests/test_a2_rbac.py                         |   2 +-
 tests/test_api.py                             |   2 +-
 tests/test_commands.py                        |  14 ++-
 tests/test_manager.py                         |   6 +-
 tests/test_user_manager.py                    |   5 +-
 15 files changed, 274 insertions(+), 48 deletions(-)
 create mode 100644 src/authentic2/a2_rbac/migrations/0026_auto_20211206_1604.py
src/authentic2/a2_rbac/apps.py
31 31
        # update rbac on save to contenttype, ou and roles
32 32
        post_save.connect(signal_handlers.update_rbac_on_ou_post_save, sender=models.OrganizationalUnit)
33 33
        post_delete.connect(signal_handlers.update_rbac_on_ou_post_delete, sender=models.OrganizationalUnit)
34
        # create CRUD operations and admin
35
        post_migrate.connect(signal_handlers.create_base_operations, sender=self)
34 36
        # keep service role and service ou field in sync
35 37
        for subclass in Service.__subclasses__():
36 38
            post_save.connect(signal_handlers.update_service_role_ou, sender=subclass)
src/authentic2/a2_rbac/managers.py
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
from django.contrib.contenttypes.models import ContentType
18
from django.db.models import Manager, query
19
from django.db.models.query import Q
18 20

  
19 21
from authentic2.a2_rbac import models
22
from authentic2.a2_rbac.utils import get_operation
20 23
from django_rbac.managers import AbstractBaseManager
21 24
from django_rbac.managers import RoleManager as BaseRoleManager
22
from django_rbac.models import ADMIN_OP
23
from django_rbac.utils import get_operation
24 25

  
25 26

  
26 27
class OrganizationalUnitManager(AbstractBaseManager):
......
28 29
        return self.get(slug=uuid)
29 30

  
30 31

  
32
class OperationManager(Manager):
33
    def get_by_natural_key(self, slug):
34
        return self.get(slug=slug)
35

  
36
    def has_perm(self, user, operation_slug, object_or_model, ou=None):
37
        """Test if an user can do the operation given by operation_slug
38
        on the given object_or_model eventually scoped by an organizational
39
        unit given by ou.
40

  
41
        Returns True or False.
42
        """
43
        ou_query = Q(ou__isnull=True)
44
        if ou:
45
            ou_query |= Q(ou=ou.as_scope())
46
        ct = ContentType.objects.get_for_model(object_or_model)
47
        target_query = Q(target_ct=ContentType.objects.get_for_model(ContentType), target_id=ct.pk)
48
        if isinstance(object_or_model, models.Model):
49
            target_query |= Q(target_ct=ct, target_id=object.pk)
50
        qs = models.Permission.objects.for_user(user)
51
        qs = qs.filter(operation__slug=operation_slug)
52
        qs = qs.filter(ou_query & target_query)
53
        return qs.exists()
54

  
55

  
56
class PermissionManagerBase(Manager):
57
    def get_by_natural_key(self, operation_slug, ou_nk, target_ct, target_nk):
58
        qs = self.filter(operation__slug=operation_slug)
59
        if ou_nk:
60
            try:
61
                ou = models.OrganizationalUnit.objects.get_by_natural_key(*ou_nk)
62
            except models.OrganizationalUnit.DoesNotExist:
63
                raise self.model.DoesNotExist
64
            qs = qs.filter(ou=ou)
65
        else:
66
            qs = qs.filter(ou__isnull=True)
67
        try:
68
            target_ct = ContentType.objects.get_by_natural_key(*target_ct)
69
        except ContentType.DoesNotExist:
70
            raise self.model.DoesNotExist
71
        target_model = target_ct.model_class()
72
        try:
73
            target = target_model.objects.get_by_natural_key(*target_nk)
74
        except target_model.DoesNotExist:
75
            raise self.model.DoesNotExist
76
        return qs.get(target_ct=ContentType.objects.get_for_model(target), target_id=target.pk)
77

  
78

  
79
class PermissionQueryset(query.QuerySet):
80
    def by_target_ct(self, target):
81
        """Filter permission whose target content-type matches the content
82
        type of the target argument
83
        """
84
        target_ct = ContentType.objects.get_for_model(target)
85
        return self.filter(target_ct=target_ct)
86

  
87
    def by_target(self, target):
88
        '''Filter permission whose target matches target'''
89
        return self.by_target_ct(target).filter(target_id=target.pk)
90

  
91
    def for_user(self, user):
92
        """Retrieve all permissions hold by an user through its role and
93
        inherited roles.
94
        """
95
        roles = models.Role.objects.for_user(user=user)
96
        return self.filter(roles__in=roles)
97

  
98
    def cleanup(self):
99
        count = 0
100
        for p in self:
101
            if not p.target and (p.target_ct_id or p.target_id):
102
                p.delete()
103
                count += 1
104
        return count
105

  
106

  
107
PermissionManager = PermissionManagerBase.from_queryset(PermissionQueryset)
108

  
109

  
31 110
class RoleManager(BaseRoleManager):
32 111
    def get_admin_role(
33 112
        self,
......
35 114
        name,
36 115
        slug,
37 116
        ou=None,
38
        operation=ADMIN_OP,
117
        operation=None,
39 118
        update_name=False,
40 119
        update_slug=False,
41 120
        permissions=(),
......
44 123
    ):
45 124
        '''Get or create the role of manager's of this object instance'''
46 125
        kwargs = {}
126
        if operation is None:
127
            operation = models.ADMIN_OP
47 128
        assert not ou or isinstance(
48 129
            instance, ContentType
49 130
        ), 'get_admin_role(ou=...) can only be used with ContentType instances: %s %s %s' % (
src/authentic2/a2_rbac/migrations/0024_fix_self_admin_perm.py
2 2

  
3 3
from django.db import migrations
4 4

  
5
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP
6
from django_rbac.models import CHANGE_OP
5
from authentic2.a2_rbac.models import CHANGE_OP, MANAGE_MEMBERS_OP
7 6

  
8 7

  
9 8
def update_self_administration_perm(apps, schema_editor):
src/authentic2/a2_rbac/migrations/0026_auto_20211206_1604.py
1
# Generated by Django 2.2.19 on 2021-12-06 15:04
2

  
3
import django.db.models.deletion
4
from django.db import migrations, models
5

  
6

  
7
class Migration(migrations.Migration):
8

  
9
    dependencies = [
10
        ('a2_rbac', '0025_auto_20210622_1132'),
11
    ]
12

  
13
    operations = [
14
        migrations.CreateModel(
15
            name='Operation',
16
            fields=[
17
                (
18
                    'id',
19
                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
20
                ),
21
                ('slug', models.CharField(max_length=32, unique=True, verbose_name='slug')),
22
            ],
23
        ),
24
        migrations.AlterField(
25
            model_name='permission',
26
            name='operation',
27
            field=models.ForeignKey(
28
                on_delete=django.db.models.deletion.CASCADE, to='a2_rbac.Operation', verbose_name='operation'
29
            ),
30
        ),
31
    ]
src/authentic2/a2_rbac/models.py
22 22
from django.core.validators import MinValueValidator
23 23
from django.db import models
24 24
from django.utils.text import slugify
25
from django.utils.translation import pgettext_lazy
25
from django.utils.translation import gettext, pgettext_lazy
26 26
from django.utils.translation import ugettext_lazy as _
27 27

  
28
from authentic2.a2_rbac.utils import get_operation
28 29
from authentic2.decorators import GlobalCache, errorcollector
29
from django_rbac import utils as rbac_utils
30
from django_rbac.models import (
31
    VIEW_OP,
32
    Operation,
33
    OrganizationalUnitAbstractBase,
34
    PermissionAbstractBase,
35
    RoleAbstractBase,
36
    RoleParentingAbstractBase,
37
)
30
from django_rbac.models import OrganizationalUnitAbstractBase, RoleAbstractBase, RoleParentingAbstractBase
38 31

  
39
from . import app_settings, fields, managers
32
from . import app_settings, fields
40 33

  
41 34

  
42 35
class OrganizationalUnit(OrganizationalUnitAbstractBase):
36
    from .managers import OrganizationalUnitManager
43 37

  
44 38
    RESET_LINK_POLICY = 0
45 39
    MANUAL_PASSWORD_POLICY = 1
......
105 99
        blank=True,
106 100
    )
107 101

  
108
    objects = managers.OrganizationalUnitManager()
102
    objects = OrganizationalUnitManager()
109 103

  
110 104
    class Meta:
111 105
        verbose_name = _('organizational unit')
......
187 181
OrganizationalUnit._meta.natural_key = [['uuid'], ['slug'], ['name']]
188 182

  
189 183

  
184
class Operation(models.Model):
185
    from .managers import OperationManager
186

  
187
    slug = models.CharField(max_length=32, verbose_name=_('slug'), unique=True)
188

  
189
    def natural_key(self):
190
        return [self.slug]
191

  
192
    def __str__(self):
193
        return str(self._registry.get(self.slug, self.slug))
194

  
195
    def export_json(self):
196
        return {'slug': self.slug}
197

  
198
    @property
199
    def name(self):
200
        return str(self)
201

  
202
    @classmethod
203
    def register(cls, name, slug):
204
        cls._registry[slug] = name
205
        return cls(slug=slug)
206

  
207
    _registry = {}
208

  
209
    objects = OperationManager()
210

  
211

  
212
Operation._meta.natural_key = ['slug']
213

  
214

  
215
class PermissionAbstractBase(models.Model):
216
    from .managers import PermissionManager
217

  
218
    operation = models.ForeignKey(to=Operation, verbose_name=_('operation'), on_delete=models.CASCADE)
219
    ou = models.ForeignKey(
220
        to=OrganizationalUnit,
221
        verbose_name=_('organizational unit'),
222
        related_name='scoped_permission',
223
        null=True,
224
        on_delete=models.CASCADE,
225
    )
226
    target_ct = models.ForeignKey(to='contenttypes.ContentType', related_name='+', on_delete=models.CASCADE)
227
    target_id = models.PositiveIntegerField()
228
    target = GenericForeignKey('target_ct', 'target_id')
229

  
230
    objects = PermissionManager()
231

  
232
    def natural_key(self):
233
        return [
234
            self.operation.slug,
235
            self.ou and self.ou.natural_key(),
236
            self.target and self.target_ct.natural_key(),
237
            self.target and self.target.natural_key(),
238
        ]
239

  
240
    def export_json(self):
241
        return {
242
            "operation": self.operation.natural_key_json(),
243
            "ou": self.ou and self.ou.natural_key_json(),
244
            'target_ct': self.target_ct.natural_key_json(),
245
            "target": self.target.natural_key_json(),
246
        }
247

  
248
    def __str__(self):
249
        ct = ContentType.objects.get_for_id(self.target_ct_id)
250
        ct_ct = ContentType.objects.get_for_model(ContentType)
251
        if ct == ct_ct:
252
            target = ContentType.objects.get_for_id(self.target_id)
253
            s = f'{self.operation} / {target}'
254
        else:
255
            s = f'{self.operation} / {ct} / {self.target}'
256
        if self.ou:
257
            s += gettext(' (scope "{0}")').format(self.ou)
258
        return s
259

  
260
    class Meta:
261
        abstract = True
262
        # FIXME: it's still allow non-unique permission with ou=null
263
        unique_together = (('operation', 'ou', 'target_ct', 'target_id'),)
264

  
265

  
190 266
class Permission(PermissionAbstractBase):
191 267
    class Meta:
192 268
        verbose_name = _('permission')
......
206 282

  
207 283

  
208 284
class Role(RoleAbstractBase):
285
    from .managers import RoleManager
286

  
209 287
    admin_scope_ct = models.ForeignKey(
210 288
        to='contenttypes.ContentType',
211 289
        null=True,
......
290 368
    def has_self_administration(self, op=None):
291 369
        if not op:
292 370
            op = MANAGE_MEMBERS_OP
293
        operation = rbac_utils.get_operation(op)
371
        operation = get_operation(op)
294 372
        self_perm, dummy = Permission.objects.get_or_create(
295 373
            operation=operation,
296 374
            target_ct=ContentType.objects.get_for_model(self),
......
303 381
        'Add permission to role so that it is self-administered'
304 382
        if not op:
305 383
            op = MANAGE_MEMBERS_OP
306
        operation = rbac_utils.get_operation(op)
384
        operation = get_operation(op)
307 385
        self_perm, dummy = Permission.objects.get_or_create(
308 386
            operation=operation, target_ct=ContentType.objects.get_for_model(self), target_id=self.pk
309 387
        )
......
313 391
    def is_internal(self):
314 392
        return self.slug.startswith('_')
315 393

  
316
    objects = managers.RoleManager()
394
    objects = RoleManager()
317 395

  
318 396
    class Meta:
319 397
        verbose_name = _('role')
......
413 491
)
414 492

  
415 493

  
494
# base rbac operations
495
ADMIN_OP = Operation.register(name=_('Management'), slug='admin')
496
CHANGE_OP = Operation.register(name=_('Change'), slug='change')
497
DELETE_OP = Operation.register(name=_('Delete'), slug='delete')
498
ADD_OP = Operation.register(name=_('Add'), slug='add')
499
VIEW_OP = Operation.register(name=_('View'), slug='view')
500
SEARCH_OP = Operation.register(name=_('Search'), slug='search')
501

  
502
# a2 specific operations
416 503
CHANGE_PASSWORD_OP = Operation.register(name=_('Change password'), slug='change_password')
417 504
RESET_PASSWORD_OP = Operation.register(name=_('Password reset'), slug='reset_password')
418 505
ACTIVATE_OP = Operation.register(name=_('Activation'), slug='activate')
src/authentic2/a2_rbac/signal_handlers.py
20 20
from django.utils.translation import override
21 21
from django.utils.translation import ugettext as _
22 22

  
23
from authentic2.a2_rbac.models import OrganizationalUnit, Role
23
from authentic2.a2_rbac.models import Operation, OrganizationalUnit, Role
24
from authentic2.a2_rbac.utils import get_operation
24 25
from authentic2.utils.misc import get_fk_model
25 26
from django_rbac.managers import defer_update_transitive_closure
26
from django_rbac.utils import get_operation
27 27

  
28 28

  
29 29
def create_default_ou(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs):
......
83 83
    Role.objects.filter(service=instance).update(ou=instance.ou)
84 84

  
85 85

  
86
def create_base_operations(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs):
87
    '''Create some basic operations, matching permissions from Django'''
88
    from .models import ADD_OP, ADMIN_OP, CHANGE_OP, DELETE_OP, SEARCH_OP, VIEW_OP
89

  
90
    if not router.allow_migrate(using, Operation):
91
        return
92

  
93
    get_operation(ADD_OP)
94
    get_operation(CHANGE_OP)
95
    get_operation(DELETE_OP)
96
    get_operation(VIEW_OP)
97
    get_operation(ADMIN_OP)
98
    get_operation(SEARCH_OP)
99

  
100

  
86 101
def create_default_permissions(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs):
87 102
    from .models import (
88 103
        ACTIVATE_OP,
src/authentic2/a2_rbac/utils.py
18 18
from django.contrib.contenttypes.models import ContentType
19 19
from django.utils.text import slugify
20 20

  
21
from django_rbac import utils as rbac_utils
22
from django_rbac.models import SEARCH_OP, VIEW_OP
23

  
24 21
from . import models
25 22

  
26 23

  
......
34 31
def get_view_user_perm(ou=None):
35 32
    User = get_user_model()
36 33
    view_user_perm, dummy = models.Permission.objects.get_or_create(
37
        operation=rbac_utils.get_operation(VIEW_OP),
34
        operation=get_operation(models.VIEW_OP),
38 35
        target_ct=ContentType.objects.get_for_model(ContentType),
39 36
        target_id=ContentType.objects.get_for_model(User).pk,
40 37
        ou__isnull=ou is None,
......
46 43
def get_search_ou_perm(ou=None):
47 44
    if ou:
48 45
        view_ou_perm, dummy = models.Permission.objects.get_or_create(
49
            operation=rbac_utils.get_operation(SEARCH_OP),
46
            operation=get_operation(models.SEARCH_OP),
50 47
            target_ct=ContentType.objects.get_for_model(ou),
51 48
            target_id=ou.pk,
52 49
            ou__isnull=True,
53 50
        )
54 51
    else:
55 52
        view_ou_perm, dummy = models.Permission.objects.get_or_create(
56
            operation=rbac_utils.get_operation(SEARCH_OP),
53
            operation=get_operation(models.SEARCH_OP),
57 54
            target_ct=ContentType.objects.get_for_model(ContentType),
58 55
            target_id=ContentType.objects.get_for_model(models.OrganizationalUnit).pk,
59 56
            ou__isnull=True,
......
64 61
def get_manage_authorizations_user_perm(ou=None):
65 62
    User = get_user_model()
66 63
    manage_authorizations_user_perm, dummy = models.Permission.objects.get_or_create(
67
        operation=rbac_utils.get_operation(models.MANAGE_AUTHORIZATIONS_OP),
64
        operation=get_operation(models.MANAGE_AUTHORIZATIONS_OP),
68 65
        target_ct=ContentType.objects.get_for_model(ContentType),
69 66
        target_id=ContentType.objects.get_for_model(User).pk,
70 67
        ou__isnull=ou is None,
......
73 70
    return manage_authorizations_user_perm
74 71

  
75 72

  
73
def get_operation(operation_tpl):
74

  
75
    operation, dummy = models.Operation.objects.get_or_create(slug=operation_tpl.slug)
76
    return operation
77

  
78

  
76 79
def generate_slug(name, seen_slugs=None):
77 80
    slug = base_slug = slugify(name).lstrip('_')
78 81
    if seen_slugs:
src/authentic2/data_transfer.py
24 24
from django.utils.text import format_lazy
25 25
from django.utils.translation import ugettext_lazy as _
26 26

  
27
from authentic2.a2_rbac.models import OrganizationalUnit, Permission, Role, RoleAttribute, RoleParenting
27
from authentic2.a2_rbac.models import (
28
    Operation,
29
    OrganizationalUnit,
30
    Permission,
31
    Role,
32
    RoleAttribute,
33
    RoleParenting,
34
)
28 35
from authentic2.decorators import errorcollector
29 36
from authentic2.utils.lazy import lazy_join
30
from django_rbac.models import Operation
31 37

  
32 38

  
33 39
def update_model(obj, d):
src/authentic2/management/commands/check-and-repair.py
29 29
from django.utils.timezone import localtime
30 30

  
31 31
from authentic2 import app_settings
32
from authentic2.a2_rbac.models import ADMIN_OP
32 33
from authentic2.a2_rbac.models import OrganizationalUnit as OU
33 34
from authentic2.a2_rbac.models import Permission, Role
35
from authentic2.a2_rbac.utils import get_operation
34 36
from authentic2.custom_user.models import User
35
from django_rbac.models import ADMIN_OP
36
from django_rbac.utils import get_operation
37 37

  
38 38
try:
39 39
    from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP  # pylint: disable=C0412
src/authentic2/manager/forms.py
30 30
from django.utils.translation import pgettext, ugettext
31 31
from django.utils.translation import ugettext_lazy as _
32 32

  
33
from authentic2.a2_rbac.models import OrganizationalUnit, Permission, Role
33
from authentic2.a2_rbac.models import Operation, OrganizationalUnit, Permission, Role
34 34
from authentic2.a2_rbac.utils import generate_slug, get_default_ou
35 35
from authentic2.forms.fields import CheckPasswordField, NewPasswordField, ValidatedEmailField
36 36
from authentic2.forms.profile import BaseUserForm
......
43 43
    send_templated_mail,
44 44
)
45 45
from django_rbac.backends import DjangoRBACBackend
46
from django_rbac.models import Operation
47 46

  
48 47
from . import app_settings, fields, utils
49 48

  
tests/test_a2_rbac.py
19 19
from django.core.exceptions import ValidationError
20 20
from django.core.management import call_command
21 21

  
22
from authentic2.a2_rbac.models import Operation
22 23
from authentic2.a2_rbac.models import OrganizationalUnit as OU
23 24
from authentic2.a2_rbac.models import Permission, Role, RoleAttribute
24 25
from authentic2.a2_rbac.utils import get_default_ou
25 26
from authentic2.custom_user.models import User
26 27
from authentic2.models import Service
27 28
from authentic2.utils.misc import get_hex_uuid
28
from django_rbac.models import Operation
29 29

  
30 30
from .utils import login, request_select2
31 31

  
tests/test_api.py
33 33
from requests.models import Response
34 34
from rest_framework import VERSION as drf_version
35 35

  
36
from authentic2.a2_rbac.models import SEARCH_OP
36 37
from authentic2.a2_rbac.models import OrganizationalUnit as OU
37 38
from authentic2.a2_rbac.models import Role
38 39
from authentic2.a2_rbac.utils import get_default_ou
39 40
from authentic2.apps.journal.models import Event, EventType
40 41
from authentic2.models import Attribute, AttributeValue, AuthorizedRole, PasswordReset, Service
41 42
from authentic2.utils.misc import good_next_url
42
from django_rbac.models import SEARCH_OP
43 43

  
44 44
from .utils import assert_event, basic_authorization_header, get_link_from_mail, login
45 45

  
tests/test_commands.py
26 26
from django.contrib.contenttypes.models import ContentType
27 27
from django.utils.timezone import now
28 28

  
29
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP, VIEW_OP, OrganizationalUnit, Permission, Role
30
from authentic2.a2_rbac.utils import get_default_ou
29
from authentic2.a2_rbac.models import (
30
    ADMIN_OP,
31
    MANAGE_MEMBERS_OP,
32
    VIEW_OP,
33
    Operation,
34
    OrganizationalUnit,
35
    Permission,
36
    Role,
37
)
38
from authentic2.a2_rbac.utils import get_default_ou, get_operation
31 39
from authentic2.custom_user.models import DeletedUser
32 40
from authentic2.models import UserExternalId
33 41
from authentic2_auth_oidc.models import OIDCAccount, OIDCProvider
34
from django_rbac.models import ADMIN_OP, Operation
35
from django_rbac.utils import get_operation
36 42

  
37 43
from .utils import call_command, login
38 44

  
tests/test_manager.py
27 27
from django.utils.encoding import force_bytes, force_str
28 28
from webtest import Upload
29 29

  
30
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP
30
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP, VIEW_OP
31 31
from authentic2.a2_rbac.models import OrganizationalUnit as OU
32 32
from authentic2.a2_rbac.models import Permission, Role
33
from authentic2.a2_rbac.utils import get_default_ou
33
from authentic2.a2_rbac.utils import get_default_ou, get_operation
34 34
from authentic2.apps.journal.models import Event
35 35
from authentic2.models import Service
36 36
from authentic2.validators import EmailValidator
37
from django_rbac.models import VIEW_OP
38
from django_rbac.utils import get_operation
39 37

  
40 38
from .utils import assert_event, get_link_from_mail, login, request_select2
41 39

  
tests/test_user_manager.py
27 27
from django.urls import reverse
28 28
from webtest import Upload
29 29

  
30
from authentic2.a2_rbac.models import VIEW_OP
30 31
from authentic2.a2_rbac.models import OrganizationalUnit as OU
31 32
from authentic2.a2_rbac.models import Permission, Role
32
from authentic2.a2_rbac.utils import get_default_ou, get_view_user_perm
33
from authentic2.a2_rbac.utils import get_default_ou, get_operation, get_view_user_perm
33 34
from authentic2.apps.journal.models import Event
34 35
from authentic2.custom_user.models import User
35 36
from authentic2.manager import user_import
36 37
from authentic2.models import Attribute, AttributeValue
37 38
from authentic2_idp_oidc.models import OIDCAuthorization, OIDCClient
38
from django_rbac.models import VIEW_OP
39
from django_rbac.utils import get_operation
40 39

  
41 40
from .utils import get_link_from_mail, login, logout
42 41

  
43
-