educommon 3.12.0__py3-none-any.whl → 3.13.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- educommon/__init__.py +0 -1
- educommon/about/ui/actions.py +16 -30
- educommon/about/ui/ui.py +3 -12
- educommon/about/utils.py +6 -5
- educommon/async_task/__init__.py +0 -1
- educommon/async_task/actions.py +18 -13
- educommon/async_task/apps.py +4 -0
- educommon/async_task/locker.py +2 -5
- educommon/async_task/migrations/0001_initial.py +55 -9
- educommon/async_task/migrations/0002_task_type_and_status_data.py +94 -89
- educommon/async_task/migrations/0003_alter_runningtask_options.py +0 -1
- educommon/async_task/models.py +9 -6
- educommon/async_task/tasks.py +11 -7
- educommon/async_task/ui.py +16 -35
- educommon/async_tasks/__init__.py +0 -1
- educommon/async_tasks/apps.py +4 -0
- educommon/async_tasks/locks.py +11 -21
- educommon/async_tasks/migrations/0001_initial.py +68 -8
- educommon/async_tasks/migrations/0002_load_initial_data.py +0 -1
- educommon/async_tasks/models.py +9 -29
- educommon/async_tasks/tasks.py +25 -54
- educommon/audit_log/__init__.py +1 -0
- educommon/audit_log/actions.py +27 -36
- educommon/audit_log/app_meta.py +7 -4
- educommon/audit_log/apps.py +44 -29
- educommon/audit_log/constants.py +7 -4
- educommon/audit_log/error_log/actions.py +1 -3
- educommon/audit_log/helpers.py +2 -4
- educommon/audit_log/management/commands/reinstall_audit_log.py +11 -7
- educommon/audit_log/migrations/0001_initial.py +91 -16
- educommon/audit_log/migrations/0002_install_audit_log.py +13 -13
- educommon/audit_log/migrations/0003_logproxy.py +1 -3
- educommon/audit_log/migrations/0004_reinstall_audit_log.py +1 -4
- educommon/audit_log/migrations/0005_postgresql_error.py +4 -2
- educommon/audit_log/migrations/0006_auto_20200806_1707.py +3 -4
- educommon/audit_log/migrations/0007_create_selective_tables_function.py +8 -5
- educommon/audit_log/migrations/0008_table_logged.py +0 -1
- educommon/audit_log/migrations/0009_reinstall_audit_log.py +0 -1
- educommon/audit_log/models.py +36 -42
- educommon/audit_log/permissions.py +11 -9
- educommon/audit_log/proxies.py +12 -23
- educommon/audit_log/ui.py +18 -15
- educommon/audit_log/utils/__init__.py +28 -60
- educommon/audit_log/utils/operations.py +16 -2
- educommon/auth/__init__.py +0 -3
- educommon/auth/rbac/__init__.py +2 -4
- educommon/auth/rbac/actions.py +148 -145
- educommon/auth/rbac/app_meta.py +9 -6
- educommon/auth/rbac/backends/base.py +2 -8
- educommon/auth/rbac/backends/caching.py +27 -37
- educommon/auth/rbac/backends/simple.py +1 -4
- educommon/auth/rbac/checker.py +1 -3
- educommon/auth/rbac/management/commands/rbac.py +6 -11
- educommon/auth/rbac/manager.py +18 -47
- educommon/auth/rbac/migrations/0001_initial.py +73 -12
- educommon/auth/rbac/migrations/0002_model_modifier_metaclass_fix.py +7 -6
- educommon/auth/rbac/migrations/0003_permission_hidden.py +1 -5
- educommon/auth/rbac/migrations/0004_auto_20171024_1245.py +26 -19
- educommon/auth/rbac/models.py +63 -68
- educommon/auth/rbac/permissions.py +6 -7
- educommon/auth/rbac/ui.py +83 -84
- educommon/auth/rbac/utils.py +10 -11
- educommon/auth/rbac/validators.py +4 -5
- educommon/auth/simple_auth/__init__.py +1 -5
- educommon/auth/simple_auth/actions.py +79 -92
- educommon/auth/simple_auth/app_meta.py +2 -9
- educommon/auth/simple_auth/checkers.py +3 -3
- educommon/auth/simple_auth/migrations/0001_initial.py +23 -4
- educommon/auth/simple_auth/validators.py +0 -1
- educommon/contingent/actions.py +7 -7
- educommon/contingent/app_meta.py +1 -4
- educommon/contingent/base.py +10 -15
- educommon/contingent/catalogs.py +424 -540
- educommon/contingent/contingent_plugin/actions.py +4 -15
- educommon/contingent/contingent_plugin/apps.py +10 -4
- educommon/contingent/contingent_plugin/migrations/0001_initial.py +5 -6
- educommon/contingent/contingent_plugin/migrations/0002_add_contingent_model_deleted.py +6 -11
- educommon/contingent/contingent_plugin/model_views.py +2 -12
- educommon/contingent/contingent_plugin/models.py +2 -7
- educommon/contingent/contingent_plugin/observer.py +14 -13
- educommon/contingent/contingent_plugin/plugin_meta.py +1 -3
- educommon/contingent/contingent_plugin/storage.py +8 -7
- educommon/contingent/contingent_plugin/utils.py +6 -6
- educommon/django/db/fields.py +72 -86
- educommon/django/db/migration/__init__.py +3 -7
- educommon/django/db/migration/operations.py +29 -51
- educommon/django/db/mixins/__init__.py +16 -10
- educommon/django/db/mixins/date_interval.py +47 -75
- educommon/django/db/mixins/validation.py +26 -26
- educommon/django/db/model_view/__init__.py +18 -22
- educommon/django/db/models.py +9 -8
- educommon/django/db/observer.py +9 -27
- educommon/django/db/partitioning/__init__.py +66 -92
- educommon/django/db/partitioning/management/commands/apply_partitioning.py +3 -13
- educommon/django/db/partitioning/management/commands/clear_table.py +18 -14
- educommon/django/db/partitioning/management/commands/split_table.py +18 -13
- educommon/django/db/routers.py +6 -15
- educommon/django/db/signals.py +149 -2
- educommon/django/db/utils.py +14 -19
- educommon/django/db/validators/__init__.py +1 -0
- educommon/django/db/validators/simple.py +72 -100
- educommon/django/storages/atcfs/api.py +39 -53
- educommon/django/storages/atcfs/app_meta.py +1 -1
- educommon/django/storages/atcfs/management/commands/atcfs_migrate.py +42 -55
- educommon/django/storages/atcfs/models.py +0 -3
- educommon/django/storages/atcfs/monkey_patching.py +18 -12
- educommon/django/storages/atcfs/storage.py +14 -23
- educommon/extjs/fields/input_params.py +15 -45
- educommon/importer/XLSReader.py +143 -241
- educommon/importer/__init__.py +86 -4
- educommon/importer/api.py +53 -84
- educommon/importer/constants.py +4 -14
- educommon/importer/loggers.py +16 -26
- educommon/importer/proxy.py +131 -176
- educommon/importer/proxy_import.py +11 -12
- educommon/importer/report.py +4 -6
- educommon/importer/ui.py +32 -26
- educommon/importer/validators.py +4 -7
- educommon/integration_entities/helpers.py +14 -18
- educommon/ioc/__init__.py +3 -6
- educommon/logger/loggers.py +10 -14
- educommon/m3/__init__.py +20 -38
- educommon/m3/extensions/__init__.py +1 -0
- educommon/m3/extensions/listeners/__init__.py +22 -38
- educommon/m3/extensions/listeners/delete_check/listeners.py +31 -41
- educommon/m3/extensions/listeners/delete_check/mixins.py +20 -25
- educommon/m3/extensions/listeners/delete_check/signals.py +2 -2
- educommon/m3/extensions/listeners/delete_check/ui.py +15 -14
- educommon/m3/extensions/listeners/delete_check/utils.py +9 -11
- educommon/m3/extensions/ui.py +15 -33
- educommon/m3/transaction_context.py +17 -19
- educommon/objectpack/actions.py +70 -88
- educommon/objectpack/apps.py +5 -0
- educommon/objectpack/filters.py +9 -15
- educommon/objectpack/ui.py +59 -77
- educommon/report/__init__.py +9 -5
- educommon/report/actions.py +29 -32
- educommon/report/constructor/__init__.py +5 -8
- educommon/report/constructor/app_meta.py +1 -3
- educommon/report/constructor/apps.py +1 -0
- educommon/report/constructor/base.py +33 -80
- educommon/report/constructor/builders/excel/_base.py +138 -286
- educommon/report/constructor/builders/excel/_header.py +2 -9
- educommon/report/constructor/builders/excel/product.py +13 -34
- educommon/report/constructor/builders/excel/with_merged_cells.py +18 -14
- educommon/report/constructor/config.py +2 -0
- educommon/report/constructor/editor/actions.py +101 -215
- educommon/report/constructor/editor/ui.py +71 -93
- educommon/report/constructor/exceptions.py +6 -12
- educommon/report/constructor/migrations/0001_initial.py +36 -44
- educommon/report/constructor/migrations/0002_report_filters.py +86 -72
- educommon/report/constructor/migrations/0003_reportfilter_exclude.py +5 -5
- educommon/report/constructor/migrations/0004_reportfilter_fields.py +22 -18
- educommon/report/constructor/migrations/0005_reportcolumn_visible.py +5 -4
- educommon/report/constructor/migrations/0006_reportsorting.py +21 -17
- educommon/report/constructor/migrations/0007_include_available_units.py +14 -14
- educommon/report/constructor/migrations/0008_auto_20170407_1318.py +4 -5
- educommon/report/constructor/migrations/0009_auto_20180405_0642.py +1 -4
- educommon/report/constructor/migrations/0010_add_aggregate_fields.py +7 -8
- educommon/report/constructor/mixins.py +14 -15
- educommon/report/constructor/models.py +76 -124
- educommon/report/constructor/utils.py +3 -8
- educommon/report/constructor/validators.py +1 -3
- educommon/report/reporter.py +25 -43
- educommon/report/utils.py +14 -40
- educommon/rest/actions.py +7 -11
- educommon/rest/context.py +6 -16
- educommon/rest/controllers.py +10 -10
- educommon/rest/mixins.py +29 -27
- educommon/secure_media/app_meta.py +9 -9
- educommon/utils/__init__.py +3 -2
- educommon/utils/caching.py +1 -3
- educommon/utils/conversion.py +1 -3
- educommon/utils/crypto.py +1 -2
- educommon/utils/date.py +13 -26
- educommon/utils/db/__init__.py +17 -26
- educommon/utils/db/postgresql.py +1 -4
- educommon/utils/fonts/__init__.py +3 -4
- educommon/utils/licence/__init__.py +5 -16
- educommon/utils/misc.py +9 -18
- educommon/utils/object_grid.py +55 -62
- educommon/utils/phone_number/modelfields.py +1 -3
- educommon/utils/phone_number/phone_number.py +5 -8
- educommon/utils/phone_number/validators.py +8 -23
- educommon/utils/plugins.py +15 -28
- educommon/utils/registry.py +2 -1
- educommon/utils/seqtools.py +1 -3
- educommon/utils/serializer.py +9 -16
- educommon/utils/storage.py +3 -2
- educommon/utils/system.py +1 -3
- educommon/utils/system_app/management/commands/delete_objects.py +17 -34
- educommon/utils/ui.py +87 -84
- educommon/utils/xml/__init__.py +2 -7
- educommon/utils/xml/resolver.py +1 -0
- educommon/ws_log/actions.py +31 -76
- educommon/ws_log/base.py +6 -20
- educommon/ws_log/migrations/0001_initial.py +25 -8
- educommon/ws_log/migrations/0002_auto_20160628_1334.py +0 -1
- educommon/ws_log/migrations/0003_add_fields_to_smev_logs.py +20 -4
- educommon/ws_log/migrations/0004_auto_20160727_1600.py +7 -6
- educommon/ws_log/migrations/0005_auto_20161130_1615.py +14 -4
- educommon/ws_log/migrations/0006_auto_20170327_1027.py +3 -2
- educommon/ws_log/migrations/0007_auto_20180607_1040.py +8 -9
- educommon/ws_log/migrations/0008_auto_20180713_1445.py +23 -10
- educommon/ws_log/migrations/0009_auto_20201130_1553.py +7 -2
- educommon/ws_log/models.py +21 -35
- educommon/ws_log/provider.py +2 -1
- educommon/ws_log/report.py +8 -13
- educommon/ws_log/smev/applications.py +12 -27
- educommon/ws_log/smev/exceptions.py +2 -3
- educommon/ws_log/ui.py +32 -32
- educommon/ws_log/utils.py +1 -3
- educommon-3.13.2.dist-info/METADATA +57 -0
- educommon-3.13.2.dist-info/RECORD +354 -0
- {educommon-3.12.0.dist-info → educommon-3.13.2.dist-info}/WHEEL +1 -1
- educommon/utils/patches.py +0 -27
- educommon/version.conf +0 -11
- educommon-3.12.0.dist-info/METADATA +0 -47
- educommon-3.12.0.dist-info/RECORD +0 -357
- educommon-3.12.0.dist-info/dependency_links.txt +0 -1
- {educommon-3.12.0.dist-info → educommon-3.13.2.dist-info}/top_level.txt +0 -0
@@ -58,20 +58,19 @@ class CachingBackend(BackendBase):
|
|
58
58
|
"""Ключ кеша, в котором сохраняется время изменения объектов в БД."""
|
59
59
|
|
60
60
|
# Модели, данные которых кэшируются.
|
61
|
-
_cached_models = {
|
62
|
-
Permission,
|
63
|
-
Role,
|
64
|
-
RoleParent,
|
65
|
-
UserRole,
|
66
|
-
RolePermission
|
67
|
-
}
|
61
|
+
_cached_models = {Permission, Role, RoleParent, UserRole, RolePermission}
|
68
62
|
|
69
63
|
@cached_property
|
70
64
|
def _logger(self):
|
71
65
|
return getLogger(__name__.rpartition('.')[0])
|
72
66
|
|
73
67
|
def __init__(self, *args, **kwargs):
|
74
|
-
|
68
|
+
"""Инициализация бэкенда RBAC с поддержкой кэширования.
|
69
|
+
|
70
|
+
Устанавливает параметры кэширования и подписывается на сигналы
|
71
|
+
для обновления кэша при изменениях в связанных моделях.
|
72
|
+
"""
|
73
|
+
super().__init__(*args, **kwargs)
|
75
74
|
|
76
75
|
# Максимальная продолжительность кеширования объектов до их
|
77
76
|
# перезагрузки (в секундах).
|
@@ -107,7 +106,8 @@ class CachingBackend(BackendBase):
|
|
107
106
|
"""Обработчик сигналов об изменениях в моделях."""
|
108
107
|
if (
|
109
108
|
# changed приходит только от post_init
|
110
|
-
kwargs.get('changed', False)
|
109
|
+
kwargs.get('changed', False)
|
110
|
+
or
|
111
111
|
# а port_save и post_delete нужно обрабатывать только для
|
112
112
|
# кэшируемых моделей
|
113
113
|
sender in self._cached_models
|
@@ -158,23 +158,17 @@ class CachingBackend(BackendBase):
|
|
158
158
|
|
159
159
|
def _load_role_permissions(self):
|
160
160
|
"""Загрузка данных о разрешениях ролей RBAC."""
|
161
|
-
for role_id, permission_id in RolePermission.objects.values_list(
|
162
|
-
'role', 'permission'
|
163
|
-
):
|
161
|
+
for role_id, permission_id in RolePermission.objects.values_list('role', 'permission'):
|
164
162
|
self._role_permissions[role_id].add(permission_id)
|
165
163
|
|
166
164
|
def _load_user_roles(self):
|
167
165
|
"""Загрузка данных о ролях пользователей."""
|
168
166
|
query = UserRole.objects.filter(
|
169
167
|
Q(date_to__isnull=True) | Q(date_to__gte=date.today()),
|
170
|
-
).values_list(
|
171
|
-
'content_type', 'object_id', 'date_from', 'date_to', 'role'
|
172
|
-
)
|
168
|
+
).values_list('content_type', 'object_id', 'date_from', 'date_to', 'role')
|
173
169
|
|
174
170
|
for ct_id, obj_id, date_from, date_to, role_id in query:
|
175
|
-
self._user_roles[ct_id, obj_id].add(
|
176
|
-
(date_from, date_to, role_id)
|
177
|
-
)
|
171
|
+
self._user_roles[ct_id, obj_id].add((date_from, date_to, role_id))
|
178
172
|
|
179
173
|
def _get_role_descendants(self, role_id, include_self=False):
|
180
174
|
"""Возвращает вложенные роли."""
|
@@ -184,9 +178,7 @@ class CachingBackend(BackendBase):
|
|
184
178
|
result.add(role_id)
|
185
179
|
|
186
180
|
for child_role_id in self._role_children[role_id]:
|
187
|
-
result.update(
|
188
|
-
self._get_role_descendants(child_role_id, include_self=True)
|
189
|
-
)
|
181
|
+
result.update(self._get_role_descendants(child_role_id, include_self=True))
|
190
182
|
|
191
183
|
return result
|
192
184
|
|
@@ -199,30 +191,30 @@ class CachingBackend(BackendBase):
|
|
199
191
|
roles_data = self._user_roles[content_type_id, user.id]
|
200
192
|
today = date.today()
|
201
193
|
|
202
|
-
return set(
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
194
|
+
return set(
|
195
|
+
chain(
|
196
|
+
*(
|
197
|
+
self._get_role_descendants(role_id, include_self=True)
|
198
|
+
for date_from, date_to, role_id in roles_data
|
199
|
+
if (date_from or today) <= today <= (date_to or today)
|
200
|
+
)
|
201
|
+
)
|
202
|
+
)
|
207
203
|
|
208
204
|
def _get_user_permissions(self, user):
|
209
205
|
"""Возврвщает все доступные пользователю разрешения.
|
210
206
|
|
211
207
|
:rtype: itertools.chain
|
212
208
|
"""
|
209
|
+
|
213
210
|
def get_role_permissions(role_id):
|
214
211
|
# pylint: disable=protected-access
|
215
212
|
for permission_id in self._role_permissions[role_id]:
|
216
213
|
yield permission_id
|
217
|
-
for name in self._manager.get_dependent_permissions(
|
218
|
-
self._permissions_by_id[permission_id]
|
219
|
-
):
|
214
|
+
for name in self._manager.get_dependent_permissions(self._permissions_by_id[permission_id]):
|
220
215
|
yield self._permissions_by_name[name]
|
221
216
|
|
222
|
-
return chain(*(
|
223
|
-
get_role_permissions(role_id)
|
224
|
-
for role_id in self._get_user_roles(user)
|
225
|
-
))
|
217
|
+
return chain(*(get_role_permissions(role_id) for role_id in self._get_user_roles(user)))
|
226
218
|
|
227
219
|
def _reload(self, force=False):
|
228
220
|
"""Перезагрузка кешируемых объектов при необходимости.
|
@@ -278,15 +270,13 @@ class CachingBackend(BackendBase):
|
|
278
270
|
|
279
271
|
# Id разрешений экшена, доступность которых будем проверять
|
280
272
|
action_permissions = set(
|
281
|
-
self._permissions_by_name[perm_name]
|
282
|
-
for perm_name in self._get_action_permissions(action)
|
273
|
+
self._permissions_by_name[perm_name] for perm_name in self._get_action_permissions(action)
|
283
274
|
)
|
284
275
|
|
285
276
|
for permission_id in self._get_user_permissions(user):
|
286
277
|
if permission_id in action_permissions:
|
287
278
|
permission_name = self._permissions_by_id[permission_id]
|
288
|
-
if self._check_permission(permission_name, action, request,
|
289
|
-
user):
|
279
|
+
if self._check_permission(permission_name, action, request, user):
|
290
280
|
return True
|
291
281
|
|
292
282
|
return False
|
@@ -72,7 +72,6 @@ def _get_user_permissions_query(user, permissions=None):
|
|
72
72
|
|
73
73
|
|
74
74
|
class SimpleBackend(BackendBase):
|
75
|
-
|
76
75
|
"""Предоставляет прямой доступ к объектам RBAC.
|
77
76
|
|
78
77
|
Доступ к объектам RBAC (разрешениям, ролям и их связям между собой)
|
@@ -91,9 +90,7 @@ class SimpleBackend(BackendBase):
|
|
91
90
|
:rtype: generator
|
92
91
|
"""
|
93
92
|
# pylint: disable=protected-access
|
94
|
-
for name in _get_user_permissions_query(user, permissions).values_list(
|
95
|
-
'name', flat=True
|
96
|
-
):
|
93
|
+
for name in _get_user_permissions_query(user, permissions).values_list('name', flat=True):
|
97
94
|
yield name
|
98
95
|
for name in self._manager.get_dependent_permissions(name):
|
99
96
|
yield name
|
educommon/auth/rbac/checker.py
CHANGED
@@ -53,9 +53,7 @@ class PermissionChecker(AbstractPermissionChecker):
|
|
53
53
|
|
54
54
|
pack_perm_code = getattr(pack, 'perm_code', False)
|
55
55
|
if not pack_perm_code:
|
56
|
-
pack_perm_code = '/'.join(
|
57
|
-
(pack.__class__.__module__, pack.__class__.__name__)
|
58
|
-
)
|
56
|
+
pack_perm_code = '/'.join((pack.__class__.__module__, pack.__class__.__name__))
|
59
57
|
|
60
58
|
if action is None:
|
61
59
|
action_perm_code = 'default'
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""Management-команда для обслуживания системы авторизации."""
|
2
|
+
|
2
3
|
import os
|
3
4
|
|
4
5
|
from django.core.management import (
|
@@ -21,7 +22,6 @@ from educommon.auth.rbac.models import (
|
|
21
22
|
|
22
23
|
|
23
24
|
class Command(BaseCommand):
|
24
|
-
|
25
25
|
"""Обслуживание системы авторизации."""
|
26
26
|
|
27
27
|
use_argparse = False
|
@@ -84,8 +84,6 @@ class Command(BaseCommand):
|
|
84
84
|
return
|
85
85
|
|
86
86
|
max_width = max(len(permission) for permission in permissions)
|
87
|
-
template = ' {} {:<%s}\n' % max_width
|
88
|
-
|
89
87
|
self.stdout.write('Permissions:\n')
|
90
88
|
|
91
89
|
for permission in sorted(permissions):
|
@@ -96,9 +94,8 @@ class Command(BaseCommand):
|
|
96
94
|
else:
|
97
95
|
status, color = '[ REGISTERED ]', 'green'
|
98
96
|
|
99
|
-
|
100
|
-
|
101
|
-
)
|
97
|
+
line = f' {status} {permission:<{max_width}}\n'
|
98
|
+
self.stdout.write(colored(line, color))
|
102
99
|
|
103
100
|
def _show(self, objects='permissions', *args, **options):
|
104
101
|
"""Отображение данных системы авторизации."""
|
@@ -119,13 +116,11 @@ class Command(BaseCommand):
|
|
119
116
|
return
|
120
117
|
|
121
118
|
max_width = max(len(p.name) for p in permissions)
|
122
|
-
template = '{:<%s} [DELETED]\n' % max_width
|
123
119
|
|
124
120
|
for permission in permissions:
|
125
121
|
permission.delete()
|
126
|
-
|
127
|
-
|
128
|
-
)
|
122
|
+
line = f'{permission.name:<{max_width}} [DELETED]\n'
|
123
|
+
self.stdout.write(colored(line, 'red'))
|
129
124
|
|
130
125
|
def _clean(self, objects='all', **options):
|
131
126
|
"""Удаление незарегистрированных правил и разрешений."""
|
@@ -137,7 +132,7 @@ class Command(BaseCommand):
|
|
137
132
|
raise CommandError('Unknown objects type: {}'.format(objects))
|
138
133
|
|
139
134
|
def handle(self, action, *args, **options):
|
140
|
-
|
135
|
+
"""Обработка команды управления RBAC."""
|
141
136
|
rbac.init(update_db=False)
|
142
137
|
|
143
138
|
if not self.stdout.isatty():
|
educommon/auth/rbac/manager.py
CHANGED
@@ -42,6 +42,7 @@ def _get_handler(handler):
|
|
42
42
|
module, handler = handler.rsplit('.', 1)
|
43
43
|
module = __import__(module, fromlist=[handler])
|
44
44
|
handler = getattr(module, handler)
|
45
|
+
|
45
46
|
return handler
|
46
47
|
|
47
48
|
|
@@ -89,11 +90,7 @@ def _set_permission(permission, name, title, description, hidden):
|
|
89
90
|
permission.full_clean()
|
90
91
|
permission.save()
|
91
92
|
changed = True
|
92
|
-
elif
|
93
|
-
permission.title != title or
|
94
|
-
permission.description != description or
|
95
|
-
permission.hidden != hidden
|
96
|
-
):
|
93
|
+
elif permission.title != title or permission.description != description or permission.hidden != hidden:
|
97
94
|
permission.title = title
|
98
95
|
permission.description = description
|
99
96
|
permission.hidden = hidden
|
@@ -129,6 +126,7 @@ class RBACManager:
|
|
129
126
|
:returns: ``('employee', 'Сотрудники')``
|
130
127
|
"""
|
131
128
|
group_name = permission_name.split('/')[0]
|
129
|
+
|
132
130
|
return group_name, self.groups[group_name]
|
133
131
|
|
134
132
|
def get_partition_title(self, group_name) -> Optional[str]:
|
@@ -154,8 +152,7 @@ class RBACManager:
|
|
154
152
|
for title, group_codes in partitions.items():
|
155
153
|
for code in group_codes:
|
156
154
|
assert code not in processed_codes, (
|
157
|
-
'Группа разрешений "{}" уже закреплена за другим '
|
158
|
-
'разделом системы.'.format(code)
|
155
|
+
'Группа разрешений "{}" уже закреплена за другим разделом системы.'.format(code)
|
159
156
|
)
|
160
157
|
self.partitions[title].add(code)
|
161
158
|
processed_codes.add(code)
|
@@ -170,9 +167,8 @@ class RBACManager:
|
|
170
167
|
continue
|
171
168
|
|
172
169
|
for code, title in groups.items():
|
173
|
-
assert code not in self.groups, (
|
174
|
-
|
175
|
-
'приложении.'.format(code, title)
|
170
|
+
assert code not in self.groups, 'Группа разрешений "{}" ({}) уже описана в другом приложении.'.format(
|
171
|
+
code, title
|
176
172
|
)
|
177
173
|
|
178
174
|
self.groups[code] = title
|
@@ -203,13 +199,9 @@ class RBACManager:
|
|
203
199
|
if hidden:
|
204
200
|
self.hidden_permissions.add(name)
|
205
201
|
else:
|
206
|
-
raise ValueError(
|
207
|
-
'Invalid permission params: ' + repr(params)
|
208
|
-
)
|
202
|
+
raise ValueError('Invalid permission params: ' + repr(params))
|
209
203
|
|
210
|
-
assert name in self.permissions_by_name, (
|
211
|
-
'Permission {} not found'.format(name)
|
212
|
-
)
|
204
|
+
assert name in self.permissions_by_name, 'Permission {} not found'.format(name)
|
213
205
|
|
214
206
|
_title, _description = self.permissions_by_name[name]
|
215
207
|
self.permissions_by_name[name] = (
|
@@ -227,27 +219,16 @@ class RBACManager:
|
|
227
219
|
module_dependencies = module_dependencies()
|
228
220
|
|
229
221
|
for name, dependencies in module_dependencies.items():
|
230
|
-
assert name in self.permissions_by_name, (
|
231
|
-
'Permission {} not found'.format(name)
|
232
|
-
)
|
222
|
+
assert name in self.permissions_by_name, 'Permission {} not found'.format(name)
|
233
223
|
assert name not in self.hidden_permissions or all(
|
234
|
-
dependency in self.hidden_permissions
|
235
|
-
|
236
|
-
), (
|
237
|
-
'Скрытые разрешения могут зависеть только от скрытых '
|
238
|
-
'разрешений: ' + name
|
239
|
-
)
|
224
|
+
dependency in self.hidden_permissions for dependency in dependencies
|
225
|
+
), 'Скрытые разрешения могут зависеть только от скрытых разрешений: ' + name
|
240
226
|
if __debug__:
|
241
227
|
for dependency in dependencies:
|
242
228
|
if name == dependency:
|
243
|
-
raise AssertionError(
|
244
|
-
'Permission {} can''t depend on itself'
|
245
|
-
.format(dependency)
|
246
|
-
)
|
229
|
+
raise AssertionError('Permission {} cant depend on itself'.format(dependency))
|
247
230
|
if dependency not in self.permissions_by_name:
|
248
|
-
raise AssertionError(
|
249
|
-
'Permission {} not found'.format(dependency)
|
250
|
-
)
|
231
|
+
raise AssertionError('Permission {} not found'.format(dependency))
|
251
232
|
|
252
233
|
self.permission_dependencies[name].update(dependencies)
|
253
234
|
|
@@ -271,10 +252,7 @@ class RBACManager:
|
|
271
252
|
with Lock(settings.DEFAULT_DB_ALIAS, 'rbac_lock'):
|
272
253
|
permissions_changed = False
|
273
254
|
|
274
|
-
permissions = {
|
275
|
-
permission.name: permission
|
276
|
-
for permission in Permission.objects.iterator()
|
277
|
-
}
|
255
|
+
permissions = {permission.name: permission for permission in Permission.objects.iterator()}
|
278
256
|
|
279
257
|
for params in self.permissions_by_name.items():
|
280
258
|
name, (title, description) = params
|
@@ -307,9 +285,7 @@ class RBACManager:
|
|
307
285
|
for dependency in self.permission_dependencies[name]:
|
308
286
|
if dependency not in _result:
|
309
287
|
_result.add(dependency)
|
310
|
-
_result.update(
|
311
|
-
self.get_dependent_permissions(dependency, _result)
|
312
|
-
)
|
288
|
+
_result.update(self.get_dependent_permissions(dependency, _result))
|
313
289
|
|
314
290
|
if primary_name:
|
315
291
|
_result.remove(primary_name)
|
@@ -351,6 +327,7 @@ class RBACManager:
|
|
351
327
|
|
352
328
|
@cached_property
|
353
329
|
def _backend(self):
|
330
|
+
"""Инициализирует и возвращает выбранный бэкенд RBAC."""
|
354
331
|
backend_name = getattr(settings, 'RBAC_BACKEND', None) or (
|
355
332
|
__name__.rpartition('.')[0] + '.backends.caching.CachingBackend'
|
356
333
|
)
|
@@ -359,18 +336,12 @@ class RBACManager:
|
|
359
336
|
try:
|
360
337
|
module = import_module(module_name)
|
361
338
|
except ImportError as e:
|
362
|
-
raise ImproperlyConfigured(
|
363
|
-
'Error importing RBAC backend module {}: "{}"'
|
364
|
-
.format(module_name, e)
|
365
|
-
)
|
339
|
+
raise ImproperlyConfigured('Error importing RBAC backend module {}: "{}"'.format(module_name, e))
|
366
340
|
|
367
341
|
try:
|
368
342
|
backend_class = getattr(module, class_name)
|
369
343
|
except AttributeError:
|
370
|
-
raise ImproperlyConfigured(
|
371
|
-
'Module "{}" does not define a RBAC backend "{}"'
|
372
|
-
.format(module, class_name)
|
373
|
-
)
|
344
|
+
raise ImproperlyConfigured('Module "{}" does not define a RBAC backend "{}"'.format(module, class_name))
|
374
345
|
else:
|
375
346
|
backend = backend_class(self)
|
376
347
|
|
@@ -5,7 +5,6 @@ from django.db import (
|
|
5
5
|
|
6
6
|
|
7
7
|
class Migration(migrations.Migration):
|
8
|
-
|
9
8
|
dependencies = [
|
10
9
|
('contenttypes', '0001_initial'),
|
11
10
|
]
|
@@ -15,9 +14,23 @@ class Migration(migrations.Migration):
|
|
15
14
|
name='Permission',
|
16
15
|
fields=[
|
17
16
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
18
|
-
(
|
19
|
-
|
20
|
-
|
17
|
+
(
|
18
|
+
'name',
|
19
|
+
models.CharField(unique=True, max_length=100, verbose_name='\u0418\u043c\u044f', db_index=True),
|
20
|
+
),
|
21
|
+
(
|
22
|
+
'title',
|
23
|
+
models.CharField(
|
24
|
+
max_length=200,
|
25
|
+
null=True,
|
26
|
+
verbose_name='\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435',
|
27
|
+
blank=True,
|
28
|
+
),
|
29
|
+
),
|
30
|
+
(
|
31
|
+
'description',
|
32
|
+
models.TextField(verbose_name='\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435', blank=True),
|
33
|
+
),
|
21
34
|
],
|
22
35
|
options={
|
23
36
|
'verbose_name': '\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435',
|
@@ -29,9 +42,26 @@ class Migration(migrations.Migration):
|
|
29
42
|
name='Role',
|
30
43
|
fields=[
|
31
44
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
32
|
-
(
|
33
|
-
|
34
|
-
|
45
|
+
(
|
46
|
+
'name',
|
47
|
+
models.CharField(
|
48
|
+
unique=True,
|
49
|
+
max_length=300,
|
50
|
+
verbose_name='\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435',
|
51
|
+
db_index=True,
|
52
|
+
),
|
53
|
+
),
|
54
|
+
(
|
55
|
+
'description',
|
56
|
+
models.TextField(verbose_name='\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435', blank=True),
|
57
|
+
),
|
58
|
+
(
|
59
|
+
'can_be_assigned',
|
60
|
+
models.BooleanField(
|
61
|
+
default=True,
|
62
|
+
verbose_name='\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e',
|
63
|
+
),
|
64
|
+
),
|
35
65
|
],
|
36
66
|
options={
|
37
67
|
'verbose_name': '\u0420\u043e\u043b\u044c',
|
@@ -56,8 +86,20 @@ class Migration(migrations.Migration):
|
|
56
86
|
name='RolePermission',
|
57
87
|
fields=[
|
58
88
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
59
|
-
(
|
60
|
-
|
89
|
+
(
|
90
|
+
'permission',
|
91
|
+
models.ForeignKey(
|
92
|
+
verbose_name='\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435',
|
93
|
+
to='rbac.Permission',
|
94
|
+
on_delete=models.CASCADE,
|
95
|
+
),
|
96
|
+
),
|
97
|
+
(
|
98
|
+
'role',
|
99
|
+
models.ForeignKey(
|
100
|
+
verbose_name='\u0420\u043e\u043b\u044c', to='rbac.Role', on_delete=models.CASCADE
|
101
|
+
),
|
102
|
+
),
|
61
103
|
],
|
62
104
|
options={
|
63
105
|
'db_table': 'rbac_role_permissions',
|
@@ -71,10 +113,29 @@ class Migration(migrations.Migration):
|
|
71
113
|
fields=[
|
72
114
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
73
115
|
('object_id', models.PositiveIntegerField()),
|
74
|
-
(
|
75
|
-
|
116
|
+
(
|
117
|
+
'date_from',
|
118
|
+
models.DateField(
|
119
|
+
null=True,
|
120
|
+
verbose_name='\u041d\u0430\u0447\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430',
|
121
|
+
blank=True,
|
122
|
+
),
|
123
|
+
),
|
124
|
+
(
|
125
|
+
'date_to',
|
126
|
+
models.DateField(
|
127
|
+
null=True,
|
128
|
+
verbose_name='\u041a\u043e\u043d\u0435\u0446 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430',
|
129
|
+
blank=True,
|
130
|
+
),
|
131
|
+
),
|
76
132
|
('content_type', models.ForeignKey(to='contenttypes.ContentType', on_delete=models.CASCADE)),
|
77
|
-
(
|
133
|
+
(
|
134
|
+
'role',
|
135
|
+
models.ForeignKey(
|
136
|
+
verbose_name='\u0420\u043e\u043b\u044c', to='rbac.Role', on_delete=models.CASCADE
|
137
|
+
),
|
138
|
+
),
|
78
139
|
],
|
79
140
|
options={
|
80
141
|
'verbose_name': '\u0420\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f',
|
@@ -5,18 +5,19 @@ from django.db import (
|
|
5
5
|
|
6
6
|
|
7
7
|
class Migration(migrations.Migration):
|
8
|
-
|
9
|
-
|
8
|
+
dependencies = [
|
9
|
+
('rbac', '0001_initial'),
|
10
|
+
]
|
10
11
|
|
11
12
|
operations = [
|
12
13
|
migrations.AlterField(
|
13
14
|
model_name='userrole',
|
14
15
|
name='date_from',
|
15
|
-
field=models.DateField(
|
16
|
-
|
16
|
+
field=models.DateField(blank=True, null=True, verbose_name='Действует с'),
|
17
|
+
),
|
17
18
|
migrations.AlterField(
|
18
19
|
model_name='userrole',
|
19
20
|
name='date_to',
|
20
|
-
field=models.DateField(
|
21
|
-
|
21
|
+
field=models.DateField(blank=True, null=True, verbose_name='по'),
|
22
|
+
),
|
22
23
|
]
|
@@ -5,7 +5,6 @@ from django.db import (
|
|
5
5
|
|
6
6
|
|
7
7
|
class Migration(migrations.Migration):
|
8
|
-
|
9
8
|
dependencies = [
|
10
9
|
('rbac', '0002_model_modifier_metaclass_fix'),
|
11
10
|
]
|
@@ -14,9 +13,6 @@ class Migration(migrations.Migration):
|
|
14
13
|
migrations.AddField(
|
15
14
|
model_name='permission',
|
16
15
|
name='hidden',
|
17
|
-
field=models.BooleanField(
|
18
|
-
default=False,
|
19
|
-
verbose_name='Видимость пользователям'
|
20
|
-
),
|
16
|
+
field=models.BooleanField(default=False, verbose_name='Видимость пользователям'),
|
21
17
|
),
|
22
18
|
]
|
@@ -8,7 +8,6 @@ from django.db import (
|
|
8
8
|
|
9
9
|
|
10
10
|
class Migration(migrations.Migration):
|
11
|
-
|
12
11
|
dependencies = [
|
13
12
|
('contenttypes', '0002_remove_content_type_name'),
|
14
13
|
('rbac', '0003_permission_hidden'),
|
@@ -18,26 +17,31 @@ class Migration(migrations.Migration):
|
|
18
17
|
migrations.CreateModel(
|
19
18
|
name='RoleUserType',
|
20
19
|
fields=[
|
21
|
-
('id', models.AutoField(
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
(
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
20
|
+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
21
|
+
(
|
22
|
+
'role',
|
23
|
+
models.ForeignKey(
|
24
|
+
on_delete=django.db.models.deletion.CASCADE,
|
25
|
+
related_name='+',
|
26
|
+
to='rbac.Role',
|
27
|
+
verbose_name='Роль',
|
28
|
+
),
|
29
|
+
),
|
30
|
+
(
|
31
|
+
'user_type',
|
32
|
+
models.ForeignKey(
|
33
|
+
on_delete=django.db.models.deletion.CASCADE,
|
34
|
+
related_name='+',
|
35
|
+
to='contenttypes.ContentType',
|
36
|
+
verbose_name='Тип пользователя',
|
37
|
+
),
|
38
|
+
),
|
36
39
|
],
|
37
40
|
options={
|
38
41
|
'verbose_name': 'Тип пользователя роли',
|
39
42
|
'verbose_name_plural': 'Типы пользователей ролей',
|
40
|
-
},
|
43
|
+
},
|
44
|
+
),
|
41
45
|
migrations.AlterModelManagers(
|
42
46
|
name='userrole',
|
43
47
|
managers=[
|
@@ -52,8 +56,11 @@ class Migration(migrations.Migration):
|
|
52
56
|
related_name='_role_user_types_+',
|
53
57
|
through='rbac.RoleUserType',
|
54
58
|
to='contenttypes.ContentType',
|
55
|
-
verbose_name='Может быть назначена'
|
59
|
+
verbose_name='Может быть назначена',
|
60
|
+
),
|
61
|
+
),
|
56
62
|
migrations.AlterUniqueTogether(
|
57
63
|
name='roleusertype',
|
58
|
-
unique_together=set([('role', 'user_type')]),
|
64
|
+
unique_together=set([('role', 'user_type')]),
|
65
|
+
),
|
59
66
|
]
|