possible bug fix

sync_v2
Laurent 6 months ago
parent 21d0c85d27
commit b0bf249e3d
  1. 23
      sync/migrations/0005_dataaccess_data_access_ids_alter_modellog_operation.py
  2. 22
      sync/models/base.py
  3. 29
      sync/models/data_access.py
  4. 53
      sync/signals.py
  5. 83
      tournaments/migrations/0118_club_data_access_ids_court_data_access_ids_and_more.py

@ -0,0 +1,23 @@
# Generated by Django 5.1 on 2025-05-23 14:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('sync', '0004_delete_device'),
]
operations = [
migrations.AddField(
model_name='dataaccess',
name='data_access_ids',
field=models.JSONField(default=list),
),
migrations.AlterField(
model_name='modellog',
name='operation',
field=models.CharField(choices=[('POST', 'POST'), ('PUT', 'PUT'), ('DELETE', 'DELETE'), ('SHARED_ACCESS', 'SHARED_ACCESS'), ('REVOKED_ACCESS', 'REVOKED_ACCESS'), ('SHARED_RELATIONSHIP_SET', 'SHARED_RELATIONSHIP_SET'), ('SHARED_RELATIONSHIP_REMOVED', 'SHARED_RELATIONSHIP_REMOVED')], max_length=50),
),
]

@ -3,11 +3,14 @@ from django.utils.timezone import now
from django.conf import settings
from typing import List, Set
from django.apps import apps
class BaseModel(models.Model):
creation_date = models.DateTimeField(default=now, editable=False)
last_update = models.DateTimeField(default=now)
related_user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL, related_name='+')
last_updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL, related_name='+')
data_access_ids = models.JSONField(default=list)
class Meta:
abstract = True
@ -15,6 +18,7 @@ class BaseModel(models.Model):
def save(self, *args, **kwargs):
if self.related_user is None:
self.related_user = self.find_related_user()
self.update_data_access_list()
super().save(*args, **kwargs)
def get_store_id(self):
@ -23,6 +27,24 @@ class BaseModel(models.Model):
else:
return None
def update_data_access_list(self):
related_instances = self.related_instances()
related_ids = [ri.id for ri in related_instances]
related_ids.append(self.id)
DataAccess = apps.get_model('sync', 'DataAccess')
data_accesses = DataAccess.objects.filter(model_id__in=related_ids)
for data_access in data_accesses:
self.add_data_access_relation(data_access)
def add_data_access_relation(self, data_access):
str_id = str(data_access.id)
if str_id not in self.data_access_ids:
self.data_access_ids.append(str_id)
def remove_data_access_relation(self, data_access):
self.data_access_ids.remove(str(data_access.id))
def get_children_by_model(self):
"""
Returns a dictionary where:

@ -9,14 +9,13 @@ import uuid
from . import ModelLog, SideStoreModel, BaseModel
class DataAccess(BaseModel):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
# owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='owned_data', on_delete=models.CASCADE)
shared_with = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='shared_data')
model_name = models.CharField(max_length=50)
model_id = models.UUIDField()
granted_at = models.DateTimeField(auto_now_add=True)
# last_hierarchy_update = models.DateTimeField(default=timezone.now)
def delete_dependencies(self):
pass
@ -59,3 +58,29 @@ class DataAccess(BaseModel):
pass
else:
print(f'model not found: {self.model_name}')
def add_references(self):
model_class = model_registry.get_model(self.model_name)
if model_class:
try:
obj = model_class.objects.get(id=self.model_id)
related_instance = obj.related_instances()
for instance in related_instance:
if isinstance(instance, BaseModel):
instance.add_data_access_relation(self)
instance.save()
except ObjectDoesNotExist:
pass
def cleanup_references(self):
model_class = model_registry.get_model(self.model_name)
if model_class:
try:
obj = model_class.objects.get(id=self.model_id)
related_instance = obj.related_instances()
for instance in related_instance:
if isinstance(instance, BaseModel):
instance.remove_data_access_relation(self)
instance.save()
except ObjectDoesNotExist:
pass

@ -13,24 +13,6 @@ from .registry import device_registry, related_users_registry
User = get_user_model()
### Device
@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)
### Sync
@receiver([pre_save, pre_delete])
@ -139,9 +121,11 @@ def save_model_log(users, model_operation, model_name, model_id, store_id):
device_id = device_registry.get_device_id(model_id)
# print(f'>> creating Model Log for: {model_operation} {model_name}')
with transaction.atomic():
for user in users:
# print(f'>>> create log for {user.username} : {model_operation} {model_name}')
# print(f' * {user.username}')
# if user.should_synchronize:
model_log = ModelLog()
@ -273,11 +257,14 @@ def handle_shared_with_changes(sender, instance, action, pk_set, **kwargs):
@receiver(post_save, sender=DataAccess)
def data_access_post_save(sender, instance, **kwargs):
instance.add_references() # create DataAccess references on hierarchy
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.cleanup_references()
instance.create_revoke_access_log()
related_users_registry.register(instance.id, instance.shared_with.all())
@ -300,13 +287,16 @@ def related_users(instance):
# users.add(instance.last_updated_by)
# look in hierarchy
related_instances = instance.related_instances()
# 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)
# look in related DataAccess
data_access_list = instances_related_data_access(instance, related_instances)
# data_access_list = instances_related_data_access(instance, related_instances)
# print(f'instance = {instance.__class__.__name__}, data access count = {len(data_access_list)}')
for data_access in data_access_list:
users.add(data_access.related_user)
users.update(data_access.shared_with.all())
@ -318,9 +308,6 @@ def related_users(instance):
def related_data_access(instance):
related_instances = instance.related_instances()
return instances_related_data_access(instance, related_instances)
def instances_related_data_access(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)
@ -339,3 +326,21 @@ def evaluate_if_user_should_sync(user):
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()
### Device
@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)

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save