From 11a3715500d5c1c361eee9f10eeb0ae53eef22f1 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Fri, 5 Feb 2021 17:43:34 +0100 Subject: [PATCH] api: do not clobber HTTP verb methods in viewsets (#50919) --- src/authentic2/api_views.py | 6 +-- tests/test_api.py | 79 +++++++++++++------------------------ 2 files changed, 30 insertions(+), 55 deletions(-) diff --git a/src/authentic2/api_views.py b/src/authentic2/api_views.py index a4a6f356..b2791325 100644 --- a/src/authentic2/api_views.py +++ b/src/authentic2/api_views.py @@ -783,9 +783,9 @@ class UsersAPI(api_mixins.GetOrCreateMixinView, HookMixin, ExceptionHandlerMixin return new_qs return qs - # only do partial updates - def put(self, request, *args, **kwargs): - return self.patch(request, *args, **kwargs) + def update(self, request, *args, **kwargs): + kwargs['partial'] = True + return super().update(request, *args, **kwargs) def check_perm(self, perm, ou): if ou: diff --git a/tests/test_api.py b/tests/test_api.py index d3aa1ac0..854ba29b 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1626,63 +1626,31 @@ def test_api_users_required_attribute(settings, app, admin, simple_user): 'first_name': 'Johnny', } headers = basic_authorization_header(admin) - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), - params=payload, headers=headers, status=400) + + # create fails + resp = app.post_json('/api/users/', params=payload, headers=headers, status=400) assert resp.json['result'] == 0 assert resp.json['errors']['last_name'] == ['This field is required.'] + # update from missing value to blank field fails payload['last_name'] = '' - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), - params=payload, headers=headers, status=400) + resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), params=payload, headers=headers, status=400) assert resp.json['result'] == 0 assert resp.json['errors']['last_name'] == ['This field may not be blank.'] + # update with value pass payload['last_name'] = 'Foobar' - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), - params=payload, headers=headers, status=200) + resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), params=payload, headers=headers, status=200) user = User.objects.get(id=simple_user.id) assert user.last_name == 'Foobar' + # update from non-empty value to blank fails payload['last_name'] = '' - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), - params=payload, headers=headers, status=400) + resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), params=payload, headers=headers, status=400) assert resp.json['result'] == 0 assert resp.json['errors']['last_name'] == ['This field may not be blank.'] -def test_api_user_required_drf_attribute(settings, app, admin, simple_user): - Attribute.objects.create(kind='birthdate', name='birthdate', label='birthdate', required=True) - Attribute.objects.create(kind='string', name='prefered_color', label='prefered color', required=True) - Attribute.objects.get(name='birthdate').required is True - Attribute.objects.get(name='prefered_color').required is True - - payload = { - 'username': simple_user.username, - 'id': simple_user.id, - 'email': 'john.doe@nowhere.null', - 'first_name': 'Johnny', - 'last_name': 'Doe', - } - headers = basic_authorization_header(admin) - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), - params=payload, headers=headers, status=400) - assert resp.json['result'] == 0 - assert resp.json['errors'] == { - 'birthdate': ['This field is required.'], - 'prefered_color': ['This field is required.'], - } - - payload['birthdate'] = '2019-02-02' - payload['prefered_color'] = '' - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), - params=payload, headers=headers, status=400) - assert resp.json['result'] == 0 - assert resp.json['errors'] == {'prefered_color': ["This field may not be blank."]} - - Attribute.objects.filter(name='prefered_color').update(required=False) - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), params=payload, headers=headers, status=200) - - def test_api_users_required_date_attributes(settings, app, admin, simple_user): Attribute.objects.create(kind='string', name='prefered_color', label='prefered color', required=True) Attribute.objects.create(kind='date', name='date', label='date', required=True) @@ -1696,40 +1664,42 @@ def test_api_users_required_date_attributes(settings, app, admin, simple_user): 'last_name': 'Doe', } headers = basic_authorization_header(admin) - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), - params=payload, headers=headers, status=400) + + # create fails + resp = app.post_json('/api/users/', params=payload, headers=headers, status=400) assert resp.json['result'] == 0 assert resp.json['errors']['prefered_color'] == ['This field is required.'] assert resp.json['errors']['date'] == ['This field is required.'] assert resp.json['errors']['birthdate'] == ['This field is required.'] + # update from missing value to blank fails payload['prefered_color'] = '' payload['date'] = '' payload['birthdate'] = '' - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), - params=payload, headers=headers, status=400) + resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), params=payload, headers=headers, status=400) assert resp.json['result'] == 0 assert resp.json['errors']['prefered_color'] == ['This field may not be blank.'] assert resp.json['errors']['date'] == ['This field may not be blank.'] assert resp.json['errors']['birthdate'] == ['This field may not be blank.'] - payload['prefered_color'] = '?'*257 + # update with invalid values fails + payload['prefered_color'] = '?' * 257 payload['date'] = '0000-00-00' payload['birthdate'] = '1899-12-31' - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), - params=payload, headers=headers, status=400) + resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), params=payload, headers=headers, status=400) assert resp.json['result'] == 0 assert resp.json['errors']['prefered_color'] == ['Ensure this field has no more than 256 characters.'] assert any(error.startswith('Date has wrong format.') for error in resp.json['errors']['date']) assert resp.json['errors']['birthdate'] == ['birthdate must be in the past and greater or equal than 1900-01-01.'] + # update with values pass payload['prefered_color'] = 'blue' payload['date'] = '1515-1-15' payload['birthdate'] = '1900-2-22' - resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), - params=payload, headers=headers, status=200) - resp = app.get('/api/users/{}/'.format(simple_user.uuid), - headers=headers, status=200) + resp = app.put_json('/api/users/{}/'.format(simple_user.uuid), params=payload, headers=headers, status=200) + + # value are properly returned on a get + resp = app.get('/api/users/{}/'.format(simple_user.uuid), headers=headers, status=200) assert resp.json['prefered_color'] == 'blue' assert resp.json['date'] == '1515-01-15' assert resp.json['birthdate'] == '1900-02-22' @@ -2225,3 +2195,8 @@ def test_api_statistics_no_crash_older_drf(app, admin): headers = basic_authorization_header(admin) expected_status = 200 if drf_version > '3.9' else 404 resp = app.get('/api/statistics/login/?time_interval=month', headers=headers, status=expected_status) + + +def test_find_duplicates_put(app, admin, settings): + app.authorization = ('Basic', (admin.username, admin.username)) + app.put_json('/api/users/find_duplicates/', params={'first_name': 'Eleonore', 'last_name': 'aeiou'}, status=405) -- 2.30.0