52 |
52 |
from rest_framework.views import APIView
|
53 |
53 |
from rest_framework.viewsets import ModelViewSet, ViewSet
|
54 |
54 |
|
|
55 |
from authentic2.apps.journal.models import reference_integer
|
55 |
56 |
from authentic2.compat.drf import action
|
56 |
57 |
|
57 |
58 |
from . import api_mixins, app_settings, decorators, hooks
|
... | ... | |
796 |
797 |
full_known_users = serializers.BooleanField(required=False)
|
797 |
798 |
timestamp = serializers.DateTimeField(required=False)
|
798 |
799 |
|
799 |
|
def check_uuids(self, uuids, timestamp=None):
|
800 |
|
User = get_user_model()
|
801 |
|
known_uuids = User.objects.filter(uuid__in=uuids).values_list('uuid', flat=True)
|
802 |
|
unknown_uuids = set(uuids) - set(known_uuids)
|
803 |
|
modified_users_uuids = []
|
804 |
|
if timestamp:
|
805 |
|
user_ct = ContentType.objects.get_for_model(get_user_model())
|
806 |
|
user_events = Event.objects.filter(
|
807 |
|
reference_ct_ids__contains=[user_ct.id], timestamp__gt=timestamp
|
808 |
|
)
|
809 |
|
for user_event in user_events:
|
810 |
|
for reference in user_event.references:
|
811 |
|
if (
|
812 |
|
reference is not None # xxx None references in journal?!
|
813 |
|
and ContentType.objects.get_for_model(reference) == user_ct
|
814 |
|
and reference.uuid not in modified_users_uuids
|
815 |
|
and reference.uuid not in unknown_uuids
|
816 |
|
):
|
817 |
|
modified_users_uuids.append(reference.uuid)
|
818 |
|
return (known_uuids, unknown_uuids, modified_users_uuids)
|
819 |
|
|
820 |
|
def get_users_from_uuids(self, known_uuids):
|
821 |
|
User = get_user_model()
|
822 |
|
known_users = User.objects.filter(uuid__in=known_uuids)
|
823 |
|
return [BaseUserSerializer(user).data for user in known_users]
|
|
800 |
def check_unknown_uuids(self, remote_uuids, users):
|
|
801 |
return set(remote_uuids) - {user.uuid for user in users}
|
|
802 |
|
|
803 |
def check_modified_uuids(self, timestamp, users, unknown_uuids):
|
|
804 |
modified_users_uuids = set()
|
|
805 |
user_ct = ContentType.objects.get_for_model(get_user_model())
|
|
806 |
reference_ids = [reference_integer(user) for user in users]
|
|
807 |
user_events = Event.objects.filter(
|
|
808 |
models.Q(reference_ids__overlap=reference_ids) | models.Q(user__in=users),
|
|
809 |
timestamp__gt=timestamp,
|
|
810 |
)
|
|
811 |
users_pks = {user.pk: user for user in users}
|
|
812 |
for user_event in user_events:
|
|
813 |
for ct_id, instance_pk in user_event.get_reference_ids():
|
|
814 |
if (
|
|
815 |
ct_id == user_ct.pk
|
|
816 |
and instance_pk in users_pks
|
|
817 |
and users_pks[instance_pk].uuid not in modified_users_uuids
|
|
818 |
):
|
|
819 |
modified_users_uuids.add(users_pks[instance_pk].uuid)
|
|
820 |
return modified_users_uuids
|
824 |
821 |
|
825 |
822 |
@action(detail=False, methods=['post'], permission_classes=(DjangoPermission('custom_user.search_user'),))
|
826 |
823 |
def synchronization(self, request):
|
... | ... | |
829 |
826 |
response = {'result': 0, 'errors': serializer.errors}
|
830 |
827 |
return Response(response, status.HTTP_400_BAD_REQUEST)
|
831 |
828 |
hooks.call_hooks('api_modify_serializer_after_validation', self, serializer)
|
832 |
|
known_uuids = serializer.validated_data.get('known_uuids', [])
|
833 |
|
timestamp = serializer.validated_data.get('timestamp', None)
|
834 |
|
known_uuids, unknown_uuids, modified_users_uuids = self.check_uuids(known_uuids, timestamp)
|
|
829 |
remote_uuids = serializer.validated_data.get('known_uuids', [])
|
|
830 |
users = User.objects.filter(uuid__in=remote_uuids).only('id', 'uuid')
|
|
831 |
unknown_uuids = self.check_unknown_uuids(remote_uuids, users)
|
835 |
832 |
data = {
|
836 |
833 |
'result': 1,
|
837 |
834 |
'unknown_uuids': unknown_uuids,
|
838 |
|
'modified_users_uuids': modified_users_uuids,
|
839 |
835 |
}
|
|
836 |
|
|
837 |
timestamp = serializer.validated_data.get('timestamp', None)
|
|
838 |
if timestamp:
|
|
839 |
data['modified_users_uuids'] = self.check_modified_uuids(timestamp, users, unknown_uuids)
|
|
840 |
|
840 |
841 |
full_known_users = serializer.validated_data.get('full_known_users', None)
|
841 |
842 |
if full_known_users:
|
842 |
|
if len(known_uuids) > 1000:
|
843 |
|
known_uuids = known_uuids[:1000]
|
844 |
|
data['known_users'] = self.get_users_from_uuids(known_uuids)
|
|
843 |
# reload users to get all fields
|
|
844 |
known_users = User.objects.filter(pk__in=[user.pk for user in users[:1000]])
|
|
845 |
data['known_users'] = [BaseUserSerializer(user).data for user in known_users]
|
845 |
846 |
hooks.call_hooks('api_modify_response', self, 'synchronization', data)
|
846 |
847 |
return Response(data)
|
847 |
848 |
|
848 |
|
-
|