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
This commit is contained in:
adriant 2015-12-01 17:04:58 +13:00 committed by Dale Smith
parent bd312534b1
commit 1526427f20
4 changed files with 62 additions and 4 deletions

View File

@ -113,6 +113,7 @@ TASK_SETTINGS:
template: completed.txt
html_template: completed.txt
reset_password:
handle_duplicates: cancel
emails:
token:
subject: Your Token

View File

@ -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

View File

@ -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):

View File

@ -120,6 +120,7 @@ TASK_SETTINGS = {
]
},
'reset_password': {
'handle_duplicates': 'cancel',
'emails': {
'token': {
'reply': 'no-reply@example.com',