-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: basics of business logic for customer provisioning
ENT-10071
- Loading branch information
1 parent
a951ee9
commit 897686b
Showing
8 changed files
with
524 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
Tests for the provisioning views. | ||
""" | ||
import uuid | ||
from unittest import mock | ||
|
||
import ddt | ||
from edx_rbac.constants import ALL_ACCESS_CONTEXT | ||
|
@@ -43,11 +44,6 @@ class TestProvisioningAuth(APITest): | |
{'system_wide_role': SYSTEM_ENTERPRISE_ADMIN_ROLE, 'context': ALL_ACCESS_CONTEXT}, | ||
status.HTTP_403_FORBIDDEN, | ||
), | ||
# Even operators can't provision | ||
( | ||
{'system_wide_role': SYSTEM_ENTERPRISE_OPERATOR_ROLE, 'context': ALL_ACCESS_CONTEXT}, | ||
status.HTTP_403_FORBIDDEN, | ||
), | ||
# No JWT based auth, no soup for you. | ||
( | ||
None, | ||
|
@@ -66,15 +62,26 @@ def test_provisioning_create_view_forbidden(self, role_context_dict, expected_re | |
response = self.client.post(PROVISIONING_CREATE_ENDPOINT) | ||
assert response.status_code == expected_response_code | ||
|
||
def test_provisioning_create_allowed_for_provisioning_admins(self): | ||
@ddt.data( | ||
( | ||
{'system_wide_role': SYSTEM_ENTERPRISE_OPERATOR_ROLE, 'context': ALL_ACCESS_CONTEXT}, | ||
status.HTTP_201_CREATED, | ||
), | ||
( | ||
{'system_wide_role': SYSTEM_ENTERPRISE_PROVISIONING_ADMIN_ROLE, 'context': ALL_ACCESS_CONTEXT}, | ||
status.HTTP_201_CREATED, | ||
), | ||
) | ||
@ddt.unpack | ||
@mock.patch('enterprise_access.apps.api.v1.views.provisioning.provisioning_api') | ||
def test_provisioning_create_allowed_for_provisioning_admins( | ||
self, role_context_dict, expected_response_code, mock_provisioning_api, | ||
): | ||
""" | ||
Tests that we get expected 200 response for the provisioning create view when | ||
the requesting user has the correct system role and provides a valid request payload. | ||
""" | ||
self.set_jwt_cookie([{ | ||
'system_wide_role': SYSTEM_ENTERPRISE_PROVISIONING_ADMIN_ROLE, | ||
'context': ALL_ACCESS_CONTEXT, | ||
}]) | ||
self.set_jwt_cookie([role_context_dict]) | ||
|
||
request_payload = { | ||
"enterprise_customer": { | ||
|
@@ -89,4 +96,259 @@ def test_provisioning_create_allowed_for_provisioning_admins(self): | |
], | ||
} | ||
response = self.client.post(PROVISIONING_CREATE_ENDPOINT, data=request_payload) | ||
assert response.status_code == expected_response_code | ||
|
||
mock_provisioning_api.get_or_create_enterprise_customer.assert_called_once_with( | ||
**request_payload['enterprise_customer'], | ||
) | ||
|
||
created_customer = mock_provisioning_api.get_or_create_enterprise_customer.return_value | ||
mock_provisioning_api.get_or_create_enterprise_admin_users.assert_called_once_with( | ||
enterprise_customer_uuid=created_customer['uuid'], | ||
user_emails=['[email protected]'], | ||
) | ||
|
||
|
||
@ddt.ddt | ||
class TestProvisioningEndToEnd(APITest): | ||
""" | ||
Tests end-to-end calls to provisioning endpoints through mocked-out calls | ||
to downstream services. | ||
""" | ||
def setUp(self): | ||
super().setUp() | ||
self.set_jwt_cookie([ | ||
{ | ||
'system_wide_role': SYSTEM_ENTERPRISE_PROVISIONING_ADMIN_ROLE, | ||
'context': ALL_ACCESS_CONTEXT, | ||
}, | ||
]) | ||
|
||
@ddt.data( | ||
# Data representing the state where a net-new customer is created. | ||
{ | ||
'existing_customer_data': None, | ||
'created_customer_data': { | ||
'name': 'Test Customer', | ||
'slug': 'test-customer', | ||
'country': 'US', | ||
'uuid': TEST_ENTERPRISE_UUID, | ||
}, | ||
'expected_get_customer_kwargs': { | ||
'enterprise_customer_slug': 'test-customer', | ||
}, | ||
'create_customer_called': True, | ||
'expected_create_customer_kwargs': { | ||
'name': 'Test Customer', | ||
'slug': 'test-customer', | ||
'country': 'US', | ||
}, | ||
}, | ||
# Data representing the state where a customer with the given slug exists. | ||
{ | ||
'existing_customer_data': { | ||
'name': 'Test Customer', | ||
'slug': 'test-customer', | ||
'country': 'US', | ||
'uuid': TEST_ENTERPRISE_UUID, | ||
}, | ||
'created_customer_data': None, | ||
'expected_get_customer_kwargs': { | ||
'enterprise_customer_slug': 'test-customer', | ||
}, | ||
'create_customer_called': False, | ||
'expected_create_customer_kwargs': None | ||
}, | ||
) | ||
@mock.patch('enterprise_access.apps.provisioning.api.LmsApiClient') | ||
def test_get_or_create_customer_and_admins_created(self, test_data, mock_lms_api_client): | ||
""" | ||
Tests cases where admins don't exist and customer is fetched or created. | ||
""" | ||
mock_client = mock_lms_api_client.return_value | ||
mock_client.get_enterprise_customer_data.return_value = test_data['existing_customer_data'] | ||
mock_client.get_enterprise_admin_users.return_value = [] | ||
mock_client.get_enterprise_pending_admin_users.return_value = [] | ||
|
||
if test_data['created_customer_data']: | ||
mock_client.create_enterprise_customer.return_value = test_data['created_customer_data'] | ||
|
||
mock_client.create_enterprise_admin_user.side_effect = [ | ||
{'user_email': '[email protected]', 'enterprise_customer_uuid': TEST_ENTERPRISE_UUID}, | ||
{'user_email': '[email protected]', 'enterprise_customer_uuid': TEST_ENTERPRISE_UUID}, | ||
] | ||
|
||
request_payload = { | ||
"enterprise_customer": { | ||
'name': 'Test Customer', | ||
'slug': 'test-customer', | ||
'country': 'US', | ||
}, | ||
'pending_admins': [ | ||
{'user_email': '[email protected]'}, | ||
{'user_email': '[email protected]'}, | ||
], | ||
} | ||
response = self.client.post(PROVISIONING_CREATE_ENDPOINT, data=request_payload) | ||
assert response.status_code == status.HTTP_201_CREATED | ||
|
||
expected_response_payload = { | ||
'enterprise_customer': { | ||
'name': 'Test Customer', | ||
'slug': 'test-customer', | ||
'country': 'US', | ||
'uuid': str(TEST_ENTERPRISE_UUID), | ||
}, | ||
'customer_admins': { | ||
'created_admins': [ | ||
{'user_email': '[email protected]'}, | ||
{'user_email': '[email protected]'}, | ||
], | ||
'existing_admins': [], | ||
}, | ||
} | ||
actual_response_payload = response.json() | ||
self.assertEqual(actual_response_payload, expected_response_payload) | ||
|
||
mock_client.get_enterprise_customer_data.assert_called_once_with( | ||
**test_data['expected_get_customer_kwargs'], | ||
) | ||
if test_data['create_customer_called']: | ||
mock_client.create_enterprise_customer.assert_called_once_with( | ||
**test_data['expected_create_customer_kwargs'], | ||
) | ||
else: | ||
self.assertFalse(mock_client.create_enterprise_customer.called) | ||
|
||
mock_client.get_enterprise_admin_users.assert_called_once_with(TEST_ENTERPRISE_UUID) | ||
mock_client.get_enterprise_pending_admin_users.assert_called_once_with(TEST_ENTERPRISE_UUID) | ||
mock_client.create_enterprise_admin_user.assert_has_calls([ | ||
mock.call(TEST_ENTERPRISE_UUID, '[email protected]'), | ||
mock.call(TEST_ENTERPRISE_UUID, '[email protected]'), | ||
], any_order=True) | ||
|
||
@ddt.data( | ||
# No admin users exist, two pending admins created. | ||
{ | ||
'existing_admin_users': [], | ||
'existing_pending_admin_users': [], | ||
'create_pending_admins_called': True, | ||
'create_admin_user_side_effect': [ | ||
{'user_email': '[email protected]', 'enterprise_customer_uuid': TEST_ENTERPRISE_UUID}, | ||
{'user_email': '[email protected]', 'enterprise_customer_uuid': TEST_ENTERPRISE_UUID}, | ||
], | ||
'expected_create_pending_admin_calls': [ | ||
mock.call(TEST_ENTERPRISE_UUID, '[email protected]'), | ||
mock.call(TEST_ENTERPRISE_UUID, '[email protected]'), | ||
], | ||
}, | ||
# One pending admin exists, one new one created. | ||
{ | ||
'existing_admin_users': [], | ||
'existing_pending_admin_users': [ | ||
{'user_email': '[email protected]', 'enterprise_customer_uuid': TEST_ENTERPRISE_UUID}, | ||
], | ||
'create_pending_admins_called': True, | ||
'create_admin_user_side_effect': [ | ||
{'user_email': '[email protected]', 'enterprise_customer_uuid': TEST_ENTERPRISE_UUID}, | ||
], | ||
'expected_create_pending_admin_calls': [ | ||
mock.call(TEST_ENTERPRISE_UUID, '[email protected]'), | ||
], | ||
}, | ||
# One full admin exists, one new pending admin created. | ||
{ | ||
'existing_admin_users': [ | ||
{'email': '[email protected]', 'enterprise_customer_uuid': TEST_ENTERPRISE_UUID}, | ||
], | ||
'existing_pending_admin_users': [], | ||
'create_pending_admins_called': True, | ||
'create_admin_user_side_effect': [ | ||
{'user_email': '[email protected]', 'enterprise_customer_uuid': TEST_ENTERPRISE_UUID}, | ||
], | ||
'expected_create_pending_admin_calls': [ | ||
mock.call(TEST_ENTERPRISE_UUID, '[email protected]'), | ||
], | ||
}, | ||
# One full admin exists, one pending exists, none created. | ||
{ | ||
'existing_admin_users': [ | ||
{'email': '[email protected]', 'enterprise_customer_uuid': TEST_ENTERPRISE_UUID}, | ||
], | ||
'existing_pending_admin_users': [ | ||
{'user_email': '[email protected]', 'enterprise_customer_uuid': TEST_ENTERPRISE_UUID}, | ||
], | ||
'create_pending_admins_called': False, | ||
'create_admin_user_side_effect': [], | ||
'expected_create_pending_admin_calls': [], | ||
}, | ||
) | ||
@mock.patch('enterprise_access.apps.provisioning.api.LmsApiClient') | ||
def test_customer_fetched_admins_fetched_or_created(self, test_data, mock_lms_api_client): | ||
""" | ||
Tests cases where [pending]admins are fetched or created, but the customer | ||
already exists | ||
""" | ||
mock_client = mock_lms_api_client.return_value | ||
mock_client.get_enterprise_customer_data.return_value = { | ||
'name': 'Test Customer', | ||
'slug': 'test-customer', | ||
'country': 'US', | ||
'uuid': TEST_ENTERPRISE_UUID, | ||
} | ||
mock_client.get_enterprise_admin_users.return_value = test_data['existing_admin_users'] | ||
mock_client.get_enterprise_pending_admin_users.return_value = test_data['existing_pending_admin_users'] | ||
mock_client.create_enterprise_admin_user.side_effect = test_data['create_admin_user_side_effect'] | ||
|
||
request_payload = { | ||
'enterprise_customer': { | ||
'name': 'Test Customer', | ||
'slug': 'test-customer', | ||
'country': 'US', | ||
}, | ||
'pending_admins': [ | ||
{'user_email': '[email protected]'}, | ||
{'user_email': '[email protected]'}, | ||
], | ||
} | ||
response = self.client.post(PROVISIONING_CREATE_ENDPOINT, data=request_payload) | ||
assert response.status_code == status.HTTP_201_CREATED | ||
|
||
existing_emails = sorted( | ||
[record['email'] for record in test_data['existing_admin_users']] + | ||
[record['user_email'] for record in test_data['existing_pending_admin_users']] | ||
) | ||
expected_existing_admins = [{'user_email': email} for email in existing_emails] | ||
expected_created_admins = [ | ||
{'user_email': record['user_email']} | ||
for record in test_data['create_admin_user_side_effect'] | ||
] | ||
expected_response_payload = { | ||
'enterprise_customer': { | ||
'name': 'Test Customer', | ||
'slug': 'test-customer', | ||
'country': 'US', | ||
'uuid': str(TEST_ENTERPRISE_UUID), | ||
}, | ||
'customer_admins': { | ||
'created_admins': expected_created_admins, | ||
'existing_admins': expected_existing_admins, | ||
}, | ||
} | ||
actual_response_payload = response.json() | ||
self.assertEqual(actual_response_payload, expected_response_payload) | ||
|
||
mock_client.get_enterprise_customer_data.assert_called_once_with( | ||
enterprise_customer_slug='test-customer', | ||
) | ||
self.assertFalse(mock_client.create_enterprise_customer.called) | ||
|
||
mock_client.get_enterprise_admin_users.assert_called_once_with(TEST_ENTERPRISE_UUID) | ||
mock_client.get_enterprise_pending_admin_users.assert_called_once_with(TEST_ENTERPRISE_UUID) | ||
if test_data['create_pending_admins_called']: | ||
mock_client.create_enterprise_admin_user.assert_has_calls( | ||
test_data['expected_create_pending_admin_calls'], | ||
any_order=True, | ||
) | ||
else: | ||
self.assertFalse(mock_client.create_enterprise_admin_user.called) |
Oops, something went wrong.