diff --git a/sync/signals.py b/sync/signals.py index 1aed363..1312146 100644 --- a/sync/signals.py +++ b/sync/signals.py @@ -12,18 +12,13 @@ User = get_user_model() @receiver(pre_save) def presave_handler(sender, instance, **kwargs): - try: - sender.objects.get(pk=instance.pk) - created = False - except sender.DoesNotExist: - created = True - synchronization_prepare(sender, instance, created, **kwargs) + synchronization_prepare(sender, instance, **kwargs) -@receiver(pre_delete) -def predelete_handler(sender, instance, **kwargs): - synchronization_prepare(sender, instance, False, **kwargs) +# @receiver(pre_delete) +# def predelete_handler(sender, instance, **kwargs): +# synchronization_prepare(sender, instance, False, **kwargs) -def synchronization_prepare(sender, instance, created, **kwargs): +def synchronization_prepare(sender, instance, **kwargs): signal = kwargs.get('signal') @@ -35,15 +30,11 @@ def synchronization_prepare(sender, instance, created, **kwargs): if not isinstance(instance, BaseModel) and not isinstance(instance, User): return - device_id = None - if hasattr(instance, '_device_id'): - device_id = instance._device_id - - # print(f'kwargs = {kwargs}') - save_model_log_if_possible(instance, signal, created, device_id) - if signal == pre_save: - # print('yes') + device_id = None + if hasattr(instance, '_device_id'): + device_id = instance._device_id + detect_foreign_key_changes(sender, instance, device_id) @receiver([post_save, post_delete]) @@ -58,6 +49,15 @@ def synchronization_notifications(sender, instance, created=False, **kwargs): if not isinstance(instance, BaseModel) and not isinstance(instance, User): return + device_id = None + if hasattr(instance, '_device_id'): + device_id = instance._device_id + + process_foreign_key_changes(sender, instance, device_id, **kwargs) + + signal = kwargs.get('signal') + save_model_log_if_possible(instance, signal, created, device_id) + # print(f'*** instance._state.db: {instance._state.db}') notify_impacted_users(instance) @@ -117,12 +117,11 @@ def save_model_log_if_possible(instance, signal, created, device_id): print(f'>>> Model Log could not be created because no linked user could be found: {instance}, {signal}') def save_model_log(users, model_operation, model_name, model_id, store_id, device_id): - now = timezone.now() # print(f'ML users = {len(users)}') existing_log = ModelLog.objects.filter(users__in=users, model_id=model_id, operation=model_operation).first() if existing_log: # print(f'update existing log {existing_log.users} ') - existing_log.date = now + existing_log.date = timezone.now() existing_log.device_id = device_id # existing_log.operation = model_operation existing_log.save() @@ -130,7 +129,7 @@ def save_model_log(users, model_operation, model_name, model_id, store_id, devic else: model_log = ModelLog() model_log.operation = model_operation - model_log.date = now + model_log.date = timezone.now() model_log.model_name = model_name model_log.model_id = model_id model_log.store_id = store_id @@ -158,17 +157,38 @@ def detect_foreign_key_changes(sender, instance, device_id): old_value = getattr(old_instance, field.name, None) new_value = getattr(instance, field.name, None) if old_value != new_value: - for data_access in data_access_list: - if old_value: - model_name = old_value.__class__.__name__ - save_model_log(data_access.concerned_users(), 'REVOKE_ACCESS', model_name, old_value.id, old_value.get_store_id(), device_id) - if new_value: - model_name = new_value.__class__.__name__ - save_model_log(data_access.concerned_users(), 'GRANT_ACCESS', model_name, new_value.id, new_value.get_store_id(), device_id) - - # REVOKE access for old_value and GRANT new_value - print(f"Foreign key changed in {sender.__name__}: " - f"{field.name} from {old_value} to {new_value}") + instance._fk_changes.append({ + 'data_access_list': data_access_list, + 'old_value': old_value, + 'new_value': new_value + }) + + # for data_access in data_access_list: + # if old_value: + # model_name = old_value.__class__.__name__ + # save_model_log(data_access.concerned_users(), 'REVOKE_ACCESS', model_name, old_value.id, old_value.get_store_id(), device_id) + # if new_value: + # model_name = new_value.__class__.__name__ + # save_model_log(data_access.concerned_users(), 'GRANT_ACCESS', model_name, new_value.id, new_value.get_store_id(), device_id) + + # # REVOKE access for old_value and GRANT new_value + # print(f"Foreign key changed in {sender.__name__}: " + # f"{field.name} from {old_value} to {new_value}") + +def process_foreign_key_changes(sender, instance, device_id, **kwargs): + if hasattr(instance, '_fk_changes'): + for change in instance._fk_changes: + for data_access in change['data_access_list']: + if change['old_value']: + model_name = change['old_value'].__class__.__name__ + save_model_log(data_access.concerned_users(), 'REVOKE_ACCESS', + model_name, change['old_value'].id, + change['old_value'].get_store_id(), device_id) + if change['new_value']: + model_name = change['new_value'].__class__.__name__ + save_model_log(data_access.concerned_users(), 'GRANT_ACCESS', + model_name, change['new_value'].id, + change['new_value'].get_store_id(), device_id) @receiver(post_delete) def delete_data_access_if_necessary(sender, instance, **kwargs): diff --git a/sync/views.py b/sync/views.py index d009369..347f8ad 100644 --- a/sync/views.py +++ b/sync/views.py @@ -94,7 +94,7 @@ class SynchronizationApi(HierarchyApiView): operations = request.data['operations'] results = [] - print(f"DataApi post, {len(operations)} operations / device: {device_id}") + # print(f"DataApi post, {len(operations)} operations / device: {device_id}") models = set() @@ -149,11 +149,12 @@ class SynchronizationApi(HierarchyApiView): instance.delete() response_status = status.HTTP_204_NO_CONTENT except model.DoesNotExist: # POST - delete = ModelLog.objects.filter(model_id=data_id, operation=model_operation).first() - if delete: - response_status = status.HTTP_208_ALREADY_REPORTED - else: - response_status = status.HTTP_404_NOT_FOUND + response_status = status.HTTP_208_ALREADY_REPORTED + # delete = ModelLog.objects.filter(model_id=data_id, operation=model_operation).first() + # if delete: + # response_status = status.HTTP_208_ALREADY_REPORTED + # else: + # response_status = status.HTTP_404_NOT_FOUND except Exception as e: response_status = status.HTTP_400_BAD_REQUEST @@ -166,7 +167,7 @@ class SynchronizationApi(HierarchyApiView): 'message': message }) - print(f"sync POST completed for models: {models}") + # print(f"sync POST completed for models: {models}") return Response({ 'results': results