Fix issue where we need to grant/revoke access on foreign keys

sync
Laurent 11 months ago
parent 9ce87672d9
commit 8916ddbbeb
  1. 6
      sync/models/base.py
  2. 42
      sync/signals.py
  3. 1
      sync/views.py

@ -12,6 +12,12 @@ class BaseModel(models.Model):
class Meta: class Meta:
abstract = True abstract = True
def get_store_id(self):
if isinstance(self, SideStoreModel):
return self.store_id
else:
return None
def get_children_by_model(self): def get_children_by_model(self):
""" """
Returns a dictionary where: Returns a dictionary where:

@ -1,4 +1,5 @@
from django.db.models.signals import pre_save, post_save, pre_delete, post_delete, m2m_changed from django.db.models.signals import pre_save, post_save, pre_delete, post_delete, m2m_changed
from django.db import models
from django.dispatch import receiver from django.dispatch import receiver
from .models import DataAccess, ModelLog, ModelOperation, BaseModel, SideStoreModel from .models import DataAccess, ModelLog, ModelOperation, BaseModel, SideStoreModel
@ -18,6 +19,39 @@ def synchronization_prepare(sender, instance, created=False, **kwargs):
save_model_log_if_possible(instance, kwargs.get('signal'), created) save_model_log_if_possible(instance, kwargs.get('signal'), created)
@receiver(pre_save)
def detect_foreign_key_changes(sender, instance, **kwargs):
if not hasattr(instance, 'pk') or not instance.pk:
return
if not isinstance(instance, BaseModel):
return
data_access_list = related_data_access(instance)
if data_access_list:
try:
old_instance = sender.objects.get(pk=instance.pk)
except sender.DoesNotExist:
return
# Check foreign key fields
for field in sender._meta.get_fields():
if isinstance(field, models.ForeignKey):
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.shared_with.all(), 'REVOKE_ACCESS', model_name, old_value.id, old_value.get_store_id())
if new_value:
model_name = new_value.__class__.__name__
save_model_log(data_access.shared_with.all(), 'GRANT_ACCESS', model_name, new_value.id, new_value.get_store_id())
# def save_model_log(users, model_operation, model_name, model_id, store_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}")
@receiver([post_save, post_delete]) @receiver([post_save, post_delete])
def synchronization_notifications(sender, instance, created=False, **kwargs): def synchronization_notifications(sender, instance, created=False, **kwargs):
""" """
@ -139,7 +173,7 @@ def related_users(instance):
related_users = [ri.related_user for ri in related_instances if isinstance(ri, BaseModel)] related_users = [ri.related_user for ri in related_instances if isinstance(ri, BaseModel)]
users.update(related_users) users.update(related_users)
data_access_list = related_data_access(instance, related_instances) data_access_list = instances_related_data_access(instance, related_instances)
for data_access in data_access_list: for data_access in data_access_list:
users.add(data_access.related_user) users.add(data_access.related_user)
users.update(data_access.shared_with.all()) users.update(data_access.shared_with.all())
@ -149,7 +183,11 @@ def related_users(instance):
return {user for user in users if user is not None} return {user for user in users if user is not None}
def related_data_access(instance, related_instances): 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_instances = instance.related_instances() # related_instances = instance.related_instances()
related_ids = [ri.id for ri in related_instances] related_ids = [ri.id for ri in related_instances]
related_ids.append(instance.id) related_ids.append(instance.id)

@ -179,7 +179,6 @@ class SynchronizationApi(HierarchyApiView):
self.add_parents_recursively(instance, grants) self.add_parents_recursively(instance, grants)
elif log.operation == 'REVOKE_ACCESS': elif log.operation == 'REVOKE_ACCESS':
print(f'revoke access {log.model_id} - {log.store_id}') print(f'revoke access {log.model_id} - {log.store_id}')
# Add to revocations instead of deletions
revocations[log.model_name].append({ revocations[log.model_name].append({
'model_id': log.model_id, 'model_id': log.model_id,
'store_id': log.store_id 'store_id': log.store_id

Loading…
Cancel
Save