From 2a64c11bd7b39daefce00527ec49100ea779fcde Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Tue, 23 Feb 2021 15:14:32 +0100 Subject: [PATCH 2/2] api: ignore deleted users when using update/get_or_create (#51368) --- src/authentic2/api_mixins.py | 20 +++++++------------- tests/test_api.py | 11 +++++++++++ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/authentic2/api_mixins.py b/src/authentic2/api_mixins.py index 11a8af34..18896ec4 100644 --- a/src/authentic2/api_mixins.py +++ b/src/authentic2/api_mixins.py @@ -41,34 +41,28 @@ class GetOrCreateMixinView(object): def _get_lookup_keys(self, name): return self.request.GET.getlist(name) - def _get_model_class(self): - serializer_class = self.get_serializer_class() - return serializer_class.Meta.model - def _lookup_instance(self, keys): - ModelClass = self._get_model_class() - kwargs = {} for key in keys: try: kwargs[key] = self.request.data[key] except KeyError: raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: ['key %r is missing' % key]}) + + qs = self.get_queryset() try: - return ModelClass.objects.get(**kwargs) - except ModelClass.DoesNotExist: + return qs.get(**kwargs) + except qs.model.DoesNotExist: return None - except ModelClass.MultipleObjectsReturned: + except qs.model.MultipleObjectsReturned: raise Conflict('retrieved several instances of model %s for key attributes %s' % ( - ModelClass.__name__, kwargs)) + qs.model.__name__, kwargs)) def _validate_get_keys(self, keys): - ModelClass = self._get_model_class() - # Remove many-to-many relationships from validated_data. # They are not valid arguments to the default `.create()` method, # as they require that the instance has already been saved. - info = model_meta.get_field_info(ModelClass) + info = model_meta.get_field_info(self.get_queryset().model) errors = [] for key in keys: if key not in info.fields: diff --git a/tests/test_api.py b/tests/test_api.py index cf276c6e..3f6bbadb 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1462,6 +1462,17 @@ def test_api_users_get_or_create(settings, app, admin): assert User.objects.get(id=id).password != password assert User.objects.get(id=id).check_password('secret') + # do not get deleted user, create a new one + User.objects.get(id=id).mark_as_deleted() + payload['last_name'] = 'Doe' + resp = app.post_json('/api/users/?get_or_create=email', params=payload, status=201) + assert id != resp.json['id'] + id = resp.json['id'] + assert User.objects.get(id=id).first_name == 'Jane' + assert User.objects.get(id=id).last_name == 'Doe' + assert User.objects.get(id=id).password != password + assert User.objects.get(id=id).check_password('secret') + def test_api_users_get_or_create_email_is_unique(settings, app, admin): settings.A2_EMAIL_IS_UNIQUE = True -- 2.30.0