From 9ce87672d9bb19a9c101a49968e8b90658319e5d Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 10 Dec 2024 16:52:19 +0100 Subject: [PATCH] Adds related_user to BaseModel --- sync/admin.py | 4 +- ..._owner_dataaccess_related_user_and_more.py | 30 ++++ sync/models/base.py | 6 +- sync/models/data_access.py | 4 +- sync/signals.py | 70 +++----- sync/views.py | 2 +- ...elated_user_court_related_user_and_more.py | 165 ++++++++++++++++++ 7 files changed, 232 insertions(+), 49 deletions(-) create mode 100644 sync/migrations/0002_remove_dataaccess_owner_dataaccess_related_user_and_more.py create mode 100644 tournaments/migrations/0106_club_related_user_court_related_user_and_more.py diff --git a/sync/admin.py b/sync/admin.py index 42c72f8..0b73192 100644 --- a/sync/admin.py +++ b/sync/admin.py @@ -20,8 +20,8 @@ class ModelLogAdmin(admin.ModelAdmin): return ", ".join([str(item) for item in obj.users.all()]) class DataAccessAdmin(AutoUpdateAdmin): - list_display = ['owner', 'get_shared_users', 'model_name', 'model_id'] - list_filter = ['owner', 'shared_with'] + list_display = ['related_user', 'get_shared_users', 'model_name', 'model_id'] + list_filter = ['related_user', 'shared_with'] ordering = ['-granted_at'] @admin.display(description='Shared with') diff --git a/sync/migrations/0002_remove_dataaccess_owner_dataaccess_related_user_and_more.py b/sync/migrations/0002_remove_dataaccess_owner_dataaccess_related_user_and_more.py new file mode 100644 index 0000000..e845a0c --- /dev/null +++ b/sync/migrations/0002_remove_dataaccess_owner_dataaccess_related_user_and_more.py @@ -0,0 +1,30 @@ +# Generated by Django 5.1 on 2024-12-10 15:12 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sync', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.RemoveField( + model_name='dataaccess', + name='owner', + ), + migrations.AddField( + model_name='dataaccess', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='dataaccess', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/sync/models/base.py b/sync/models/base.py index 13b50b7..54a0efd 100644 --- a/sync/models/base.py +++ b/sync/models/base.py @@ -1,12 +1,13 @@ from django.db import models from django.utils.timezone import now -from typing import List, Set from django.conf import settings +from typing import List, Set class BaseModel(models.Model): creation_date = models.DateTimeField(default=now, editable=False) last_update = models.DateTimeField(default=now) - last_updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL) + 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='+') class Meta: abstract = True @@ -57,7 +58,6 @@ class BaseModel(models.Model): return parents - def get_recursive_children(self, processed_objects: Set = None) -> List: """ Recursively get all children objects through the hierarchy diff --git a/sync/models/data_access.py b/sync/models/data_access.py index ee8bf25..761f5be 100644 --- a/sync/models/data_access.py +++ b/sync/models/data_access.py @@ -1,6 +1,6 @@ from django.db import models from django.utils import timezone -from django.apps import apps +# from django.apps import apps from django.core.exceptions import ObjectDoesNotExist from django.conf import settings @@ -11,7 +11,7 @@ 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) + # 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() diff --git a/sync/signals.py b/sync/signals.py index d1771cd..55a4303 100644 --- a/sync/signals.py +++ b/sync/signals.py @@ -54,13 +54,14 @@ def notify_impacted_users(instance, signal): websocket_sender.send_user_message(user_id) # send_user_message(user_id) + def save_model_log_if_possible(instance, signal, created): if isinstance(instance, User): - user = instance + users = {instance} else: - user = instance.last_updated_by + users = related_users(instance) - if user: + if users: if signal == post_save or signal == pre_save: if created: operation = ModelOperation.POST @@ -77,16 +78,6 @@ def save_model_log_if_possible(instance, signal, created): if operation == ModelOperation.DELETE: # delete now unnecessary logs ModelLog.objects.filter(model_id=instance.id).delete() - users = {user} - if isinstance(instance, BaseModel): - data_access_list = related_data_access(instance) - for data_access in data_access_list: - users.add(data_access.owner) - users.update(data_access.shared_with.all()) - if isinstance(instance, DataAccess): - users.add(instance.owner) - users.update(instance.shared_with.all()) - user_ids = [user.id for user in users] print(f'users to notify: {user_ids}') @@ -115,12 +106,6 @@ def save_model_log(users, model_operation, model_name, model_id, store_id): model_log.save() model_log.users.set(users) -def related_data_access(instance): - 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 delete_data_access_if_necessary(model_id): DataAccess.objects.filter(model_id=model_id).delete() @@ -138,31 +123,34 @@ def handle_shared_with_changes(sender, instance, action, pk_set, **kwargs): websocket_sender.send_user_message(user_id) # send_user_message(user_id) -# def send_user_message(user_id): +@receiver(pre_delete, sender=DataAccess) +def revoke_access_after_delete(sender, instance, **kwargs): + instance.create_revoke_access_log() -# if not hasattr(send_user_message, '_buffer'): -# send_user_message._buffer = set() -# send_user_message._timer = None +def related_users(instance): + users = set() + if isinstance(instance, User): + users.add(instance) + elif isinstance(instance, BaseModel): + users.add(instance.related_user) + users.add(instance.last_updated_by) -# send_user_message._buffer.add(user_id) + related_instances = instance.related_instances() + related_users = [ri.related_user for ri in related_instances if isinstance(ri, BaseModel)] + users.update(related_users) -# if send_user_message._timer: -# send_user_message._timer.cancel() + data_access_list = related_data_access(instance, related_instances) + for data_access in data_access_list: + users.add(data_access.related_user) + users.update(data_access.shared_with.all()) -# def send_buffered_messages(): -# channel_layer = get_channel_layer() -# for buffered_id in send_user_message._buffer: -# group_name = f"sync_{buffered_id}" -# print(f">>> send to group {group_name}") -# async_to_sync(channel_layer.group_send)( -# group_name, {"type": "sync.update", "message": "hello"} -# ) -# send_user_message._buffer.clear() -# send_user_message._timer = None + if isinstance(instance, DataAccess): + users.update(instance.shared_with.all()) -# send_user_message._timer = Timer(0.1, send_buffered_messages) -# send_user_message._timer.start() + return {user for user in users if user is not None} -@receiver(pre_delete, sender=DataAccess) -def revoke_access_after_delete(sender, instance, **kwargs): - instance.create_revoke_access_log() +def 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) diff --git a/sync/views.py b/sync/views.py index affe711..fd7eed5 100644 --- a/sync/views.py +++ b/sync/views.py @@ -313,5 +313,5 @@ class DataAccessViewSet(viewsets.ModelViewSet): def get_queryset(self): if self.request.user: - return self.queryset.filter(Q(owner=self.request.user) | Q(shared_with__in=[self.request.user])) + return self.queryset.filter(Q(related_user=self.request.user) | Q(shared_with__in=[self.request.user])) return [] diff --git a/tournaments/migrations/0106_club_related_user_court_related_user_and_more.py b/tournaments/migrations/0106_club_related_user_court_related_user_and_more.py new file mode 100644 index 0000000..2cf6bc2 --- /dev/null +++ b/tournaments/migrations/0106_club_related_user_court_related_user_and_more.py @@ -0,0 +1,165 @@ +# Generated by Django 5.1 on 2024-12-10 15:12 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tournaments', '0105_rename_referees_customuser_agents'), + ] + + operations = [ + migrations.AddField( + model_name='club', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='court', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='dateinterval', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='devicetoken', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='event', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='failedapicall', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='groupstage', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='log', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='match', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='playerregistration', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='purchase', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='round', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='teamregistration', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='teamscore', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='tournament', + name='related_user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='club', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='court', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='dateinterval', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='devicetoken', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='event', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='failedapicall', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='groupstage', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='log', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='match', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='playerregistration', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='purchase', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='round', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='teamregistration', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='teamscore', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='tournament', + name='last_updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + ]