|
|
|
|
@ -2,7 +2,7 @@ from django.db.models.signals import pre_save, post_save, pre_delete, post_delet |
|
|
|
|
from django.db import models, transaction |
|
|
|
|
from django.dispatch import receiver |
|
|
|
|
|
|
|
|
|
from .models import DataAccess, ModelLog, ModelOperation, BaseModel, SideStoreModel |
|
|
|
|
from .models import DataAccess, ModelLog, ModelOperation, BaseModel, SideStoreModel, Device |
|
|
|
|
from django.contrib.auth import get_user_model |
|
|
|
|
from django.utils import timezone |
|
|
|
|
|
|
|
|
|
@ -10,14 +10,26 @@ from .ws_sender import websocket_sender |
|
|
|
|
|
|
|
|
|
User = get_user_model() |
|
|
|
|
|
|
|
|
|
@receiver(post_save, sender=Device) |
|
|
|
|
def device_created(sender, instance, **kwargs): |
|
|
|
|
if not instance.user: |
|
|
|
|
return |
|
|
|
|
evaluate_if_user_should_sync(instance.user) |
|
|
|
|
|
|
|
|
|
@receiver(pre_delete, sender=Device) |
|
|
|
|
def device_pre_delete(sender, instance, **kwargs): |
|
|
|
|
instance._user = instance.user if instance.user else None |
|
|
|
|
|
|
|
|
|
@receiver(post_delete, sender=Device) |
|
|
|
|
def device_post_delete(sender, instance, **kwargs): |
|
|
|
|
if not hasattr(instance, '_user') or not instance._user: |
|
|
|
|
return |
|
|
|
|
evaluate_if_user_should_sync(instance._user) |
|
|
|
|
|
|
|
|
|
@receiver(pre_save) |
|
|
|
|
def presave_handler(sender, instance, **kwargs): |
|
|
|
|
synchronization_prepare(sender, instance, **kwargs) |
|
|
|
|
|
|
|
|
|
# @receiver(pre_delete) |
|
|
|
|
# def predelete_handler(sender, instance, **kwargs): |
|
|
|
|
# synchronization_prepare(sender, instance, False, **kwargs) |
|
|
|
|
|
|
|
|
|
def synchronization_prepare(sender, instance, **kwargs): |
|
|
|
|
|
|
|
|
|
signal = kwargs.get('signal') |
|
|
|
|
@ -122,14 +134,15 @@ def save_model_log(users, model_operation, model_name, model_id, store_id, devic |
|
|
|
|
|
|
|
|
|
with transaction.atomic(): |
|
|
|
|
for user in users: |
|
|
|
|
model_log = ModelLog() |
|
|
|
|
model_log.user = user |
|
|
|
|
model_log.operation = model_operation |
|
|
|
|
model_log.model_name = model_name |
|
|
|
|
model_log.model_id = model_id |
|
|
|
|
model_log.store_id = store_id |
|
|
|
|
model_log.device_id = device_id |
|
|
|
|
model_log.save() |
|
|
|
|
if user.should_synchronize: |
|
|
|
|
model_log = ModelLog() |
|
|
|
|
model_log.user = user |
|
|
|
|
model_log.operation = model_operation |
|
|
|
|
model_log.model_name = model_name |
|
|
|
|
model_log.model_id = model_id |
|
|
|
|
model_log.store_id = store_id |
|
|
|
|
model_log.device_id = device_id |
|
|
|
|
model_log.save() |
|
|
|
|
|
|
|
|
|
# print(f'ML users = {len(users)}') |
|
|
|
|
# existing_log = ModelLog.objects.filter(users__in=users, model_id=model_id, operation=model_operation).first() |
|
|
|
|
@ -177,18 +190,6 @@ def detect_foreign_key_changes(sender, instance, device_id): |
|
|
|
|
'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: |
|
|
|
|
@ -206,6 +207,8 @@ def process_foreign_key_changes(sender, instance, device_id, **kwargs): |
|
|
|
|
|
|
|
|
|
@receiver(post_delete) |
|
|
|
|
def delete_data_access_if_necessary(sender, instance, **kwargs): |
|
|
|
|
if not isinstance(instance, BaseModel): |
|
|
|
|
return |
|
|
|
|
if hasattr(instance, 'id'): |
|
|
|
|
DataAccess.objects.filter(model_id=instance.id).delete() |
|
|
|
|
|
|
|
|
|
@ -225,10 +228,24 @@ def handle_shared_with_changes(sender, instance, action, pk_set, **kwargs): |
|
|
|
|
|
|
|
|
|
for user_id in pk_set: |
|
|
|
|
websocket_sender.send_user_message(user_id, device_id) |
|
|
|
|
for user in users: |
|
|
|
|
evaluate_if_user_should_sync(user) |
|
|
|
|
|
|
|
|
|
@receiver(post_save, sender=DataAccess) |
|
|
|
|
def data_access_post_save(sender, instance, **kwargs): |
|
|
|
|
if instance.related_user: |
|
|
|
|
evaluate_if_user_should_sync(instance.related_user) |
|
|
|
|
|
|
|
|
|
@receiver(pre_delete, sender=DataAccess) |
|
|
|
|
def revoke_access_after_delete(sender, instance, **kwargs): |
|
|
|
|
instance.create_revoke_access_log() |
|
|
|
|
instance._user = instance.related_user |
|
|
|
|
|
|
|
|
|
@receiver(post_delete, sender=DataAccess) |
|
|
|
|
def data_access_post_delete(sender, instance, **kwargs): |
|
|
|
|
if not hasattr(instance, '_user') or not instance._user: |
|
|
|
|
return |
|
|
|
|
evaluate_if_user_should_sync(instance._user) |
|
|
|
|
|
|
|
|
|
def related_users(instance): |
|
|
|
|
users = set() |
|
|
|
|
@ -259,7 +276,23 @@ def related_data_access(instance): |
|
|
|
|
return instances_related_data_access(instance, related_instances) |
|
|
|
|
|
|
|
|
|
def instances_related_data_access(instance, related_instances): |
|
|
|
|
# related_instances = instance.related_instances() |
|
|
|
|
related_ids = [ri.id for ri in related_instances] |
|
|
|
|
related_ids.append(instance.id) |
|
|
|
|
return DataAccess.objects.filter(model_id__in=related_ids) |
|
|
|
|
|
|
|
|
|
def evaluate_if_user_should_sync(user): |
|
|
|
|
should_synchronize = False |
|
|
|
|
if user.devices.count() > 1: |
|
|
|
|
should_synchronize = True |
|
|
|
|
elif DataAccess.objects.filter( |
|
|
|
|
models.Q(shared_with=user) | |
|
|
|
|
models.Q(related_user=user) |
|
|
|
|
).count() > 0: |
|
|
|
|
should_synchronize = True |
|
|
|
|
|
|
|
|
|
print(f'should_synchronize = {should_synchronize}') |
|
|
|
|
|
|
|
|
|
with transaction.atomic(): |
|
|
|
|
user.should_synchronize = should_synchronize |
|
|
|
|
# if we go from True to False we might want to delete ModelLog once the last device has synchronized |
|
|
|
|
user.save() |
|
|
|
|
|