Additional tests for USERNAME_IS_EMAIL=False
Note that while all of the base stacktask codebase works with this setting, not all of the client and horizon will work with it. This is due to when the settings change a number of actions now also require a username field to be filled in, and there isn't a way for the clients to determine whether or not this is the case. Change-Id: Ie91f7634b3686a1535af1c3344be217db5a80d15
This commit is contained in:
parent
cf100fc804
commit
ed6bb16cd1
|
@ -397,6 +397,8 @@ class UserNameAction(BaseAction):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if settings.USERNAME_IS_EMAIL:
|
||||
# NOTE(amelia): Make a copy to avoid editing it globally.
|
||||
self.required = list(self.required)
|
||||
try:
|
||||
self.required.remove('username')
|
||||
except ValueError:
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# under the License.
|
||||
|
||||
from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
|
||||
import mock
|
||||
|
||||
|
@ -450,6 +451,60 @@ class ProjectActionTests(TestCase):
|
|||
action.post_approve()
|
||||
self.assertEquals(action.valid, False)
|
||||
|
||||
@override_settings(USERNAME_IS_EMAIL=False)
|
||||
def test_new_project_email_not_username(self):
|
||||
"""
|
||||
Base case, no project, no user.
|
||||
|
||||
Project and user created at post_approve step,
|
||||
user password at submit step.
|
||||
"""
|
||||
|
||||
setup_temp_cache({}, {})
|
||||
|
||||
task = Task.objects.create(
|
||||
ip_address="0.0.0.0",
|
||||
keystone_user={}
|
||||
)
|
||||
|
||||
data = {
|
||||
'domain_id': 'default',
|
||||
'parent_id': None,
|
||||
'email': 'test@example.com',
|
||||
'username': 'test_user',
|
||||
'project_name': 'test_project',
|
||||
}
|
||||
|
||||
action = NewProjectWithUserAction(data, task=task, order=1)
|
||||
|
||||
action.pre_approve()
|
||||
self.assertEquals(action.valid, True)
|
||||
|
||||
action.post_approve()
|
||||
self.assertEquals(action.valid, True)
|
||||
self.assertEquals(
|
||||
tests.temp_cache['projects']['test_project'].name,
|
||||
'test_project')
|
||||
self.assertEquals(
|
||||
task.cache,
|
||||
{'project_id': 'project_id_1', 'user_id': 'user_id_1',
|
||||
'user_state': 'default'})
|
||||
|
||||
token_data = {'password': '123456'}
|
||||
action.submit(token_data)
|
||||
self.assertEquals(action.valid, True)
|
||||
self.assertEquals(
|
||||
tests.temp_cache['users']["user_id_1"].email,
|
||||
'test@example.com')
|
||||
self.assertEquals(
|
||||
tests.temp_cache['users']["user_id_1"].name,
|
||||
'test_user')
|
||||
project = tests.temp_cache['projects']['test_project']
|
||||
self.assertEquals(
|
||||
sorted(project.roles["user_id_1"]),
|
||||
sorted(['_member_', 'project_admin',
|
||||
'project_mod', 'heat_stack_owner']))
|
||||
|
||||
@modify_dict_settings(DEFAULT_ACTION_SETTINGS={
|
||||
'key_list': ['AddDefaultUsersToProjectAction'],
|
||||
'operation': 'override',
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
import mock
|
||||
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from stacktask.actions.v1.users import (
|
||||
EditUserRolesAction, NewUserAction, ResetUserPasswordAction)
|
||||
from stacktask.api.models import Task
|
||||
|
@ -832,3 +834,113 @@ class UserActionTests(StacktaskTestCase):
|
|||
self.assertEquals(len(project.roles[user.id]), 2)
|
||||
self.assertEquals(set(project.roles[user.id]),
|
||||
set(['project_mod', 'new_role']))
|
||||
|
||||
# Simple positive tests for when USERNAME_IS_EMAIL=False
|
||||
@override_settings(USERNAME_IS_EMAIL=False)
|
||||
def test_create_user_email_not_username(self):
|
||||
"""
|
||||
Test the default case, all valid.
|
||||
No existing user, valid tenant.
|
||||
Different username from email address
|
||||
"""
|
||||
project = mock.Mock()
|
||||
project.id = 'test_project_id'
|
||||
project.name = 'test_project'
|
||||
project.domain = 'default'
|
||||
project.roles = {}
|
||||
|
||||
setup_temp_cache({'test_project': project}, {})
|
||||
|
||||
task = Task.objects.create(
|
||||
ip_address="0.0.0.0",
|
||||
keystone_user={
|
||||
'roles': ['admin', 'project_mod'],
|
||||
'project_id': 'test_project_id',
|
||||
'project_domain_id': 'default',
|
||||
})
|
||||
|
||||
data = {
|
||||
'username': 'test_user',
|
||||
'email': 'test@example.com',
|
||||
'project_id': 'test_project_id',
|
||||
'roles': ['_member_'],
|
||||
'domain_id': 'default',
|
||||
}
|
||||
|
||||
action = NewUserAction(data, task=task, order=1)
|
||||
|
||||
action.pre_approve()
|
||||
self.assertEquals(action.valid, True)
|
||||
|
||||
action.post_approve()
|
||||
self.assertEquals(action.valid, True)
|
||||
|
||||
token_data = {'password': '123456'}
|
||||
action.submit(token_data)
|
||||
self.assertEquals(action.valid, True)
|
||||
self.assertEquals(len(tests.temp_cache['users']), 2)
|
||||
# The new user id in this case will be "user_id_1"
|
||||
self.assertEquals(
|
||||
tests.temp_cache['users']["user_id_1"].email,
|
||||
'test@example.com')
|
||||
self.assertEquals(
|
||||
tests.temp_cache['users']["user_id_1"].name,
|
||||
'test_user')
|
||||
self.assertEquals(
|
||||
tests.temp_cache['users']["user_id_1"].password,
|
||||
'123456')
|
||||
|
||||
self.assertEquals(project.roles["user_id_1"], ['_member_'])
|
||||
|
||||
@override_settings(USERNAME_IS_EMAIL=False)
|
||||
def test_reset_user_email_not_username(self):
|
||||
"""
|
||||
Base case, existing user.
|
||||
Username not email address
|
||||
"""
|
||||
|
||||
user = mock.Mock()
|
||||
user.id = 'user_id'
|
||||
user.name = "test_user"
|
||||
user.email = "test@example.com"
|
||||
user.domain = 'default'
|
||||
user.password = "gibberish"
|
||||
|
||||
setup_temp_cache({}, {user.id: user})
|
||||
|
||||
task = Task.objects.create(
|
||||
ip_address="0.0.0.0",
|
||||
keystone_user={
|
||||
'roles': ['admin', 'project_mod'],
|
||||
'project_id': 'test_project_id',
|
||||
'project_domain_id': 'default',
|
||||
})
|
||||
|
||||
data = {
|
||||
'username': "test_user",
|
||||
'domain_name': 'Default',
|
||||
'email': 'test@example.com',
|
||||
'project_name': 'test_project',
|
||||
}
|
||||
|
||||
action = ResetUserPasswordAction(data, task=task, order=1)
|
||||
|
||||
action.pre_approve()
|
||||
self.assertEquals(action.valid, True)
|
||||
|
||||
action.post_approve()
|
||||
self.assertEquals(action.valid, True)
|
||||
|
||||
token_data = {'password': '123456'}
|
||||
action.submit(token_data)
|
||||
self.assertEquals(action.valid, True)
|
||||
|
||||
self.assertEquals(
|
||||
tests.temp_cache['users'][user.id].password,
|
||||
'123456')
|
||||
self.assertEquals(
|
||||
tests.temp_cache['users'][user.id].name,
|
||||
'test_user')
|
||||
self.assertEquals(
|
||||
tests.temp_cache['users'][user.id].email,
|
||||
'test@example.com')
|
||||
|
|
|
@ -17,6 +17,8 @@ import mock
|
|||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from django.test.utils import override_settings
|
||||
|
||||
from stacktask.api.models import Token
|
||||
from stacktask.api.v1.tests import FakeManager, setup_temp_cache
|
||||
|
||||
|
@ -239,3 +241,38 @@ class OpenstackAPITests(APITestCase):
|
|||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data,
|
||||
{'notes': ['Task completed successfully.']})
|
||||
|
||||
@override_settings(USERNAME_IS_EMAIL=False)
|
||||
def test_new_user_username_not_email(self):
|
||||
"""
|
||||
Ensure the new user workflow goes as expected.
|
||||
Create task, create token, submit token.
|
||||
"""
|
||||
project = mock.Mock()
|
||||
project.id = 'test_project_id'
|
||||
project.name = 'test_project'
|
||||
project.domain = 'default'
|
||||
project.roles = {}
|
||||
|
||||
setup_temp_cache({'test_project': project}, {})
|
||||
|
||||
url = "/v1/openstack/users"
|
||||
headers = {
|
||||
'project_name': "test_project",
|
||||
'project_id': "test_project_id",
|
||||
'roles': "project_admin,_member_,project_mod",
|
||||
'username': "test@example.com",
|
||||
'user_id': "test_user_id",
|
||||
'authenticated': True
|
||||
}
|
||||
data = {'email': "test@example.com", 'roles': ["_member_"],
|
||||
'project_id': 'test_project_id', 'username': 'user_name'}
|
||||
response = self.client.post(url, data, format='json', headers=headers)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data, {'notes': ['created token']})
|
||||
|
||||
new_token = Token.objects.all()[0]
|
||||
url = "/v1/tokens/" + new_token.token
|
||||
data = {'password': 'testpassword'}
|
||||
response = self.client.post(url, data, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
|
|
@ -19,6 +19,10 @@ from rest_framework import status
|
|||
from stacktask.api.models import Task, Token
|
||||
from stacktask.api.v1.tests import (FakeManager, setup_temp_cache,
|
||||
StacktaskAPITestCase)
|
||||
from stacktask.api.v1 import tests
|
||||
|
||||
from django.core import mail
|
||||
from django.test.utils import override_settings
|
||||
|
||||
|
||||
@mock.patch('stacktask.actions.user_store.IdentityManager',
|
||||
|
@ -95,11 +99,18 @@ class TaskViewTests(StacktaskAPITestCase):
|
|||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data, {'notes': ['created token']})
|
||||
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(mail.outbox[0].subject, 'invite_user')
|
||||
|
||||
new_token = Token.objects.all()[0]
|
||||
url = "/v1/tokens/" + new_token.token
|
||||
data = {'password': 'testpassword'}
|
||||
response = self.client.post(url, data, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(mail.outbox), 2)
|
||||
self.assertEquals(
|
||||
tests.temp_cache['users']["user_id_1"].name,
|
||||
'test@example.com')
|
||||
|
||||
def test_new_user_no_project(self):
|
||||
"""
|
||||
|
@ -642,3 +653,125 @@ class TaskViewTests(StacktaskAPITestCase):
|
|||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
self.assertFalse(response.data.get('task'))
|
||||
|
||||
# Positive tests for when USERNAME_IS_EMAIL=False
|
||||
@override_settings(USERNAME_IS_EMAIL=False)
|
||||
def test_invite_user_email_not_username(self):
|
||||
"""
|
||||
Invites a user where the email is different to the username.
|
||||
"""
|
||||
project = mock.Mock()
|
||||
project.id = 'test_project_id'
|
||||
project.name = 'test_project'
|
||||
project.domain = 'default'
|
||||
project.roles = {}
|
||||
|
||||
setup_temp_cache({'test_project': project}, {})
|
||||
|
||||
url = "/v1/actions/InviteUser"
|
||||
headers = {
|
||||
'project_name': "test_project",
|
||||
'project_id': "test_project_id",
|
||||
'roles': "project_admin,_member_,project_mod",
|
||||
'username': "user",
|
||||
'user_id': "test_user_id",
|
||||
'authenticated': True
|
||||
}
|
||||
data = {'username': 'new_user', 'email': "new@example.com",
|
||||
'roles': ["_member_"], 'project_id': 'test_project_id'}
|
||||
response = self.client.post(url, data, format='json', headers=headers)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data, {'notes': ['created token']})
|
||||
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEquals(mail.outbox[0].subject, 'invite_user')
|
||||
self.assertEquals(mail.outbox[0].to[0], 'new@example.com')
|
||||
|
||||
new_token = Token.objects.all()[0]
|
||||
url = "/v1/tokens/" + new_token.token
|
||||
data = {'password': 'testpassword'}
|
||||
response = self.client.post(url, data, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(len(mail.outbox), 2)
|
||||
|
||||
self.assertEquals(
|
||||
tests.temp_cache['users']["user_id_1"].name,
|
||||
'new_user')
|
||||
|
||||
@override_settings(USERNAME_IS_EMAIL=False)
|
||||
def test_reset_user_username_not_email(self):
|
||||
"""
|
||||
Ensure the reset user workflow goes as expected.
|
||||
Create task + create token, submit token.
|
||||
"""
|
||||
|
||||
user = mock.Mock()
|
||||
user.id = 'user_id'
|
||||
user.name = "test_user"
|
||||
user.email = "test@example.com"
|
||||
user.domain = 'default'
|
||||
user.password = "test_password"
|
||||
|
||||
setup_temp_cache({}, {user.id: user})
|
||||
|
||||
url = "/v1/actions/ResetPassword"
|
||||
# NOTE(amelia): Requiring both username and email here may be
|
||||
# a slight issue for various UIs as typically a
|
||||
# forgotten password screen only asks for the
|
||||
# email address, however there isn't a very
|
||||
# good way to address this as keystone doesn't
|
||||
# store emails in their own field
|
||||
# Currently this is an issue for the forked stacktask
|
||||
# horizon
|
||||
data = {'email': "test@example.com", 'username': 'test_user'}
|
||||
response = self.client.post(url, data, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(
|
||||
response.data['notes'],
|
||||
['If user with email exists, reset token will be issued.'])
|
||||
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
self.assertEqual(mail.outbox[0].subject,
|
||||
'Password Reset for OpenStack')
|
||||
self.assertEqual(mail.outbox[0].to[0], 'test@example.com')
|
||||
|
||||
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')
|
||||
|
||||
@override_settings(USERNAME_IS_EMAIL=False)
|
||||
def test_new_project_username_not_email(self):
|
||||
setup_temp_cache({}, {})
|
||||
|
||||
url = "/v1/actions/CreateProject"
|
||||
data = {'project_name': "test_project", 'email': "test@example.com",
|
||||
'username': 'test'}
|
||||
response = self.client.post(url, data, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
headers = {
|
||||
'project_name': "test_project",
|
||||
'project_id': "test_project_id",
|
||||
'roles': "admin,_member_",
|
||||
'username': "test@example.com",
|
||||
'user_id': "test_user_id",
|
||||
'authenticated': True
|
||||
}
|
||||
new_task = Task.objects.all()[0]
|
||||
url = "/v1/tasks/" + new_task.uuid
|
||||
response = self.client.post(url, {'approved': True}, format='json',
|
||||
headers=headers)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(
|
||||
response.data,
|
||||
{'notes': ['created token']}
|
||||
)
|
||||
|
||||
new_token = Token.objects.all()[0]
|
||||
url = "/v1/tokens/" + new_token.token
|
||||
data = {'password': 'testpassword'}
|
||||
response = self.client.post(url, data, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
|
|
@ -193,6 +193,7 @@ TASK_SETTINGS = {
|
|||
'reset_password': {
|
||||
'duplicate_policy': 'cancel',
|
||||
'emails': {
|
||||
'initial': None,
|
||||
'token': {
|
||||
'template': 'password_reset_token.txt',
|
||||
'subject': 'Password Reset for OpenStack'
|
||||
|
|
Loading…
Reference in New Issue