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
educommon/audit_log/actions.py
CHANGED
@@ -79,42 +79,24 @@ class AuditLogPack(ViewWindowPackMixin, PackValidationMixin, ObjectPack):
|
|
79
79
|
|
80
80
|
# Фильтр интервала дат
|
81
81
|
date_filter = DatetimeFilterCreator(
|
82
|
-
model, 'time',
|
83
|
-
get_from=lambda: date.today() - timedelta(days=2),
|
84
|
-
get_to=date.today
|
82
|
+
model, 'time', get_from=lambda: date.today() - timedelta(days=2), get_to=date.today
|
85
83
|
)
|
86
84
|
|
87
85
|
columns = [
|
88
|
-
{
|
89
|
-
'data_index': 'time',
|
90
|
-
'width': 140,
|
91
|
-
'header': 'Дата и время',
|
92
|
-
'sortable': True,
|
93
|
-
'filter': date_filter.filter
|
94
|
-
},
|
86
|
+
{'data_index': 'time', 'width': 140, 'header': 'Дата и время', 'sortable': True, 'filter': date_filter.filter},
|
95
87
|
{
|
96
88
|
'data_index': 'user_name',
|
97
89
|
'width': 130,
|
98
90
|
'header': 'Пользователь',
|
99
|
-
'filter': ff(
|
100
|
-
|
101
|
-
|
102
|
-
) & ff(
|
103
|
-
'table__name',
|
104
|
-
lookup=lambda x: make_name_filter('firstname', x)
|
105
|
-
) & ff(
|
106
|
-
'table__name',
|
107
|
-
lookup=lambda x: make_name_filter('patronymic', x)
|
108
|
-
)
|
91
|
+
'filter': ff('table__name', lookup=lambda x: make_name_filter('surname', x))
|
92
|
+
& ff('table__name', lookup=lambda x: make_name_filter('firstname', x))
|
93
|
+
& ff('table__name', lookup=lambda x: make_name_filter('patronymic', x)),
|
109
94
|
},
|
110
95
|
{
|
111
96
|
'data_index': 'operation',
|
112
97
|
'width': 60,
|
113
98
|
'header': 'Операция',
|
114
|
-
'filter': ff(
|
115
|
-
'operation',
|
116
|
-
ask_before_deleting=False
|
117
|
-
),
|
99
|
+
'filter': ff('operation', ask_before_deleting=False),
|
118
100
|
},
|
119
101
|
{
|
120
102
|
'data_index': 'model_name',
|
@@ -158,7 +140,8 @@ class AuditLogPack(ViewWindowPackMixin, PackValidationMixin, ObjectPack):
|
|
158
140
|
]
|
159
141
|
|
160
142
|
def __init__(self):
|
161
|
-
super(
|
143
|
+
super().__init__()
|
144
|
+
|
162
145
|
self.view_changes_action = ViewChangeAction()
|
163
146
|
self.actions.append(self.view_changes_action)
|
164
147
|
|
@@ -174,29 +157,32 @@ class AuditLogPack(ViewWindowPackMixin, PackValidationMixin, ObjectPack):
|
|
174
157
|
Устанавливает интервал дат фильтрации по умолчанию
|
175
158
|
в параметрах запроса.
|
176
159
|
"""
|
177
|
-
super(
|
160
|
+
super().configure_grid(grid)
|
161
|
+
|
178
162
|
grid.store.base_params = self.date_filter.base_params
|
179
163
|
|
180
164
|
def get_edit_window_params(self, params, request, context):
|
181
|
-
|
182
|
-
|
183
|
-
|
165
|
+
"""Возвращает словарь параметров, которые будут переданы окну редактирования."""
|
166
|
+
params = super().get_edit_window_params(params, request, context)
|
167
|
+
|
184
168
|
params['grid_action'] = self.view_changes_action
|
169
|
+
|
185
170
|
return params
|
186
171
|
|
187
172
|
def get_list_window_params(self, params, request, context):
|
188
|
-
|
189
|
-
|
190
|
-
|
173
|
+
"""Возвращает словарь параметров, которые будут переданы окну списка."""
|
174
|
+
params = super().get_list_window_params(params, request, context)
|
175
|
+
|
191
176
|
params['maximized'] = True
|
177
|
+
|
192
178
|
return params
|
193
179
|
|
194
180
|
def get_rows_query(self, request, context):
|
195
|
-
|
196
|
-
|
197
|
-
).prefetch_related('table')
|
181
|
+
"""Возвращает выборку из БД для получения списка данных."""
|
182
|
+
return super().get_rows_query(request, context).prefetch_related('table')
|
198
183
|
|
199
184
|
def extend_menu(self, menu):
|
185
|
+
"""Расширение главного меню."""
|
200
186
|
return menu.administry(
|
201
187
|
menu.Item(self.title, self.list_window_action),
|
202
188
|
)
|
@@ -206,14 +192,19 @@ class ViewChangeAction(BaseAction):
|
|
206
192
|
"""Action для просмотра изменений."""
|
207
193
|
|
208
194
|
def context_declaration(self):
|
209
|
-
|
195
|
+
"""Делегирует декларацию контекста в пак."""
|
196
|
+
result = super().context_declaration()
|
197
|
+
|
210
198
|
result[self.parent.id_param_name] = dict(type='int')
|
199
|
+
|
211
200
|
return result
|
212
201
|
|
213
202
|
def run(self, request, context):
|
203
|
+
"""Тело Action, вызывается при обработке запроса к серверу."""
|
214
204
|
object_id = getattr(context, self.parent.id_param_name)
|
215
205
|
if object_id:
|
216
206
|
rows = LogProxy.objects.get(id=object_id).diff
|
217
207
|
else:
|
218
208
|
rows = []
|
209
|
+
|
219
210
|
return PreJsonResult({'rows': rows, 'total': len(rows)})
|
educommon/audit_log/app_meta.py
CHANGED
@@ -10,7 +10,10 @@ from educommon.audit_log.error_log.actions import (
|
|
10
10
|
|
11
11
|
|
12
12
|
def register_actions():
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
"""Регистрация паков и экшенов."""
|
14
|
+
ioc.get('main_controller').packs.extend(
|
15
|
+
(
|
16
|
+
AuditLogPack(),
|
17
|
+
PostgreSQLErrorPack(),
|
18
|
+
)
|
19
|
+
)
|
educommon/audit_log/apps.py
CHANGED
@@ -30,16 +30,30 @@ from educommon.utils.db.postgresql import (
|
|
30
30
|
|
31
31
|
|
32
32
|
class AppConfig(AppConfig):
|
33
|
+
"""Конфигурация подсистемы логирования изменений в БД.
|
34
|
+
|
35
|
+
При инициализации приложения:
|
36
|
+
- подключает обработку сигнала post_migrate;
|
37
|
+
- создаёт необходимые расширения PostgreSQL (hstore, postgres_fdw);
|
38
|
+
- проверяет и настраивает подключение к сервисной БД через FDW;
|
39
|
+
- выполняет установку и проверку инфраструктуры AuditLog.
|
40
|
+
"""
|
33
41
|
|
34
42
|
name = __name__.rpartition('.')[0]
|
35
43
|
|
36
44
|
@property
|
37
45
|
def _dispatch_uid(self):
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
46
|
+
"""Уникальный идентификатор для подключения сигнала post_migrate.
|
47
|
+
|
48
|
+
Используется для предотвращения дублирующего подключения обработчиков.
|
49
|
+
"""
|
50
|
+
return '.'.join(
|
51
|
+
(
|
52
|
+
self.name,
|
53
|
+
self.__class__.__name__,
|
54
|
+
self._configure_audit_log.__name__,
|
55
|
+
)
|
56
|
+
)
|
43
57
|
|
44
58
|
def _create_postgresql_extensions(self):
|
45
59
|
"""Создает в БД необходимые расширения PostgreSQL.
|
@@ -52,13 +66,9 @@ class AppConfig(AppConfig):
|
|
52
66
|
if not is_extension_exists(alias, 'postgres_fdw'):
|
53
67
|
if create_extension(alias, 'postgres_fdw', quite=True):
|
54
68
|
with closing(connections[alias].cursor()) as cursor:
|
55
|
-
cursor.execute(
|
56
|
-
'GRANT USAGE ON FOREIGN DATA WRAPPER postgres_fdw '
|
57
|
-
'TO PUBLIC'
|
58
|
-
)
|
69
|
+
cursor.execute('GRANT USAGE ON FOREIGN DATA WRAPPER postgres_fdw TO PUBLIC')
|
59
70
|
|
60
|
-
for alias in (settings.DEFAULT_DB_ALIAS,
|
61
|
-
settings.SERVICE_DB_ALIAS):
|
71
|
+
for alias in (settings.DEFAULT_DB_ALIAS, settings.SERVICE_DB_ALIAS):
|
62
72
|
if not is_extension_exists(alias, 'hstore'):
|
63
73
|
create_extension(alias, 'hstore', quite=True)
|
64
74
|
|
@@ -68,32 +78,41 @@ class AppConfig(AppConfig):
|
|
68
78
|
from educommon.audit_log.utils import (
|
69
79
|
configure,
|
70
80
|
)
|
81
|
+
|
71
82
|
configure()
|
72
83
|
|
73
84
|
# Проверка подключения подключения к сервисной БД через FDW.
|
74
85
|
from educommon.audit_log.utils import (
|
75
86
|
check_connection_fdw,
|
76
87
|
)
|
88
|
+
|
77
89
|
success, error_message = check_connection_fdw()
|
78
90
|
if not success:
|
79
91
|
raise ImproperlyConfigured(
|
80
|
-
|
92
|
+
'{0} - Ошибка подключения к сервисной базе через '
|
81
93
|
"postgres_fdw. Необходимо убедится что 'Журнал изменений' "
|
82
|
-
|
94
|
+
'настроен корректно.'.format(error_message)
|
83
95
|
)
|
84
96
|
|
85
97
|
def _configure_db(self, **kwargs):
|
98
|
+
"""Инициализирует расширения PostgreSQL и настраивает AuditLog.
|
99
|
+
|
100
|
+
Вызывается после применения миграций. Если AuditLog уже инициализирован,
|
101
|
+
выполняется его настройка.
|
102
|
+
"""
|
86
103
|
from educommon.audit_log.utils import (
|
87
104
|
is_initialized,
|
88
105
|
)
|
89
106
|
|
90
107
|
self._create_postgresql_extensions()
|
91
108
|
if is_initialized(settings.DEFAULT_DB_ALIAS):
|
92
|
-
self._configure_audit_log(
|
93
|
-
connections[settings.DEFAULT_DB_ALIAS]
|
94
|
-
)
|
109
|
+
self._configure_audit_log(connections[settings.DEFAULT_DB_ALIAS])
|
95
110
|
|
96
111
|
def ready(self):
|
112
|
+
"""Вызывается при готовности приложения.
|
113
|
+
|
114
|
+
Подключает обработчик _configure_db к сигналу post_migrate.
|
115
|
+
"""
|
97
116
|
post_migrate.connect(self._configure_db, sender=self)
|
98
117
|
|
99
118
|
|
@@ -104,10 +123,7 @@ def check_postgres_fdw(app_configs, **kwargs):
|
|
104
123
|
|
105
124
|
if not is_extension_exists(settings.DEFAULT_DB_ALIAS, 'postgres_fdw'):
|
106
125
|
dbname = settings.DATABASES[settings.DEFAULT_DB_ALIAS]['NAME']
|
107
|
-
msg = (
|
108
|
-
"'postgres_fdw' PostgreSQL extension not installed in '{}' "
|
109
|
-
"database."
|
110
|
-
).format(dbname)
|
126
|
+
msg = ("'postgres_fdw' PostgreSQL extension not installed in '{}' database.").format(dbname)
|
111
127
|
hint = (
|
112
128
|
"Execute this SQL in '{dbname}' database:\n"
|
113
129
|
'{indent}CREATE EXTENSION postgres_fdw;\n'
|
@@ -125,20 +141,19 @@ def check_hstore(app_configs, **kwargs):
|
|
125
141
|
errors = []
|
126
142
|
|
127
143
|
msg = "'hstore' PostgreSQL extension not installed in '{}' database."
|
128
|
-
hint =
|
129
|
-
"Execute this SQL in '{dbname}' database:\n"
|
130
|
-
'{indent}CREATE EXTENSION hstore;'
|
131
|
-
)
|
144
|
+
hint = "Execute this SQL in '{dbname}' database:\n{indent}CREATE EXTENSION hstore;"
|
132
145
|
indent = ' ' * 14
|
133
146
|
|
134
147
|
def check(alias, message_id):
|
135
148
|
dbname = settings.DATABASES[alias]['NAME']
|
136
149
|
if not is_extension_exists(alias, 'hstore'):
|
137
|
-
errors.append(
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
150
|
+
errors.append(
|
151
|
+
Critical(
|
152
|
+
msg.format(dbname),
|
153
|
+
hint.format(indent=indent, dbname=dbname),
|
154
|
+
id=message_id,
|
155
|
+
)
|
156
|
+
)
|
142
157
|
|
143
158
|
check(settings.DEFAULT_DB_ALIAS, 'audit_log.C002')
|
144
159
|
check(settings.SERVICE_DB_ALIAS, 'audit_log.C003')
|
educommon/audit_log/constants.py
CHANGED
@@ -21,8 +21,11 @@ EXCLUDED_TABLES = (
|
|
21
21
|
)
|
22
22
|
|
23
23
|
# Папка с sql файлами
|
24
|
-
SQL_FILES_DIR = os.path.abspath(
|
25
|
-
os.path.
|
26
|
-
)
|
24
|
+
SQL_FILES_DIR = os.path.abspath(
|
25
|
+
os.path.join(
|
26
|
+
os.path.dirname(__file__),
|
27
|
+
'sql',
|
28
|
+
)
|
29
|
+
)
|
27
30
|
|
28
|
-
INSTALL_AUDIT_LOG_SQL_FILE_NAME = 'install_audit_log.sql'
|
31
|
+
INSTALL_AUDIT_LOG_SQL_FILE_NAME = 'install_audit_log.sql'
|
@@ -72,9 +72,7 @@ class PostgreSQLErrorPack(PackValidationMixin, ObjectPack):
|
|
72
72
|
)
|
73
73
|
|
74
74
|
def get_list_window_params(self, params, request, context):
|
75
|
-
result = super(PostgreSQLErrorPack, self).get_list_window_params(
|
76
|
-
params, request, context
|
77
|
-
)
|
75
|
+
result = super(PostgreSQLErrorPack, self).get_list_window_params(params, request, context)
|
78
76
|
|
79
77
|
result['maximized'] = True
|
80
78
|
result['read_only'] = not self.delete_action.has_perm(request)
|
educommon/audit_log/helpers.py
CHANGED
@@ -20,11 +20,9 @@ if TYPE_CHECKING:
|
|
20
20
|
|
21
21
|
|
22
22
|
def get_models_table_ids(models: Union['Model', IterableType['Model']]) -> List[int]:
|
23
|
-
"""
|
24
|
-
Возвращает перечень id таблиц из AuditLog соответствующих указанным моделям.
|
25
|
-
"""
|
23
|
+
"""Возвращает перечень id таблиц из AuditLog соответствующих указанным моделям."""
|
26
24
|
if not isinstance(models, Iterable):
|
27
|
-
models = (models,
|
25
|
+
models = (models,)
|
28
26
|
|
29
27
|
table_ids = Table.objects.filter(
|
30
28
|
name__in=(model._meta.db_table for model in models),
|
@@ -37,14 +37,18 @@ class Command(BaseCommand):
|
|
37
37
|
|
38
38
|
def add_arguments(self, parser):
|
39
39
|
"""Добавление аргументов команды."""
|
40
|
+
(
|
41
|
+
parser.add_argument(
|
42
|
+
'--clear_audit_logs',
|
43
|
+
action='store_true',
|
44
|
+
default=False,
|
45
|
+
help='Удалить записи из audit_log для неотслеживаемых таблиц',
|
46
|
+
),
|
47
|
+
)
|
40
48
|
parser.add_argument(
|
41
|
-
'--
|
42
|
-
|
43
|
-
default=
|
44
|
-
help='Удалить записи из audit_log для неотслеживаемых таблиц',
|
45
|
-
),
|
46
|
-
parser.add_argument(
|
47
|
-
'--chunk_size', type=int, default=DEFAULT_QUERYSET_CHUNK_SIZE,
|
49
|
+
'--chunk_size',
|
50
|
+
type=int,
|
51
|
+
default=DEFAULT_QUERYSET_CHUNK_SIZE,
|
48
52
|
help='Кол-во единовременно удаляемых записей',
|
49
53
|
)
|
50
54
|
|
@@ -12,9 +12,7 @@ from educommon.django.db.migration.operations import (
|
|
12
12
|
|
13
13
|
|
14
14
|
class Migration(migrations.Migration):
|
15
|
-
|
16
|
-
dependencies = [
|
17
|
-
]
|
15
|
+
dependencies = []
|
18
16
|
|
19
17
|
operations = [
|
20
18
|
CreateSchema('audit', aliases=('default',)),
|
@@ -22,11 +20,33 @@ class Migration(migrations.Migration):
|
|
22
20
|
name='PostgreSQLError',
|
23
21
|
fields=[
|
24
22
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
25
|
-
(
|
23
|
+
(
|
24
|
+
'user_id',
|
25
|
+
models.IntegerField(
|
26
|
+
null=True,
|
27
|
+
verbose_name='\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c',
|
28
|
+
),
|
29
|
+
),
|
26
30
|
('ip', models.GenericIPAddressField(null=True, verbose_name='IP \u0430\u0434\u0440\u0435\u0441')),
|
27
|
-
(
|
28
|
-
|
29
|
-
|
31
|
+
(
|
32
|
+
'time',
|
33
|
+
models.DateTimeField(
|
34
|
+
auto_now_add=True, verbose_name='\u0414\u0430\u0442\u0430, \u0432\u0440\u0435\u043c\u044f'
|
35
|
+
),
|
36
|
+
),
|
37
|
+
(
|
38
|
+
'level',
|
39
|
+
models.CharField(
|
40
|
+
max_length=50,
|
41
|
+
verbose_name='\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u0448\u0438\u0431\u043a\u0438',
|
42
|
+
),
|
43
|
+
),
|
44
|
+
(
|
45
|
+
'text',
|
46
|
+
models.TextField(
|
47
|
+
verbose_name='\u0422\u0435\u043a\u0441\u0442 \u043e\u0448\u0438\u0431\u043a\u0438'
|
48
|
+
),
|
49
|
+
),
|
30
50
|
],
|
31
51
|
options={
|
32
52
|
'db_table': 'audit"."postgresql_errors',
|
@@ -38,14 +58,54 @@ class Migration(migrations.Migration):
|
|
38
58
|
name='AuditLog',
|
39
59
|
fields=[
|
40
60
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
41
|
-
(
|
42
|
-
|
61
|
+
(
|
62
|
+
'user_id',
|
63
|
+
models.IntegerField(
|
64
|
+
null=True,
|
65
|
+
verbose_name='\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c',
|
66
|
+
db_index=True,
|
67
|
+
),
|
68
|
+
),
|
69
|
+
(
|
70
|
+
'user_type_id',
|
71
|
+
models.IntegerField(
|
72
|
+
null=True,
|
73
|
+
verbose_name='\u0422\u0438\u043f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f',
|
74
|
+
db_index=True,
|
75
|
+
),
|
76
|
+
),
|
43
77
|
('ip', models.GenericIPAddressField(null=True, verbose_name='IP \u0430\u0434\u0440\u0435\u0441')),
|
44
|
-
(
|
45
|
-
|
78
|
+
(
|
79
|
+
'time',
|
80
|
+
models.DateTimeField(
|
81
|
+
auto_now_add=True,
|
82
|
+
verbose_name='\u0414\u0430\u0442\u0430, \u0432\u0440\u0435\u043c\u044f',
|
83
|
+
db_index=True,
|
84
|
+
),
|
85
|
+
),
|
86
|
+
(
|
87
|
+
'object_id',
|
88
|
+
models.IntegerField(
|
89
|
+
verbose_name='\u041e\u0431\u044a\u0435\u043a\u0442 \u043c\u043e\u0434\u0435\u043b\u0438',
|
90
|
+
db_index=True,
|
91
|
+
),
|
92
|
+
),
|
46
93
|
('data', HStoreField(null=True, verbose_name='\u041e\u0431\u044a\u0435\u043a\u0442')),
|
47
|
-
(
|
48
|
-
|
94
|
+
(
|
95
|
+
'changes',
|
96
|
+
HStoreField(null=True, verbose_name='\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f'),
|
97
|
+
),
|
98
|
+
(
|
99
|
+
'operation',
|
100
|
+
models.SmallIntegerField(
|
101
|
+
verbose_name='\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435',
|
102
|
+
choices=[
|
103
|
+
(1, '\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435'),
|
104
|
+
(2, '\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435'),
|
105
|
+
(3, '\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435'),
|
106
|
+
],
|
107
|
+
),
|
108
|
+
),
|
49
109
|
],
|
50
110
|
options={
|
51
111
|
'abstract': False,
|
@@ -56,8 +116,19 @@ class Migration(migrations.Migration):
|
|
56
116
|
name='Table',
|
57
117
|
fields=[
|
58
118
|
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
59
|
-
(
|
60
|
-
|
119
|
+
(
|
120
|
+
'name',
|
121
|
+
models.CharField(
|
122
|
+
max_length=250, verbose_name='\u0418\u043c\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b'
|
123
|
+
),
|
124
|
+
),
|
125
|
+
(
|
126
|
+
'schema',
|
127
|
+
models.CharField(
|
128
|
+
max_length=250,
|
129
|
+
verbose_name='\u0421\u0445\u0435\u043c\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u044b',
|
130
|
+
),
|
131
|
+
),
|
61
132
|
],
|
62
133
|
options={
|
63
134
|
'verbose_name': '\u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0430',
|
@@ -72,7 +143,11 @@ class Migration(migrations.Migration):
|
|
72
143
|
migrations.AddField(
|
73
144
|
model_name='auditlog',
|
74
145
|
name='table',
|
75
|
-
field=models.ForeignKey(
|
146
|
+
field=models.ForeignKey(
|
147
|
+
verbose_name='\u0422\u0430\u0431\u043b\u0438\u0446\u0430',
|
148
|
+
to='audit_log.Table',
|
149
|
+
on_delete=models.CASCADE,
|
150
|
+
),
|
76
151
|
preserve_default=True,
|
77
152
|
),
|
78
153
|
]
|
@@ -30,8 +30,7 @@ class InitDefaultDatabase(Operation):
|
|
30
30
|
def state_forwards(self, app_label, state):
|
31
31
|
pass
|
32
32
|
|
33
|
-
def database_forwards(self, app_label, schema_editor, from_state,
|
34
|
-
to_state):
|
33
|
+
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
35
34
|
if schema_editor.connection.alias != settings.DEFAULT_DB_ALIAS:
|
36
35
|
return
|
37
36
|
|
@@ -44,8 +43,7 @@ class InitDefaultDatabase(Operation):
|
|
44
43
|
|
45
44
|
schema_editor.execute(sql)
|
46
45
|
|
47
|
-
def database_backwards(self, app_label, schema_editor, from_state,
|
48
|
-
to_state):
|
46
|
+
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
49
47
|
if schema_editor.connection.alias != settings.DEFAULT_DB_ALIAS:
|
50
48
|
return
|
51
49
|
|
@@ -64,24 +62,26 @@ class LoadTableData(Operation):
|
|
64
62
|
def state_forwards(self, app_label, state):
|
65
63
|
pass
|
66
64
|
|
67
|
-
def database_forwards(self, app_label, schema_editor, from_state,
|
68
|
-
to_state):
|
65
|
+
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
69
66
|
Table = to_state.apps.get_model('audit_log', 'Table')
|
70
67
|
|
71
68
|
if self.allow_migrate_model(schema_editor.connection.alias, Table):
|
72
69
|
cursor = connections[settings.DEFAULT_DB_ALIAS].cursor()
|
73
|
-
cursor.execute(
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
70
|
+
cursor.execute(
|
71
|
+
'\n'.join(
|
72
|
+
(
|
73
|
+
'SELECT table_name, table_schema',
|
74
|
+
'FROM information_schema.tables',
|
75
|
+
"WHERE table_schema = 'public'",
|
76
|
+
)
|
77
|
+
)
|
78
|
+
)
|
78
79
|
|
79
80
|
for name, schema in cursor:
|
80
81
|
if (schema, name) not in EXCLUDED_TABLES:
|
81
82
|
Table.objects.get_or_create(name=name, schema=schema)
|
82
83
|
|
83
|
-
def database_backwards(self, app_label, schema_editor, from_state,
|
84
|
-
to_state):
|
84
|
+
def database_backwards(self, app_label, schema_editor, from_state, to_state):
|
85
85
|
pass
|
86
86
|
|
87
87
|
|
@@ -4,7 +4,6 @@ from django.db import (
|
|
4
4
|
|
5
5
|
|
6
6
|
class Migration(migrations.Migration):
|
7
|
-
|
8
7
|
dependencies = [
|
9
8
|
('audit_log', '0002_install_audit_log'),
|
10
9
|
]
|
@@ -12,8 +11,7 @@ class Migration(migrations.Migration):
|
|
12
11
|
operations = [
|
13
12
|
migrations.CreateModel(
|
14
13
|
name='LogProxy',
|
15
|
-
fields=[
|
16
|
-
],
|
14
|
+
fields=[],
|
17
15
|
options={
|
18
16
|
'proxy': True,
|
19
17
|
},
|
@@ -8,7 +8,6 @@ from educommon.audit_log.utils.operations import (
|
|
8
8
|
|
9
9
|
|
10
10
|
class Migration(migrations.Migration):
|
11
|
-
|
12
11
|
dependencies = [
|
13
12
|
('audit_log', '0004_reinstall_audit_log'),
|
14
13
|
]
|
@@ -17,6 +16,9 @@ class Migration(migrations.Migration):
|
|
17
16
|
ReinstallAuditLog(),
|
18
17
|
migrations.AlterModelOptions(
|
19
18
|
name='auditlog',
|
20
|
-
options={
|
19
|
+
options={
|
20
|
+
'verbose_name': '\u0417\u0430\u043f\u0438\u0441\u044c \u0436\u0443\u0440\u043d\u0430\u043b\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439',
|
21
|
+
'verbose_name_plural': '\u0417\u0430\u043f\u0438\u0441\u0438 \u0436\u0443\u0440\u043d\u0430\u043b\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439',
|
22
|
+
},
|
21
23
|
),
|
22
24
|
]
|
@@ -8,7 +8,6 @@ from django.db import (
|
|
8
8
|
|
9
9
|
|
10
10
|
class Migration(migrations.Migration):
|
11
|
-
|
12
11
|
dependencies = [
|
13
12
|
('audit_log', '0005_postgresql_error'),
|
14
13
|
]
|
@@ -19,8 +18,8 @@ class Migration(migrations.Migration):
|
|
19
18
|
name='time',
|
20
19
|
field=models.DateTimeField(
|
21
20
|
auto_now_add=True,
|
22
|
-
validators=[django.core.validators.MinValueValidator(
|
23
|
-
|
24
|
-
|
21
|
+
validators=[django.core.validators.MinValueValidator(datetime.datetime(1900, 1, 1, 0, 0))],
|
22
|
+
verbose_name='Дата, время',
|
23
|
+
),
|
25
24
|
),
|
26
25
|
]
|
@@ -13,14 +13,17 @@ def drop_select_table_function(apps, schema_editor):
|
|
13
13
|
return
|
14
14
|
|
15
15
|
cursor = connections[settings.DEFAULT_DB_ALIAS].cursor()
|
16
|
-
cursor.execute(
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
cursor.execute(
|
17
|
+
'\n'.join(
|
18
|
+
(
|
19
|
+
'SELECT',
|
20
|
+
"audit.drop_functions_by_name('set_for_selective_tables_triggers');",
|
21
|
+
)
|
22
|
+
)
|
23
|
+
)
|
20
24
|
|
21
25
|
|
22
26
|
class Migration(migrations.Migration):
|
23
|
-
|
24
27
|
dependencies = [
|
25
28
|
('audit_log', '0006_auto_20200806_1707'),
|
26
29
|
]
|