0001-a2_rbac-move-signal-handlers-from-django_rbac-69902.patch
src/authentic2/a2_rbac/apps.py | ||
---|---|---|
25 | 25 |
from django.db.models.signals import post_delete, post_migrate, post_save |
26 | 26 | |
27 | 27 |
from authentic2.models import Service |
28 |
from django_rbac import utils |
|
28 | 29 | |
29 |
from . import models, signal_handlers |
|
30 |
from . import models, signal_handlers, signals
|
|
30 | 31 | |
32 |
# update role parenting when new role parenting is created |
|
33 |
post_save.connect(signal_handlers.role_parenting_post_save, sender=utils.get_role_parenting_model()) |
|
34 |
# update role parenting when role parenting is deleted |
|
35 |
post_delete.connect( |
|
36 |
signal_handlers.role_parenting_post_delete, sender=utils.get_role_parenting_model() |
|
37 |
) |
|
38 |
# or soft-created |
|
39 |
signals.post_soft_create.connect( |
|
40 |
signal_handlers.role_parenting_post_soft_delete, sender=utils.get_role_parenting_model() |
|
41 |
) |
|
42 |
# or soft-deleted |
|
43 |
signals.post_soft_delete.connect( |
|
44 |
signal_handlers.role_parenting_post_soft_delete, sender=utils.get_role_parenting_model() |
|
45 |
) |
|
46 |
# create CRUD operations and admin |
|
47 |
post_migrate.connect(signal_handlers.create_base_operations, sender=self) |
|
48 |
# update role parenting in post migrate |
|
49 |
post_migrate.connect(signal_handlers.fix_role_parenting_closure, sender=self) |
|
31 | 50 |
# update rbac on save to contenttype, ou and roles |
32 | 51 |
post_save.connect(signal_handlers.update_rbac_on_ou_post_save, sender=models.OrganizationalUnit) |
33 | 52 |
post_delete.connect(signal_handlers.update_rbac_on_ou_post_delete, sender=models.OrganizationalUnit) |
src/authentic2/a2_rbac/managers.py | ||
---|---|---|
19 | 19 |
from authentic2.a2_rbac import models |
20 | 20 |
from django_rbac.managers import AbstractBaseManager |
21 | 21 |
from django_rbac.managers import RoleManager as BaseRoleManager |
22 |
from django_rbac.models import ADMIN_OP |
|
23 | 22 |
from django_rbac.utils import get_operation |
24 | 23 | |
25 | 24 | |
... | ... | |
35 | 34 |
name, |
36 | 35 |
slug, |
37 | 36 |
ou=None, |
38 |
operation=ADMIN_OP,
|
|
37 |
operation=None,
|
|
39 | 38 |
update_name=False, |
40 | 39 |
update_slug=False, |
41 | 40 |
permissions=(), |
... | ... | |
43 | 42 |
create=True, |
44 | 43 |
): |
45 | 44 |
'''Get or create the role of manager's of this object instance''' |
45 |
from .models import ADMIN_OP |
|
46 | ||
47 |
if operation is None: |
|
48 |
operation = ADMIN_OP |
|
49 | ||
46 | 50 |
kwargs = {} |
47 | 51 |
assert not ou or isinstance( |
48 | 52 |
instance, ContentType |
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/models.py | ||
---|---|---|
39 | 39 |
from authentic2.validators import HexaColourValidator |
40 | 40 |
from django_rbac import managers as rbac_managers |
41 | 41 |
from django_rbac import utils as rbac_utils |
42 |
from django_rbac.models import VIEW_OP, Operation
|
|
42 |
from django_rbac.models import Operation |
|
43 | 43 | |
44 | 44 |
from . import app_settings, fields, managers |
45 | 45 | |
... | ... | |
759 | 759 |
) |
760 | 760 | |
761 | 761 | |
762 |
ADMIN_OP = Operation.register(name=pgettext_lazy('permission', 'Management'), slug='admin') |
|
763 |
CHANGE_OP = Operation.register(name=pgettext_lazy('permission', 'Change'), slug='change') |
|
764 |
DELETE_OP = Operation.register(name=pgettext_lazy('permission', 'Delete'), slug='delete') |
|
765 |
ADD_OP = Operation.register(name=pgettext_lazy('permission', 'Add'), slug='add') |
|
766 |
VIEW_OP = Operation.register(name=pgettext_lazy('permission', 'View'), slug='view') |
|
767 |
SEARCH_OP = Operation.register(name=pgettext_lazy('permission', 'Search'), slug='search') |
|
762 | 768 |
CHANGE_PASSWORD_OP = Operation.register(name=_('Change password'), slug='change_password') |
763 | 769 |
RESET_PASSWORD_OP = Operation.register(name=_('Password reset'), slug='reset_password') |
764 | 770 |
ACTIVATE_OP = Operation.register(name=_('Activation'), slug='activate') |
src/authentic2/a2_rbac/signal_handlers.py | ||
---|---|---|
23 | 23 |
from authentic2.a2_rbac.models import OrganizationalUnit, Role |
24 | 24 |
from authentic2.utils.misc import get_fk_model |
25 | 25 |
from django_rbac.managers import defer_update_transitive_closure |
26 |
from django_rbac.utils import get_operation |
|
26 |
from django_rbac.utils import get_operation, get_role_parenting_model
|
|
27 | 27 | |
28 | 28 | |
29 | 29 |
def create_default_ou(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): |
... | ... | |
103 | 103 |
get_operation(CHANGE_EMAIL_OP) |
104 | 104 |
get_operation(MANAGE_MEMBERS_OP) |
105 | 105 |
get_operation(MANAGE_AUTHORIZATIONS_OP) |
106 | ||
107 | ||
108 |
def role_parenting_post_save(sender, instance, raw, created, **kwargs): |
|
109 |
'''Close the role parenting relation after instance creation''' |
|
110 |
if raw: # do nothing if save comes from fixture loading |
|
111 |
return |
|
112 |
if not instance.direct: # do nothing if instance is not direct |
|
113 |
return |
|
114 |
sender.objects.update_transitive_closure() |
|
115 | ||
116 | ||
117 |
def role_parenting_post_delete(sender, instance, **kwargs): |
|
118 |
'''Close the role parenting relation after instance deletion''' |
|
119 |
if not instance.direct: # do nothing if instance is not direct |
|
120 |
return |
|
121 |
sender.objects.update_transitive_closure() |
|
122 | ||
123 | ||
124 |
def role_parenting_post_soft_delete(sender, instance, **kwargs): |
|
125 |
'''Close the role parenting relation after instance soft-deletion''' |
|
126 |
sender.objects.update_transitive_closure() |
|
127 | ||
128 | ||
129 |
def create_base_operations(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): |
|
130 |
'''Create some basic operations, matching permissions from Django''' |
|
131 |
from . import models |
|
132 | ||
133 |
if not router.allow_migrate(using, models.Operation): |
|
134 |
return |
|
135 | ||
136 |
get_operation(models.ADD_OP) |
|
137 |
get_operation(models.CHANGE_OP) |
|
138 |
get_operation(models.DELETE_OP) |
|
139 |
get_operation(models.VIEW_OP) |
|
140 |
get_operation(models.ADMIN_OP) |
|
141 |
get_operation(models.SEARCH_OP) |
|
142 | ||
143 | ||
144 |
def fix_role_parenting_closure(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): |
|
145 |
'''Close the role parenting relation after migrations''' |
|
146 |
if not router.allow_migrate(using, get_role_parenting_model()): |
|
147 |
return |
|
148 |
get_role_parenting_model().objects.update_transitive_closure() |
src/authentic2/a2_rbac/utils.py | ||
---|---|---|
19 | 19 |
from django.utils.text import slugify |
20 | 20 | |
21 | 21 |
from django_rbac import utils as rbac_utils |
22 |
from django_rbac.models import SEARCH_OP, VIEW_OP |
|
23 | 22 | |
24 | 23 |
from . import models |
25 | 24 | |
... | ... | |
38 | 37 |
def get_view_user_perm(ou=None): |
39 | 38 |
User = get_user_model() |
40 | 39 |
view_user_perm, dummy = models.Permission.objects.get_or_create( |
41 |
operation=rbac_utils.get_operation(VIEW_OP), |
|
40 |
operation=rbac_utils.get_operation(models.VIEW_OP),
|
|
42 | 41 |
target_ct=ContentType.objects.get_for_model(ContentType), |
43 | 42 |
target_id=ContentType.objects.get_for_model(User).pk, |
44 | 43 |
ou__isnull=ou is None, |
... | ... | |
50 | 49 |
def get_search_ou_perm(ou=None): |
51 | 50 |
if ou: |
52 | 51 |
view_ou_perm, dummy = models.Permission.objects.get_or_create( |
53 |
operation=rbac_utils.get_operation(SEARCH_OP), |
|
52 |
operation=rbac_utils.get_operation(models.SEARCH_OP),
|
|
54 | 53 |
target_ct=ContentType.objects.get_for_model(ou), |
55 | 54 |
target_id=ou.pk, |
56 | 55 |
ou__isnull=True, |
57 | 56 |
) |
58 | 57 |
else: |
59 | 58 |
view_ou_perm, dummy = models.Permission.objects.get_or_create( |
60 |
operation=rbac_utils.get_operation(SEARCH_OP), |
|
59 |
operation=rbac_utils.get_operation(models.SEARCH_OP),
|
|
61 | 60 |
target_ct=ContentType.objects.get_for_model(ContentType), |
62 | 61 |
target_id=ContentType.objects.get_for_model(models.OrganizationalUnit).pk, |
63 | 62 |
ou__isnull=True, |
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 |
34 | 35 |
from authentic2.custom_user.models import User |
35 |
from django_rbac.models import ADMIN_OP |
|
36 | 36 |
from django_rbac.utils import get_operation |
37 | 37 | |
38 | 38 |
try: |
src/django_rbac/apps.py | ||
---|---|---|
4 | 4 |
class DjangoRBACConfig(AppConfig): |
5 | 5 |
name = 'django_rbac' |
6 | 6 |
verbose_name = 'RBAC engine for Django' |
7 | ||
8 |
def ready(self): |
|
9 |
from django.db.models.signals import post_delete, post_migrate, post_save |
|
10 | ||
11 |
from . import signal_handlers, signals, utils |
|
12 | ||
13 |
# update role parenting when new role parenting is created |
|
14 |
post_save.connect(signal_handlers.role_parenting_post_save, sender=utils.get_role_parenting_model()) |
|
15 |
# update role parenting when role parenting is deleted |
|
16 |
post_delete.connect( |
|
17 |
signal_handlers.role_parenting_post_delete, sender=utils.get_role_parenting_model() |
|
18 |
) |
|
19 |
# or soft-created |
|
20 |
signals.post_soft_create.connect( |
|
21 |
signal_handlers.role_parenting_post_soft_delete, sender=utils.get_role_parenting_model() |
|
22 |
) |
|
23 |
# or soft-deleted |
|
24 |
signals.post_soft_delete.connect( |
|
25 |
signal_handlers.role_parenting_post_soft_delete, sender=utils.get_role_parenting_model() |
|
26 |
) |
|
27 |
# create CRUD operations and admin |
|
28 |
post_migrate.connect(signal_handlers.create_base_operations, sender=self) |
|
29 |
# update role parenting in post migrate |
|
30 |
post_migrate.connect(signal_handlers.fix_role_parenting_closure, sender=self) |
src/django_rbac/managers.py | ||
---|---|---|
9 | 9 |
from django.db.models.query import Prefetch, Q |
10 | 10 |
from django.db.transaction import atomic |
11 | 11 | |
12 |
from . import signals, utils |
|
12 |
from authentic2.a2_rbac import signals |
|
13 | ||
14 |
from . import utils |
|
13 | 15 | |
14 | 16 | |
15 | 17 |
class AbstractBaseManager(models.Manager): |
... | ... | |
210 | 212 |
signals.post_soft_create.send(sender=self.model, instance=rp) |
211 | 213 | |
212 | 214 |
def soft_delete(self, parent, child): |
213 |
from . import signals |
|
214 | ||
215 | 215 |
qs = self.filter(parent=parent, child=child, deleted__isnull=True, direct=True) |
216 | 216 |
with atomic(savepoint=False): |
217 | 217 |
rp = qs.first() |
src/django_rbac/models.py | ||
---|---|---|
1 | 1 |
from django.db import models |
2 | 2 |
from django.utils.translation import gettext_lazy as _ |
3 |
from django.utils.translation import pgettext_lazy |
|
4 | 3 | |
5 | 4 |
from . import managers |
6 | 5 | |
... | ... | |
32 | 31 | |
33 | 32 | |
34 | 33 |
Operation._meta.natural_key = ['slug'] |
35 | ||
36 | ||
37 |
ADMIN_OP = Operation.register(name=pgettext_lazy('permission', 'Management'), slug='admin') |
|
38 |
CHANGE_OP = Operation.register(name=pgettext_lazy('permission', 'Change'), slug='change') |
|
39 |
DELETE_OP = Operation.register(name=pgettext_lazy('permission', 'Delete'), slug='delete') |
|
40 |
ADD_OP = Operation.register(name=pgettext_lazy('permission', 'Add'), slug='add') |
|
41 |
VIEW_OP = Operation.register(name=pgettext_lazy('permission', 'View'), slug='view') |
|
42 |
SEARCH_OP = Operation.register(name=pgettext_lazy('permission', 'Search'), slug='search') |
src/django_rbac/signal_handlers.py | ||
---|---|---|
1 |
from django.db import DEFAULT_DB_ALIAS, router |
|
2 | ||
3 |
from . import models, utils |
|
4 | ||
5 | ||
6 |
def role_parenting_post_save(sender, instance, raw, created, **kwargs): |
|
7 |
'''Close the role parenting relation after instance creation''' |
|
8 |
if raw: # do nothing if save comes from fixture loading |
|
9 |
return |
|
10 |
if not instance.direct: # do nothing if instance is not direct |
|
11 |
return |
|
12 |
sender.objects.update_transitive_closure() |
|
13 | ||
14 | ||
15 |
def role_parenting_post_delete(sender, instance, **kwargs): |
|
16 |
'''Close the role parenting relation after instance deletion''' |
|
17 |
if not instance.direct: # do nothing if instance is not direct |
|
18 |
return |
|
19 |
sender.objects.update_transitive_closure() |
|
20 | ||
21 | ||
22 |
def role_parenting_post_soft_delete(sender, instance, **kwargs): |
|
23 |
'''Close the role parenting relation after instance soft-deletion''' |
|
24 |
sender.objects.update_transitive_closure() |
|
25 | ||
26 | ||
27 |
def create_base_operations(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): |
|
28 |
'''Create some basic operations, matching permissions from Django''' |
|
29 |
if not router.allow_migrate(using, models.Operation): |
|
30 |
return |
|
31 | ||
32 |
utils.get_operation(models.ADD_OP) |
|
33 |
utils.get_operation(models.CHANGE_OP) |
|
34 |
utils.get_operation(models.DELETE_OP) |
|
35 |
utils.get_operation(models.VIEW_OP) |
|
36 |
utils.get_operation(models.ADMIN_OP) |
|
37 |
utils.get_operation(models.SEARCH_OP) |
|
38 | ||
39 | ||
40 |
def fix_role_parenting_closure(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): |
|
41 |
'''Close the role parenting relation after migrations''' |
|
42 |
if not router.allow_migrate(using, utils.get_role_parenting_model()): |
|
43 |
return |
|
44 |
utils.get_role_parenting_model().objects.update_transitive_closure() |
tests/api/test_all.py | ||
---|---|---|
32 | 32 |
from django.utils.text import slugify |
33 | 33 |
from requests.models import Response |
34 | 34 | |
35 |
from authentic2.a2_rbac.models import SEARCH_OP |
|
35 | 36 |
from authentic2.a2_rbac.models import OrganizationalUnit as OU |
36 | 37 |
from authentic2.a2_rbac.models import Role |
37 | 38 |
from authentic2.a2_rbac.utils import get_default_ou |
... | ... | |
40 | 41 |
from authentic2.models import APIClient, Attribute, AttributeValue, AuthorizedRole, PasswordReset, Service |
41 | 42 |
from authentic2.utils.misc import good_next_url |
42 | 43 |
from authentic2_idp_cas.models import Service as CASService |
43 |
from django_rbac.models import SEARCH_OP |
|
44 | 44 | |
45 | 45 |
from ..utils import assert_event, basic_authorization_header, get_link_from_mail, login |
46 | 46 |
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 MANAGE_MEMBERS_OP |
|
22 |
from authentic2.a2_rbac.models import CHANGE_OP, MANAGE_MEMBERS_OP
|
|
23 | 23 |
from authentic2.a2_rbac.models import OrganizationalUnit as OU |
24 | 24 |
from authentic2.a2_rbac.models import Permission, Role, RoleAttribute |
25 | 25 |
from authentic2.a2_rbac.utils import get_default_ou |
26 | 26 |
from authentic2.custom_user.models import User |
27 | 27 |
from authentic2.models import Service |
28 | 28 |
from authentic2.utils.misc import get_hex_uuid |
29 |
from django_rbac.models import CHANGE_OP, Operation
|
|
29 |
from django_rbac.models import Operation |
|
30 | 30 |
from tests.utils import login, request_select2, scoped_db_fixture |
31 | 31 | |
32 | 32 |
tests/test_api_client.py | ||
---|---|---|
6 | 6 |
from django.contrib.contenttypes.models import ContentType |
7 | 7 |
from django.urls import reverse |
8 | 8 | |
9 |
from authentic2.a2_rbac.models import Role |
|
9 |
from authentic2.a2_rbac.models import ADD_OP, SEARCH_OP, VIEW_OP, Role
|
|
10 | 10 |
from authentic2.models import APIClient |
11 |
from django_rbac.models import ADD_OP, SEARCH_OP, VIEW_OP |
|
12 | 11 | |
13 | 12 |
User = get_user_model() |
14 | 13 |
tests/test_commands.py | ||
---|---|---|
27 | 27 |
from django.utils.timezone import now |
28 | 28 |
from jwcrypto.jwk import JWK, JWKSet |
29 | 29 | |
30 |
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP, VIEW_OP, OrganizationalUnit, Permission, Role |
|
30 |
from authentic2.a2_rbac.models import ( |
|
31 |
ADMIN_OP, |
|
32 |
MANAGE_MEMBERS_OP, |
|
33 |
VIEW_OP, |
|
34 |
OrganizationalUnit, |
|
35 |
Permission, |
|
36 |
Role, |
|
37 |
) |
|
31 | 38 |
from authentic2.a2_rbac.utils import get_default_ou |
32 | 39 |
from authentic2.apps.journal.models import Event |
33 | 40 |
from authentic2.custom_user.models import DeletedUser |
34 | 41 |
from authentic2.models import UserExternalId |
35 | 42 |
from authentic2_auth_oidc.models import OIDCAccount, OIDCProvider |
36 |
from django_rbac.models import ADMIN_OP, Operation
|
|
43 |
from django_rbac.models import Operation |
|
37 | 44 |
from django_rbac.utils import get_operation |
38 | 45 | |
39 | 46 |
from .utils import call_command, login |
tests/test_manager.py | ||
---|---|---|
28 | 28 |
from django.utils.encoding import force_bytes, force_str |
29 | 29 |
from webtest import Upload |
30 | 30 | |
31 |
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP |
|
31 |
from authentic2.a2_rbac.models import MANAGE_MEMBERS_OP, VIEW_OP
|
|
32 | 32 |
from authentic2.a2_rbac.models import OrganizationalUnit as OU |
33 | 33 |
from authentic2.a2_rbac.models import Permission, Role |
34 | 34 |
from authentic2.a2_rbac.utils import get_default_ou |
35 | 35 |
from authentic2.apps.journal.models import Event |
36 | 36 |
from authentic2.models import Service |
37 | 37 |
from authentic2.validators import EmailValidator |
38 |
from django_rbac.models import VIEW_OP |
|
39 | 38 |
from django_rbac.utils import get_operation |
40 | 39 | |
41 | 40 |
from .utils import assert_event, get_link_from_mail, login, request_select2, text_content |
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 | 33 |
from authentic2.a2_rbac.utils import get_default_ou, get_view_user_perm |
... | ... | |
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 | 39 |
from django_rbac.utils import get_operation |
40 | 40 | |
41 | 41 |
from .utils import get_link_from_mail, login, logout |
42 |
- |