Laurent 9 months ago
parent 4bd82fcf29
commit b8adfe2809
  1. 84
      sync/signals.py
  2. 15
      sync/views.py

@ -12,18 +12,13 @@ User = get_user_model()
@receiver(pre_save) @receiver(pre_save)
def presave_handler(sender, instance, **kwargs): def presave_handler(sender, instance, **kwargs):
try: synchronization_prepare(sender, instance, **kwargs)
sender.objects.get(pk=instance.pk)
created = False
except sender.DoesNotExist:
created = True
synchronization_prepare(sender, instance, created, **kwargs)
@receiver(pre_delete) # @receiver(pre_delete)
def predelete_handler(sender, instance, **kwargs): # def predelete_handler(sender, instance, **kwargs):
synchronization_prepare(sender, instance, False, **kwargs) # synchronization_prepare(sender, instance, False, **kwargs)
def synchronization_prepare(sender, instance, created, **kwargs): def synchronization_prepare(sender, instance, **kwargs):
signal = kwargs.get('signal') 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): if not isinstance(instance, BaseModel) and not isinstance(instance, User):
return 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: 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) detect_foreign_key_changes(sender, instance, device_id)
@receiver([post_save, post_delete]) @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): if not isinstance(instance, BaseModel) and not isinstance(instance, User):
return 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}') # print(f'*** instance._state.db: {instance._state.db}')
notify_impacted_users(instance) 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}') 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): def save_model_log(users, model_operation, model_name, model_id, store_id, device_id):
now = timezone.now()
# print(f'ML users = {len(users)}') # print(f'ML users = {len(users)}')
existing_log = ModelLog.objects.filter(users__in=users, model_id=model_id, operation=model_operation).first() existing_log = ModelLog.objects.filter(users__in=users, model_id=model_id, operation=model_operation).first()
if existing_log: if existing_log:
# print(f'update existing log {existing_log.users} ') # 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.device_id = device_id
# existing_log.operation = model_operation # existing_log.operation = model_operation
existing_log.save() existing_log.save()
@ -130,7 +129,7 @@ def save_model_log(users, model_operation, model_name, model_id, store_id, devic
else: else:
model_log = ModelLog() model_log = ModelLog()
model_log.operation = model_operation model_log.operation = model_operation
model_log.date = now model_log.date = timezone.now()
model_log.model_name = model_name model_log.model_name = model_name
model_log.model_id = model_id model_log.model_id = model_id
model_log.store_id = store_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) old_value = getattr(old_instance, field.name, None)
new_value = getattr(instance, field.name, None) new_value = getattr(instance, field.name, None)
if old_value != new_value: if old_value != new_value:
for data_access in data_access_list: instance._fk_changes.append({
if old_value: 'data_access_list': data_access_list,
model_name = old_value.__class__.__name__ 'old_value': old_value,
save_model_log(data_access.concerned_users(), 'REVOKE_ACCESS', model_name, old_value.id, old_value.get_store_id(), device_id) 'new_value': new_value
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) # for data_access in data_access_list:
# if old_value:
# REVOKE access for old_value and GRANT new_value # model_name = old_value.__class__.__name__
print(f"Foreign key changed in {sender.__name__}: " # save_model_log(data_access.concerned_users(), 'REVOKE_ACCESS', model_name, old_value.id, old_value.get_store_id(), device_id)
f"{field.name} from {old_value} to {new_value}") # 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) @receiver(post_delete)
def delete_data_access_if_necessary(sender, instance, **kwargs): def delete_data_access_if_necessary(sender, instance, **kwargs):

@ -94,7 +94,7 @@ class SynchronizationApi(HierarchyApiView):
operations = request.data['operations'] operations = request.data['operations']
results = [] results = []
print(f"DataApi post, {len(operations)} operations / device: {device_id}") # print(f"DataApi post, {len(operations)} operations / device: {device_id}")
models = set() models = set()
@ -149,11 +149,12 @@ class SynchronizationApi(HierarchyApiView):
instance.delete() instance.delete()
response_status = status.HTTP_204_NO_CONTENT response_status = status.HTTP_204_NO_CONTENT
except model.DoesNotExist: # POST except model.DoesNotExist: # POST
delete = ModelLog.objects.filter(model_id=data_id, operation=model_operation).first() response_status = status.HTTP_208_ALREADY_REPORTED
if delete: # delete = ModelLog.objects.filter(model_id=data_id, operation=model_operation).first()
response_status = status.HTTP_208_ALREADY_REPORTED # if delete:
else: # response_status = status.HTTP_208_ALREADY_REPORTED
response_status = status.HTTP_404_NOT_FOUND # else:
# response_status = status.HTTP_404_NOT_FOUND
except Exception as e: except Exception as e:
response_status = status.HTTP_400_BAD_REQUEST response_status = status.HTTP_400_BAD_REQUEST
@ -166,7 +167,7 @@ class SynchronizationApi(HierarchyApiView):
'message': message 'message': message
}) })
print(f"sync POST completed for models: {models}") # print(f"sync POST completed for models: {models}")
return Response({ return Response({
'results': results 'results': results

Loading…
Cancel
Save