Projet

Général

Profil

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

Benjamin Dauvergne, 10 octobre 2022 10:37

Télécharger (5,3 ko)

Voir les différences:

Subject: [PATCH 3/6] 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, 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
-