From 962ee0265686a9b9f5abd97c2703f5e0e3afadcd Mon Sep 17 00:00:00 2001 From: Dale Smith Date: Tue, 24 Nov 2015 17:36:47 +0000 Subject: [PATCH] Adding the openstack/forgotpassword endpoint. Inherits from tasks version. Change-Id: I2f5f656ce714f0fddb3c13ab8833ae38cb79abb5 --- stacktask/api/v1/openstack.py | 14 ++++++++++++++ stacktask/api/v1/tasks.py | 22 +++++++++++++++++++++- stacktask/api/v1/tests.py | 20 ++++++++++---------- stacktask/api/v1/urls.py | 1 + stacktask/middleware.py | 2 +- 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/stacktask/api/v1/openstack.py b/stacktask/api/v1/openstack.py index da35140..3bce12e 100644 --- a/stacktask/api/v1/openstack.py +++ b/stacktask/api/v1/openstack.py @@ -228,3 +228,17 @@ class RoleList(tasks.TaskView): managable_roles.append(role.to_dict()) return Response({'roles': managable_roles}) + + +class ResetPassword(tasks.ResetPassword): + """ + The openstack forgot password endpoint. + --- + """ + + def get(self, request): + """ + The ResetPassword endpoint does not support GET. + This returns a 404. + """ + return Response(status=404) diff --git a/stacktask/api/v1/tasks.py b/stacktask/api/v1/tasks.py index e942b92..345f6db 100644 --- a/stacktask/api/v1/tasks.py +++ b/stacktask/api/v1/tasks.py @@ -385,6 +385,25 @@ class ResetPassword(TaskView): def post(self, request, format=None): """ Unauthenticated endpoint bound to the password reset action. + This will submit and approve a password reset request. + --- + parameters: + - name: email + required: true + type: string + description: The email of the user to reset + - name: username + required: false + type: string + description: The username of the user, not required if using + USERNAME_IS_PASSWORD + + responseMessages: + - code: 400 + message: Validation Errors + - code: 200 + message: Success. Does not indicate user exists. + """ self.logger.info("(%s) - New ResetUser request." % timezone.now()) processed = self.process_actions(request) @@ -398,7 +417,8 @@ class ResetPassword(TaskView): task = processed['task'] self.logger.info("(%s) - AutoApproving Resetuser request." % timezone.now()) - return self.approve(task) + self.approve(task) + return Response(status=200) class EditUser(TaskView): diff --git a/stacktask/api/v1/tests.py b/stacktask/api/v1/tests.py index b736815..62ecdda 100644 --- a/stacktask/api/v1/tests.py +++ b/stacktask/api/v1/tests.py @@ -466,7 +466,7 @@ class APITests(APITestCase): 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, {'notes': ['created token']}) + self.assertEqual(response.data, None) new_token = Token.objects.all()[0] url = "/v1/tokens/" + new_token.token @@ -479,16 +479,16 @@ class APITests(APITestCase): FakeManager) def test_reset_user_no_existing(self): """ - Actions should be invalid. + Actions should be successful, so usernames are not exposed. """ setup_temp_cache({}, {}) url = "/v1/actions/ResetPassword" - data = {'email': "test@example.com"} + data = {'email': "test@exampleinvalid.com"} response = self.client.post(url, data, format='json') - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual(response.data, {'errors': ['actions invalid']}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data, None) def test_no_token_get(self): """ @@ -567,7 +567,7 @@ class APITests(APITestCase): 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, {'notes': ['created token']}) + self.assertEqual(response.data, None) new_token = Token.objects.all()[0] new_token.expires = timezone.now() - timedelta(hours=24) @@ -600,7 +600,7 @@ class APITests(APITestCase): 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, {'notes': ['created token']}) + self.assertEqual(response.data, None) new_token = Token.objects.all()[0] new_token.expires = timezone.now() - timedelta(hours=24) @@ -843,13 +843,13 @@ class APITests(APITestCase): 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, {'notes': ['created token']}) + self.assertEqual(response.data, None) url = "/v1/actions/ResetPassword" data = {'email': "test2@example.com"} response = self.client.post(url, data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertEqual(response.data, {'notes': ['created token']}) + self.assertEqual(response.data, None) tokens = Token.objects.all() @@ -893,7 +893,7 @@ class APITests(APITestCase): 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, {'notes': ['created token']}) + self.assertEqual(response.data, None) task = Task.objects.all()[0] new_token = Token.objects.all()[0] diff --git a/stacktask/api/v1/urls.py b/stacktask/api/v1/urls.py index 3b532e2..f7b143d 100644 --- a/stacktask/api/v1/urls.py +++ b/stacktask/api/v1/urls.py @@ -36,4 +36,5 @@ urlpatterns = [ url(r'^openstack/users/(?P\w+)/?$', openstack.UserDetail.as_view()), url(r'^openstack/users/?$', openstack.UserList.as_view()), url(r'^openstack/roles/?$', openstack.RoleList.as_view()), + url(r'^openstack/forgotpassword/?$', openstack.ResetPassword.as_view()), ] diff --git a/stacktask/middleware.py b/stacktask/middleware.py index c1f77ef..b3103f4 100644 --- a/stacktask/middleware.py +++ b/stacktask/middleware.py @@ -75,7 +75,7 @@ class RequestLoggingMiddleware(object): request.timer = time() def process_response(self, request, response): - if getattr(request, 'timer'): + if hasattr(request, 'timer'): time_delta = time() - request.timer else: time_delta = -1