From 1526427f208f59f2d258a7449e26aedf413b9469 Mon Sep 17 00:00:00 2001 From: adriant Date: Tue, 1 Dec 2015 17:04:58 +1300 Subject: [PATCH] Allowing different TaskViews to handle Duplicates differently * In order for resetting of passwords to work correctly duplicate tasks need to be allowed. In this case as well, older duplicates should be cancelled. * Added a conf setting, and updated the duplicate check code to handle this. Change-Id: Ie6b93d271dda3a6df54e3c58e9f23c9b701cf652 --- conf/conf.yaml | 1 + stacktask/api/v1/tasks.py | 19 +++++++-- stacktask/api/v1/tests/test_api_taskview.py | 45 +++++++++++++++++++++ stacktask/test_settings.py | 1 + 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/conf/conf.yaml b/conf/conf.yaml index 2624258..539191d 100644 --- a/conf/conf.yaml +++ b/conf/conf.yaml @@ -113,6 +113,7 @@ TASK_SETTINGS: template: completed.txt html_template: completed.txt reset_password: + handle_duplicates: cancel emails: token: subject: Your Token diff --git a/stacktask/api/v1/tasks.py b/stacktask/api/v1/tasks.py index 911d0b7..3fe3fd8 100644 --- a/stacktask/api/v1/tasks.py +++ b/stacktask/api/v1/tasks.py @@ -102,14 +102,25 @@ class TaskView(APIViewWithLogger): return {'errors': errors} hash_key = create_task_hash(self.task_type, action_list) - - tasks = Task.objects.filter( + duplicate_tasks = Task.objects.filter( hash_key=hash_key, completed=0, cancelled=0) - if len(tasks) > 0: - return {'errors': ['Task is a duplicate of an existing one']} + if duplicate_tasks: + duplicate_policy = class_conf.get("handle_duplicates", "") + if duplicate_policy == "cancel": + self.logger.info( + "(%s) - Task is a duplicate - Cancelling old tasks." % + timezone.now()) + for task in duplicate_tasks: + task.cancelled = True + task.save() + else: + self.logger.info( + "(%s) - Task is a duplicate - Ignoring new task." % + timezone.now()) + return {'errors': ['Task is a duplicate of an existing task']} ip_address = request.META['REMOTE_ADDR'] keystone_user = request.keystone_user diff --git a/stacktask/api/v1/tests/test_api_taskview.py b/stacktask/api/v1/tests/test_api_taskview.py index 7db7368..d022418 100644 --- a/stacktask/api/v1/tests/test_api_taskview.py +++ b/stacktask/api/v1/tests/test_api_taskview.py @@ -363,6 +363,51 @@ class TaskViewTests(APITestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(user.password, 'new_test_password') + @mock.patch('stacktask.actions.models.user_store.IdentityManager', + FakeManager) + def test_reset_user_duplicate(self): + """ + Request password reset twice in a row + The first token should become invalid, with the second replacing it. + + """ + + user = mock.Mock() + user.id = 'user_id' + user.name = "test@example.com" + user.email = "test@example.com" + user.password = "test_password" + + setup_temp_cache({}, {user.name: user}) + + # Submit password reset + url = "/v1/actions/ResetPassword" + data = {'email': "test@example.com"} + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data, None) + + # Submit password reset again + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data, None) + + # Verify the first token doesn't work + first_token = Token.objects.all()[0] + url = "/v1/tokens/" + first_token.token + data = {'password': 'new_test_password1'} + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, 400) + self.assertEqual(user.password, 'test_password') + + # Now reset with the second token + second_token = Token.objects.all()[1] + url = "/v1/tokens/" + second_token.token + data = {'password': 'new_test_password2'} + response = self.client.post(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(user.password, 'new_test_password2') + @mock.patch('stacktask.actions.models.user_store.IdentityManager', FakeManager) def test_reset_user_no_existing(self): diff --git a/stacktask/test_settings.py b/stacktask/test_settings.py index 6cb9085..9f7f1f6 100644 --- a/stacktask/test_settings.py +++ b/stacktask/test_settings.py @@ -120,6 +120,7 @@ TASK_SETTINGS = { ] }, 'reset_password': { + 'handle_duplicates': 'cancel', 'emails': { 'token': { 'reply': 'no-reply@example.com',