Adding admin only endpoint to force password resets.

* Different email templates for each type
  of password reset.
* For now the force reset will be mainly for new users,
  hence "initial_password" template.

Change-Id: Ie0fecacfed7d767727bd2729fca888a45467a43d
This commit is contained in:
adriant 2015-12-18 11:24:07 +13:00
parent 3476781a0e
commit de017bd970
7 changed files with 118 additions and 3 deletions

View File

@ -109,6 +109,20 @@ TASK_SETTINGS:
handle_duplicates: cancel
emails:
initial: null
token:
subject: Password Reset for OpenStack
reply: no-reply@example.com
template: password_reset.txt
html_template: password_reset.txt
force_password:
handle_duplicates: cancel
emails:
initial: null
token:
subject: Setup Your OpenStack Password
reply: no-reply@example.com
template: initial_password.txt
html_template: initial_password.txt
edit_user:
emails:
initial: null

View File

@ -246,7 +246,7 @@ class RoleList(tasks.TaskView):
return Response({'roles': managable_roles})
class ResetPassword(tasks.ResetPassword):
class UserResetPassword(tasks.ResetPassword):
"""
The openstack forgot password endpoint.
---
@ -258,3 +258,23 @@ class ResetPassword(tasks.ResetPassword):
This returns a 404.
"""
return Response(status=404)
class UserSetPassword(tasks.ResetPassword):
"""
The openstack endpoint to force a password reset.
---
"""
task_type = "force_password"
def get(self, request):
"""
The ForcePassword endpoint does not support GET.
This returns a 404.
"""
return Response(status=404)
@utils.admin
def post(self, request, format=None):
return super(UserSetPassword, self).post(request)

View File

@ -0,0 +1,6 @@
Hello,
You can setup your initial OpenStack user password by following this link:
{{ tokenurl }}{{ token }}/
Once setup you will have access to the web dashboard.

View File

@ -0,0 +1,7 @@
Hello,
Your password reset link is:
{{ tokenurl }}{{ token }}/
If you did not request this reset ignore this email.

View File

@ -83,6 +83,7 @@ class OpenstackAPITests(APITestCase):
'user_id': "test_user_id",
'authenticated': True
}
data = {'email': "test@example.com", 'roles': ["Member"],
'project_id': 'test_project_id'}
response = self.client.post(url, data, format='json', headers=headers)
@ -104,3 +105,48 @@ class OpenstackAPITests(APITestCase):
response = self.client.get(url, headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
@mock.patch(
'stacktask.actions.models.user_store.IdentityManager', FakeManager)
def test_force_reset_password(self):
"""
Ensure the force password endpoint works as expected,
and only for admin.
Should also check if template can be rendered.
"""
user = mock.Mock()
user.id = 'user_id'
user.username = "test@example.com"
user.email = "test@example.com"
user.password = "test_password"
setup_temp_cache({}, {user.username: user})
headers = {
'project_name': "test_project",
'project_id': "test_project_id",
'roles': "Member",
'username': "test@example.com",
'user_id': "test_user_id",
'authenticated': True
}
url = "/v1/openstack/users/password-set"
data = {'email': "test@example.com"}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
response = self.client.post(url, data, format='json', headers=headers)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
headers["roles"] = "admin,Member"
response = self.client.post(url, data, format='json', headers=headers)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, None)
new_token = Token.objects.all()[0]
url = "/v1/tokens/" + new_token.token
data = {'password': 'new_test_password'}
response = self.client.post(url, data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(user.password, 'new_test_password')

View File

@ -31,9 +31,12 @@ urlpatterns = [
openstack.UserRoles.as_view()),
url(r'^openstack/users/(?P<user_id>\w+)/?$',
openstack.UserDetail.as_view()),
url(r'^openstack/users/password-reset?$',
openstack.UserResetPassword.as_view()),
url(r'^openstack/users/password-set?$',
openstack.UserSetPassword.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()),
]
if settings.SHOW_ACTION_ENDPOINTS:

View File

@ -108,7 +108,26 @@ TASK_SETTINGS = {
]
},
'reset_password': {
'handle_duplicates': 'cancel'
'handle_duplicates': 'cancel',
'emails': {
'token': {
'reply': 'no-reply@example.com',
'html_template': 'password_reset.txt',
'template': 'password_reset.txt',
'subject': 'Password Reset for OpenStack'
}
}
},
'force_password': {
'handle_duplicates': 'cancel',
'emails': {
'token': {
'reply': 'no-reply@example.com',
'html_template': 'initial_password.txt',
'template': 'initial_password.txt',
'subject': 'Setup Your OpenStack Password'
}
}
}
}