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:
Amelia Cordwell 2017-01-06 17:15:39 +13:00 committed by Adrian Turjak
parent cf100fc804
commit ed6bb16cd1
6 changed files with 340 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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