|
|
|
@ -6,11 +6,14 @@ from .models import DataAccess, ModelLog, ModelOperation, BaseModel, SideStoreMo |
|
|
|
from authentication.models import Device |
|
|
|
from authentication.models import Device |
|
|
|
|
|
|
|
|
|
|
|
from django.contrib.auth import get_user_model |
|
|
|
from django.contrib.auth import get_user_model |
|
|
|
from django.utils import timezone |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from .ws_sender import websocket_sender |
|
|
|
from .ws_sender import websocket_sender |
|
|
|
from .registry import device_registry, related_users_registry |
|
|
|
from .registry import device_registry, related_users_registry |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import logging |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
|
|
|
|
|
|
User = get_user_model() |
|
|
|
User = get_user_model() |
|
|
|
|
|
|
|
|
|
|
|
### Sync |
|
|
|
### Sync |
|
|
|
@ -28,12 +31,18 @@ def presave_handler(sender, instance, **kwargs): |
|
|
|
return |
|
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
users = related_users(instance) |
|
|
|
users = related_users(instance) |
|
|
|
# print(f'* impacted users = {users}') |
|
|
|
|
|
|
|
related_users_registry.register(instance.id, users) |
|
|
|
related_users_registry.register(instance.id, users) |
|
|
|
# user_ids = [user.id for user in users] |
|
|
|
# user_ids = [user.id for user in users] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if signal == pre_save: |
|
|
|
if signal == pre_save: |
|
|
|
detect_foreign_key_changes_for_shared_instances(sender, instance) |
|
|
|
detect_foreign_key_changes_for_shared_instances(sender, instance) |
|
|
|
|
|
|
|
sig_type = 'pre_save' |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
sig_type = 'pre_delete' |
|
|
|
|
|
|
|
logger.info(f'* {sig_type} : {instance.__class__.__name__} > impacted users = {users}') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@receiver([post_save, post_delete]) |
|
|
|
@receiver([post_save, post_delete]) |
|
|
|
def synchronization_notifications(sender, instance, created=False, **kwargs): |
|
|
|
def synchronization_notifications(sender, instance, created=False, **kwargs): |
|
|
|
@ -87,7 +96,14 @@ def notify_impacted_users(instance): |
|
|
|
def save_model_log_if_possible(instance, signal, created): |
|
|
|
def save_model_log_if_possible(instance, signal, created): |
|
|
|
|
|
|
|
|
|
|
|
users = related_users_registry.get_users(instance.id) |
|
|
|
users = related_users_registry.get_users(instance.id) |
|
|
|
# print(f'*** save_model_log >>> users = {users}, instance = {instance}') |
|
|
|
logger.debug(f'*** save_model_log_if_possible >>> users from registry = {users}, instance = {instance}') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not users: |
|
|
|
|
|
|
|
logger.warning(f'!!! Registry returned empty users for instance {instance.id} ({instance.__class__.__name__})') |
|
|
|
|
|
|
|
# Try to recalculate users as fallback |
|
|
|
|
|
|
|
users = related_users(instance) |
|
|
|
|
|
|
|
logger.info(f'!!! Recalculated users for fallback: {users}') |
|
|
|
|
|
|
|
|
|
|
|
if users: |
|
|
|
if users: |
|
|
|
if signal == post_save or signal == pre_save: |
|
|
|
if signal == post_save or signal == pre_save: |
|
|
|
if created: |
|
|
|
if created: |
|
|
|
@ -111,16 +127,20 @@ def save_model_log_if_possible(instance, signal, created): |
|
|
|
save_model_log(users, operation, model_name, instance.id, store_id) |
|
|
|
save_model_log(users, operation, model_name, instance.id, store_id) |
|
|
|
|
|
|
|
|
|
|
|
else: |
|
|
|
else: |
|
|
|
print(f'>>> Model Log could not be created because no linked user could be found: {instance.__class__.__name__} {instance}, {signal}') |
|
|
|
logger.info(f'!!! Model Log could not be created because no linked user could be found: {instance.__class__.__name__} {instance}, {signal}') |
|
|
|
|
|
|
|
|
|
|
|
def save_model_log(users, model_operation, model_name, model_id, store_id): |
|
|
|
def save_model_log(users, model_operation, model_name, model_id, store_id): |
|
|
|
|
|
|
|
|
|
|
|
device_id = device_registry.get_device_id(model_id) |
|
|
|
device_id = device_registry.get_device_id(model_id) |
|
|
|
|
|
|
|
|
|
|
|
# print(f'>> creating Model Log for: {model_operation} {model_name}') |
|
|
|
logger.info(f'*** creating ModelLogs for: {model_operation} {model_name} : {users}') |
|
|
|
|
|
|
|
|
|
|
|
logs_to_create = [ |
|
|
|
try: |
|
|
|
ModelLog( |
|
|
|
with transaction.atomic(): |
|
|
|
|
|
|
|
created_logs = [] |
|
|
|
|
|
|
|
for user in users: |
|
|
|
|
|
|
|
logger.debug(f'Creating ModelLog for user {user.id} ({user.username})') |
|
|
|
|
|
|
|
model_log = ModelLog( |
|
|
|
user=user, |
|
|
|
user=user, |
|
|
|
operation=model_operation, |
|
|
|
operation=model_operation, |
|
|
|
model_name=model_name, |
|
|
|
model_name=model_name, |
|
|
|
@ -128,12 +148,22 @@ def save_model_log(users, model_operation, model_name, model_id, store_id): |
|
|
|
store_id=store_id, |
|
|
|
store_id=store_id, |
|
|
|
device_id=device_id |
|
|
|
device_id=device_id |
|
|
|
) |
|
|
|
) |
|
|
|
for user in users |
|
|
|
model_log.save() |
|
|
|
if user.can_synchronize |
|
|
|
created_logs.append(model_log.id) |
|
|
|
] |
|
|
|
logger.debug(f'Successfully created ModelLog {model_log.id}') |
|
|
|
|
|
|
|
|
|
|
|
with transaction.atomic(): |
|
|
|
logger.info(f'*** Successfully created {len(created_logs)} ModelLogs: {created_logs}') |
|
|
|
ModelLog.objects.bulk_create(logs_to_create) |
|
|
|
|
|
|
|
|
|
|
|
# Verify ModelLogs were actually persisted |
|
|
|
|
|
|
|
persisted_count = ModelLog.objects.filter(id__in=created_logs).count() |
|
|
|
|
|
|
|
if persisted_count != len(created_logs): |
|
|
|
|
|
|
|
logger.error(f'*** PERSISTENCE VERIFICATION FAILED! Created {len(created_logs)} ModelLogs but only {persisted_count} were persisted to database') |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
logger.debug(f'*** PERSISTENCE VERIFIED: All {persisted_count} ModelLogs successfully persisted') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
|
|
logger.error(f'*** FAILED to create ModelLogs for: {model_operation} {model_name}, users: {[u.id for u in users]}, error: {e}', exc_info=True) |
|
|
|
|
|
|
|
raise |
|
|
|
|
|
|
|
|
|
|
|
# with transaction.atomic(): |
|
|
|
# with transaction.atomic(): |
|
|
|
# for user in users: |
|
|
|
# for user in users: |
|
|
|
@ -258,6 +288,7 @@ def handle_shared_with_changes(sender, instance, action, pk_set, **kwargs): |
|
|
|
# print(f'm2m changed = {pk_set}') |
|
|
|
# print(f'm2m changed = {pk_set}') |
|
|
|
users = User.objects.filter(id__in=pk_set) |
|
|
|
users = User.objects.filter(id__in=pk_set) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with transaction.atomic(): |
|
|
|
if action == "post_add": |
|
|
|
if action == "post_add": |
|
|
|
instance.create_access_log(users, 'SHARED_ACCESS') |
|
|
|
instance.create_access_log(users, 'SHARED_ACCESS') |
|
|
|
elif action == "post_remove": |
|
|
|
elif action == "post_remove": |
|
|
|
@ -302,18 +333,8 @@ def related_users(instance): |
|
|
|
users.add(instance) |
|
|
|
users.add(instance) |
|
|
|
elif isinstance(instance, BaseModel): |
|
|
|
elif isinstance(instance, BaseModel): |
|
|
|
users.add(instance.related_user) |
|
|
|
users.add(instance.related_user) |
|
|
|
# users.add(instance.last_updated_by) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# look in hierarchy |
|
|
|
|
|
|
|
# related_instances = instance.related_instances() |
|
|
|
|
|
|
|
# print(f'related_instances = {related_instances}') |
|
|
|
|
|
|
|
# related_users = [ri.related_user for ri in related_instances if isinstance(ri, BaseModel)] |
|
|
|
|
|
|
|
# users.update(related_users) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
data_access_list = DataAccess.objects.filter(id__in=instance.data_access_ids) |
|
|
|
data_access_list = DataAccess.objects.filter(id__in=instance.data_access_ids) |
|
|
|
|
|
|
|
|
|
|
|
# look in related DataAccess |
|
|
|
|
|
|
|
# data_access_list = instances_related_data_access(instance, related_instances) |
|
|
|
|
|
|
|
# print(f'instance = {instance.__class__.__name__}, data access count = {len(data_access_list)}') |
|
|
|
# print(f'instance = {instance.__class__.__name__}, data access count = {len(data_access_list)}') |
|
|
|
for data_access in data_access_list: |
|
|
|
for data_access in data_access_list: |
|
|
|
users.add(data_access.related_user) |
|
|
|
users.add(data_access.related_user) |
|
|
|
|