Projet

Général

Profil

0003-api-refactor-user-synchronization-API-endpoint-67901.patch

Benjamin Dauvergne, 02 novembre 2022 14:22

Télécharger (5,29 ko)

Voir les différences:

Subject: [PATCH 3/7] api: refactor user synchronization API endpoint (#67901)

 src/authentic2/api_views.py | 65 +++++++++++++++++++------------------
 1 file changed, 33 insertions(+), 32 deletions(-)
src/authentic2/api_views.py
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
......
797 798
        full_known_users = serializers.BooleanField(required=False)
798 799
        timestamp = serializers.DateTimeField(required=False)
799 800

  
800
    def check_uuids(self, uuids, timestamp=None):
801
        User = get_user_model()
802
        known_uuids = User.objects.filter(uuid__in=uuids).values_list('uuid', flat=True)
803
        unknown_uuids = set(uuids) - set(known_uuids)
804
        modified_users_uuids = []
805
        if timestamp:
806
            user_ct = ContentType.objects.get_for_model(get_user_model())
807
            user_events = Event.objects.filter(
808
                reference_ct_ids__contains=[user_ct.id], timestamp__gt=timestamp
809
            )
810
            for user_event in user_events:
811
                for reference in user_event.references:
812
                    if (
813
                        reference is not None  # xxx None references in journal?!
814
                        and ContentType.objects.get_for_model(reference) == user_ct
815
                        and reference.uuid not in modified_users_uuids
816
                        and reference.uuid not in unknown_uuids
817
                    ):
818
                        modified_users_uuids.append(reference.uuid)
819
        return (known_uuids, unknown_uuids, modified_users_uuids)
820

  
821
    def get_users_from_uuids(self, known_uuids):
822
        User = get_user_model()
823
        known_users = User.objects.filter(uuid__in=known_uuids)
824
        return [BaseUserSerializer(user).data for user in known_users]
801
    def check_unknown_uuids(self, remote_uuids, users):
802
        return set(remote_uuids) - {user.uuid for user in users}
803

  
804
    def check_modified_uuids(self, timestamp, users, unknown_uuids):
805
        modified_users_uuids = set()
806
        user_ct = ContentType.objects.get_for_model(get_user_model())
807
        reference_ids = [reference_integer(user) for user in users]
808
        user_events = Event.objects.filter(
809
            models.Q(reference_ids__overlap=reference_ids) | models.Q(user__in=users),
810
            timestamp__gt=timestamp,
811
        )
812
        users_pks = {user.pk: user for user in users}
813
        for user_event in user_events:
814
            for ct_id, instance_pk in user_event.get_reference_ids():
815
                if (
816
                    ct_id == user_ct.pk
817
                    and instance_pk in users_pks
818
                    and users_pks[instance_pk].uuid not in modified_users_uuids
819
                ):
820
                    modified_users_uuids.add(users_pks[instance_pk].uuid)
821
        return modified_users_uuids
825 822

  
826 823
    @action(detail=False, methods=['post'], permission_classes=(DjangoPermission('custom_user.search_user'),))
827 824
    def synchronization(self, request):
......
830 827
            response = {'result': 0, 'errors': serializer.errors}
831 828
            return Response(response, status.HTTP_400_BAD_REQUEST)
832 829
        hooks.call_hooks('api_modify_serializer_after_validation', self, serializer)
833
        known_uuids = serializer.validated_data.get('known_uuids', [])
834
        timestamp = serializer.validated_data.get('timestamp', None)
835
        known_uuids, unknown_uuids, modified_users_uuids = self.check_uuids(known_uuids, timestamp)
830
        remote_uuids = serializer.validated_data.get('known_uuids', [])
831
        users = User.objects.filter(uuid__in=remote_uuids).only('id', 'uuid')
832
        unknown_uuids = self.check_unknown_uuids(remote_uuids, users)
836 833
        data = {
837 834
            'result': 1,
838 835
            'unknown_uuids': unknown_uuids,
839
            'modified_users_uuids': modified_users_uuids,
840 836
        }
837

  
838
        timestamp = serializer.validated_data.get('timestamp', None)
839
        if timestamp:
840
            data['modified_users_uuids'] = self.check_modified_uuids(timestamp, users, unknown_uuids)
841

  
841 842
        full_known_users = serializer.validated_data.get('full_known_users', None)
842 843
        if full_known_users:
843
            if len(known_uuids) > 1000:
844
                known_uuids = known_uuids[:1000]
845
            data['known_users'] = self.get_users_from_uuids(known_uuids)
844
            # reload users to get all fields
845
            known_users = User.objects.filter(pk__in=[user.pk for user in users[:1000]])
846
            data['known_users'] = [BaseUserSerializer(user).data for user in known_users]
846 847
        hooks.call_hooks('api_modify_response', self, 'synchronization', data)
847 848
        return Response(data)
848 849

  
849
-