|
|
|
|
@ -91,10 +91,12 @@ class SynchronizationApi(HierarchyApiView): |
|
|
|
|
def post(self, request, *args, **kwargs): |
|
|
|
|
|
|
|
|
|
device_id = request.data.get('device_id') |
|
|
|
|
print(f"DataApi post > device: {device_id}") |
|
|
|
|
|
|
|
|
|
operations = request.data['operations'] |
|
|
|
|
results = [] |
|
|
|
|
print(f"DataApi post, {len(operations)} operations / device: {device_id}") |
|
|
|
|
|
|
|
|
|
models = set() |
|
|
|
|
|
|
|
|
|
for op in operations: |
|
|
|
|
result = None |
|
|
|
|
@ -104,6 +106,8 @@ class SynchronizationApi(HierarchyApiView): |
|
|
|
|
model_name = op.get('model_name') |
|
|
|
|
data = op.get('data') |
|
|
|
|
|
|
|
|
|
models.add(model_name) |
|
|
|
|
|
|
|
|
|
serializer_class = build_serializer_class(model_name) |
|
|
|
|
data['last_updated_by'] = request.user.id # always refresh the user performing the operation |
|
|
|
|
|
|
|
|
|
@ -162,6 +166,8 @@ class SynchronizationApi(HierarchyApiView): |
|
|
|
|
'message': message |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
print(f"sync POST completed for models: {models}") |
|
|
|
|
|
|
|
|
|
return Response({ |
|
|
|
|
'results': results |
|
|
|
|
}, status=207) # Multi-Status |
|
|
|
|
@ -252,7 +258,8 @@ class SynchronizationApi(HierarchyApiView): |
|
|
|
|
"date": last_log_date |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
print(f'response_data = {response_data}') |
|
|
|
|
print(f'sync GET response. UP = {len(updates)} / DEL = {len(deletions)} / G = {len(grants)} / R = {len(revocations)}') |
|
|
|
|
# print(f'sync GET response. response = {response_data}') |
|
|
|
|
return Response(response_data, status=status.HTTP_200_OK) |
|
|
|
|
|
|
|
|
|
def query_model_logs(self, last_update, user, device_id): |
|
|
|
|
@ -265,56 +272,66 @@ class UserDataAccessApi(HierarchyApiView): |
|
|
|
|
permission_classes = [IsAuthenticated] |
|
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs): |
|
|
|
|
# Get all GRANT_ACCESS and REVOKE_ACCESS logs for the user, ordered by date |
|
|
|
|
all_logs = ModelLog.objects.filter( |
|
|
|
|
Q(users=request.user) & |
|
|
|
|
(Q(operation='GRANT_ACCESS') | Q(operation='REVOKE_ACCESS')) |
|
|
|
|
).order_by('date') |
|
|
|
|
|
|
|
|
|
# Track latest status for each (model_name, model_id) |
|
|
|
|
active_grants = {} |
|
|
|
|
|
|
|
|
|
# Process logs chronologically to determine current access state |
|
|
|
|
for log in all_logs: |
|
|
|
|
if log.operation == 'GRANT_ACCESS': |
|
|
|
|
active_grants[log.model_id] = log |
|
|
|
|
elif log.operation == 'REVOKE_ACCESS': |
|
|
|
|
if log.model_id in active_grants and active_grants[log.model_id].date < log.date: |
|
|
|
|
del active_grants[log.model_id] |
|
|
|
|
|
|
|
|
|
# Convert active_grants dict to list of grant logs |
|
|
|
|
active_grants = list(active_grants.values()) |
|
|
|
|
|
|
|
|
|
# Prepare response data structure |
|
|
|
|
data_by_model = defaultdict(dict) |
|
|
|
|
|
|
|
|
|
print(f'>>> grants = {len(active_grants)}') |
|
|
|
|
try: |
|
|
|
|
# Get all DataAccess objects where the requesting user is in shared_with |
|
|
|
|
data_access_objects = DataAccess.objects.filter( |
|
|
|
|
shared_with=request.user |
|
|
|
|
).prefetch_related('shared_with') # Use prefetch_related for better performance |
|
|
|
|
|
|
|
|
|
for log in active_grants: |
|
|
|
|
try: |
|
|
|
|
model = sync_registry.get_model(log.model_name) |
|
|
|
|
instance = model.objects.get(id=log.model_id) |
|
|
|
|
data_by_model = defaultdict(dict) |
|
|
|
|
|
|
|
|
|
# Get the base data |
|
|
|
|
serializer = get_serializer(instance, log.model_name) |
|
|
|
|
data_by_model[log.model_name][log.model_id] = serializer.data |
|
|
|
|
print(f'>>> grants = {len(data_access_objects)}') |
|
|
|
|
|
|
|
|
|
# Add parents & children recursively |
|
|
|
|
self.add_children_recursively(instance, data_by_model) |
|
|
|
|
self.add_parents_recursively(instance, data_by_model) |
|
|
|
|
for data_access in data_access_objects: |
|
|
|
|
try: |
|
|
|
|
model = sync_registry.get_model(data_access.model_name) |
|
|
|
|
instance = model.objects.get(id=data_access.model_id) |
|
|
|
|
|
|
|
|
|
except ObjectDoesNotExist: |
|
|
|
|
continue |
|
|
|
|
# Get the base data |
|
|
|
|
serializer = get_serializer(instance, data_access.model_name) |
|
|
|
|
data_by_model[data_access.model_name][data_access.model_id] = serializer.data |
|
|
|
|
|
|
|
|
|
# Convert dictionary values to lists |
|
|
|
|
response_data = { |
|
|
|
|
model_name: list(model_data.values()) |
|
|
|
|
for model_name, model_data in data_by_model.items() |
|
|
|
|
} |
|
|
|
|
# Add parents & children recursively |
|
|
|
|
self.add_children_recursively(instance, data_by_model) |
|
|
|
|
self.add_parents_recursively(instance, data_by_model) |
|
|
|
|
|
|
|
|
|
print(f'response_data = {response_data}') |
|
|
|
|
except ObjectDoesNotExist: |
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
return Response(response_data, status=status.HTTP_200_OK) |
|
|
|
|
response_data = { |
|
|
|
|
model_name: list(model_data.values()) |
|
|
|
|
for model_name, model_data in data_by_model.items() |
|
|
|
|
} |
|
|
|
|
print(f'response_data = {response_data}') |
|
|
|
|
return Response(response_data, status=status.HTTP_200_OK) |
|
|
|
|
|
|
|
|
|
except Exception as e: |
|
|
|
|
return Response({ |
|
|
|
|
'status': 'error', |
|
|
|
|
'message': str(e) |
|
|
|
|
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # Get all GRANT_ACCESS and REVOKE_ACCESS logs for the user, ordered by date |
|
|
|
|
# all_logs = ModelLog.objects.filter( |
|
|
|
|
# Q(users=request.user) & |
|
|
|
|
# (Q(operation='GRANT_ACCESS') | Q(operation='REVOKE_ACCESS')) |
|
|
|
|
# ).order_by('date') |
|
|
|
|
|
|
|
|
|
# # Track latest status for each (model_name, model_id) |
|
|
|
|
# active_grants = {} |
|
|
|
|
|
|
|
|
|
# # Process logs chronologically to determine current access state |
|
|
|
|
# for log in all_logs: |
|
|
|
|
# if log.operation == 'GRANT_ACCESS': |
|
|
|
|
# active_grants[log.model_id] = log |
|
|
|
|
# elif log.operation == 'REVOKE_ACCESS': |
|
|
|
|
# if log.model_id in active_grants and active_grants[log.model_id].date < log.date: |
|
|
|
|
# del active_grants[log.model_id] |
|
|
|
|
|
|
|
|
|
# # Convert active_grants dict to list of grant logs |
|
|
|
|
# active_grants = list(active_grants.values()) |
|
|
|
|
|
|
|
|
|
# def _add_children_recursively(self, instance, data_dict): |
|
|
|
|
# """ |
|
|
|
|
|