Merge pull request #15025 from open-craft/haikuginger/enterprise-branded-logistration
[ENT-336][ENT-337][ENT-338] Enterprise registration/login form updates
This commit is contained in:
@@ -367,20 +367,38 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
@ddt.data("signin_user", "register_user")
|
||||
def test_third_party_auth_disabled(self, url_name):
|
||||
response = self.client.get(reverse(url_name))
|
||||
self._assert_third_party_auth_data(response, None, None, [])
|
||||
self._assert_third_party_auth_data(response, None, None, [], None)
|
||||
|
||||
@mock.patch('student_account.views.enterprise_customer_for_request')
|
||||
@ddt.data(
|
||||
("signin_user", None, None),
|
||||
("register_user", None, None),
|
||||
("signin_user", "google-oauth2", "Google"),
|
||||
("register_user", "google-oauth2", "Google"),
|
||||
("signin_user", "facebook", "Facebook"),
|
||||
("register_user", "facebook", "Facebook"),
|
||||
("signin_user", "dummy", "Dummy"),
|
||||
("register_user", "dummy", "Dummy"),
|
||||
("signin_user", None, None, None),
|
||||
("register_user", None, None, None),
|
||||
("signin_user", "google-oauth2", "Google", None),
|
||||
("register_user", "google-oauth2", "Google", None),
|
||||
("signin_user", "facebook", "Facebook", None),
|
||||
("register_user", "facebook", "Facebook", None),
|
||||
("signin_user", "dummy", "Dummy", None),
|
||||
("register_user", "dummy", "Dummy", None),
|
||||
(
|
||||
"signin_user",
|
||||
"google-oauth2",
|
||||
"Google",
|
||||
{
|
||||
'name': 'FakeName',
|
||||
'logo': 'https://host.com/logo.jpg',
|
||||
'welcome_msg': 'No message'
|
||||
}
|
||||
)
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_third_party_auth(self, url_name, current_backend, current_provider):
|
||||
def test_third_party_auth(
|
||||
self,
|
||||
url_name,
|
||||
current_backend,
|
||||
current_provider,
|
||||
expected_enterprise_customer_mock_attrs,
|
||||
enterprise_customer_mock
|
||||
):
|
||||
params = [
|
||||
('course_id', 'course-v1:Org+Course+Run'),
|
||||
('enrollment_action', 'enroll'),
|
||||
@@ -389,6 +407,21 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
('next', '/custom/final/destination'),
|
||||
]
|
||||
|
||||
if expected_enterprise_customer_mock_attrs:
|
||||
expected_ec = mock.MagicMock(
|
||||
branding_configuration=mock.MagicMock(
|
||||
logo=mock.MagicMock(
|
||||
url=expected_enterprise_customer_mock_attrs['logo']
|
||||
),
|
||||
welcome_message=expected_enterprise_customer_mock_attrs['welcome_msg']
|
||||
)
|
||||
)
|
||||
expected_ec.name = expected_enterprise_customer_mock_attrs['name']
|
||||
else:
|
||||
expected_ec = None
|
||||
|
||||
enterprise_customer_mock.return_value = expected_ec
|
||||
|
||||
# Simulate a running pipeline
|
||||
if current_backend is not None:
|
||||
pipeline_target = "student_account.views.third_party_auth.pipeline"
|
||||
@@ -426,7 +459,13 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
"registerUrl": self._third_party_login_url("google-oauth2", "register", params)
|
||||
},
|
||||
]
|
||||
self._assert_third_party_auth_data(response, current_backend, current_provider, expected_providers)
|
||||
self._assert_third_party_auth_data(
|
||||
response,
|
||||
current_backend,
|
||||
current_provider,
|
||||
expected_providers,
|
||||
expected_ec
|
||||
)
|
||||
|
||||
def test_hinted_login(self):
|
||||
params = [("next", "/courses/something/?tpa_hint=oa2-google-oauth2")]
|
||||
@@ -455,6 +494,59 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
target_status_code=302
|
||||
)
|
||||
|
||||
@mock.patch('student_account.views.enterprise_customer_for_request')
|
||||
@ddt.data(
|
||||
('signin_user', False, None, None, None),
|
||||
('register_user', False, None, None, None),
|
||||
('signin_user', True, 'Fake EC', 'http://logo.com/logo.jpg', u'{enterprise_name} - {platform_name}'),
|
||||
('register_user', True, 'Fake EC', 'http://logo.com/logo.jpg', u'{enterprise_name} - {platform_name}'),
|
||||
('signin_user', True, 'Fake EC', None, u'{enterprise_name} - {platform_name}'),
|
||||
('register_user', True, 'Fake EC', None, u'{enterprise_name} - {platform_name}'),
|
||||
('signin_user', True, 'Fake EC', 'http://logo.com/logo.jpg', None),
|
||||
('register_user', True, 'Fake EC', 'http://logo.com/logo.jpg', None),
|
||||
('signin_user', True, 'Fake EC', None, None),
|
||||
('register_user', True, 'Fake EC', None, None),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_enterprise_register(self, url_name, ec_present, ec_name, logo_url, welcome_message, mock_get_ec):
|
||||
"""
|
||||
Verify that when an EnterpriseCustomer is received on the login and register views,
|
||||
the appropriate sidebar is rendered.
|
||||
"""
|
||||
if ec_present:
|
||||
mock_ec = mock_get_ec.return_value
|
||||
mock_ec.name = ec_name
|
||||
if logo_url:
|
||||
mock_ec.branding_configuration.logo.url = logo_url
|
||||
else:
|
||||
mock_ec.branding_configuration.logo = None
|
||||
if welcome_message:
|
||||
mock_ec.branding_configuration.welcome_message = welcome_message
|
||||
else:
|
||||
del mock_ec.branding_configuration.welcome_message
|
||||
else:
|
||||
mock_get_ec.return_value = None
|
||||
|
||||
response = self.client.get(reverse(url_name), HTTP_ACCEPT="text/html")
|
||||
|
||||
enterprise_sidebar_div_id = u'enterprise-content-container'
|
||||
|
||||
if not ec_present:
|
||||
self.assertNotContains(response, text=enterprise_sidebar_div_id)
|
||||
else:
|
||||
self.assertContains(response, text=enterprise_sidebar_div_id)
|
||||
if not welcome_message:
|
||||
welcome_message = settings.ENTERPRISE_SPECIFIC_BRANDED_WELCOME_TEMPLATE
|
||||
expected_message = welcome_message.format(
|
||||
start_bold=u'<b>',
|
||||
end_bold=u'</b>',
|
||||
enterprise_name=ec_name,
|
||||
platform_name=settings.PLATFORM_NAME
|
||||
)
|
||||
self.assertContains(response, expected_message)
|
||||
if logo_url:
|
||||
self.assertContains(response, logo_url)
|
||||
|
||||
@override_settings(SITE_NAME=settings.MICROSITE_TEST_HOSTNAME)
|
||||
def test_microsite_uses_old_login_page(self):
|
||||
# Retrieve the login page from a microsite domain
|
||||
@@ -494,7 +586,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
|
||||
self.assertEqual(resp['X-Frame-Options'], 'ALLOW')
|
||||
|
||||
def _assert_third_party_auth_data(self, response, current_backend, current_provider, providers):
|
||||
def _assert_third_party_auth_data(self, response, current_backend, current_provider, providers, expected_ec):
|
||||
"""Verify that third party auth info is rendered correctly in a DOM data attribute. """
|
||||
finish_auth_url = None
|
||||
if current_backend:
|
||||
@@ -507,6 +599,9 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
|
||||
"finishAuthUrl": finish_auth_url,
|
||||
"errorMessage": None,
|
||||
}
|
||||
if expected_ec is not None:
|
||||
# If we set an EnterpriseCustomer, third-party auth providers ought to be hidden.
|
||||
auth_info['providers'] = []
|
||||
auth_info = dump_js_escaped_json(auth_info)
|
||||
|
||||
expected_data = '"third_party_auth": {auth_info}'.format(
|
||||
|
||||
@@ -18,7 +18,7 @@ from django.utils.translation import ugettext as _
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django_countries import countries
|
||||
from edxmako.shortcuts import render_to_response
|
||||
from edxmako.shortcuts import render_to_response, render_to_string
|
||||
import pytz
|
||||
|
||||
from commerce.models import CommerceConfiguration
|
||||
@@ -34,7 +34,10 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_
|
||||
from openedx.core.djangoapps.theming.helpers import is_request_in_themed_site
|
||||
from openedx.core.djangoapps.user_api.accounts.api import request_password_change
|
||||
from openedx.core.djangoapps.user_api.errors import UserNotFound
|
||||
from openedx.features.enterprise_support.api import set_enterprise_branding_filter_param
|
||||
from openedx.features.enterprise_support.api import (
|
||||
enterprise_customer_for_request,
|
||||
set_enterprise_branding_filter_param
|
||||
)
|
||||
from openedx.core.lib.time_zone_utils import TIME_ZONE_CHOICES
|
||||
from openedx.core.lib.edx_api_utils import get_edx_api_data
|
||||
from student.models import UserProfile
|
||||
@@ -144,6 +147,8 @@ def login_and_registration_form(request, initial_mode="login"):
|
||||
),
|
||||
}
|
||||
|
||||
context = update_context_for_enterprise(request, context)
|
||||
|
||||
return render_to_response('student_account/login_and_register.html', context)
|
||||
|
||||
|
||||
@@ -197,6 +202,89 @@ def password_change_request_handler(request):
|
||||
return HttpResponseBadRequest(_("No email address provided."))
|
||||
|
||||
|
||||
def update_context_for_enterprise(request, context):
|
||||
"""
|
||||
Take the processed context produced by the view, determine if it's relevant
|
||||
to a particular Enterprise Customer, and update it to include that customer's
|
||||
enterprise metadata.
|
||||
"""
|
||||
|
||||
context = context.copy()
|
||||
|
||||
sidebar_context = enterprise_sidebar_context(request)
|
||||
|
||||
if sidebar_context:
|
||||
context['data']['registration_form_desc']['fields'] = enterprise_fields_only(
|
||||
context['data']['registration_form_desc']
|
||||
)
|
||||
context.update(sidebar_context)
|
||||
context['enable_enterprise_sidebar'] = True
|
||||
else:
|
||||
context['enable_enterprise_sidebar'] = False
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def enterprise_fields_only(fields):
|
||||
"""
|
||||
Take the received field definition, and exclude those fields that we don't want
|
||||
to require if the user is going to be a member of an Enterprise Customer.
|
||||
"""
|
||||
enterprise_exclusions = configuration_helpers.get_value(
|
||||
'ENTERPRISE_EXCLUDED_REGISTRATION_FIELDS',
|
||||
settings.ENTERPRISE_EXCLUDED_REGISTRATION_FIELDS
|
||||
)
|
||||
return [field for field in fields['fields'] if field['name'] not in enterprise_exclusions]
|
||||
|
||||
|
||||
def enterprise_sidebar_context(request):
|
||||
"""
|
||||
Given the current request, render the HTML of a sidebar for the current
|
||||
logistration view that depicts Enterprise-related information.
|
||||
"""
|
||||
enterprise_customer = enterprise_customer_for_request(request)
|
||||
|
||||
if not enterprise_customer:
|
||||
return {}
|
||||
|
||||
platform_name = configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME)
|
||||
|
||||
if enterprise_customer.branding_configuration.logo:
|
||||
enterprise_logo_url = enterprise_customer.branding_configuration.logo.url
|
||||
else:
|
||||
enterprise_logo_url = ''
|
||||
|
||||
if getattr(enterprise_customer.branding_configuration, 'welcome_message', None):
|
||||
branded_welcome_template = enterprise_customer.branding_configuration.welcome_message
|
||||
else:
|
||||
branded_welcome_template = configuration_helpers.get_value(
|
||||
'ENTERPRISE_SPECIFIC_BRANDED_WELCOME_TEMPLATE',
|
||||
settings.ENTERPRISE_SPECIFIC_BRANDED_WELCOME_TEMPLATE
|
||||
)
|
||||
|
||||
branded_welcome_string = branded_welcome_template.format(
|
||||
start_bold=u'<b>',
|
||||
end_bold=u'</b>',
|
||||
enterprise_name=enterprise_customer.name,
|
||||
platform_name=platform_name
|
||||
)
|
||||
|
||||
platform_welcome_template = configuration_helpers.get_value(
|
||||
'ENTERPRISE_PLATFORM_WELCOME_TEMPLATE',
|
||||
settings.ENTERPRISE_PLATFORM_WELCOME_TEMPLATE
|
||||
)
|
||||
platform_welcome_string = platform_welcome_template.format(platform_name=platform_name)
|
||||
|
||||
context = {
|
||||
'enterprise_name': enterprise_customer.name,
|
||||
'enterprise_logo_url': enterprise_logo_url,
|
||||
'enterprise_branded_welcome_string': branded_welcome_string,
|
||||
'platform_welcome_string': platform_welcome_string,
|
||||
}
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def _third_party_auth_context(request, redirect_to, tpa_hint=None):
|
||||
"""Context for third party auth providers and the currently running pipeline.
|
||||
|
||||
@@ -221,24 +309,25 @@ def _third_party_auth_context(request, redirect_to, tpa_hint=None):
|
||||
}
|
||||
|
||||
if third_party_auth.is_enabled():
|
||||
for enabled in third_party_auth.provider.Registry.displayed_for_login(tpa_hint=tpa_hint):
|
||||
info = {
|
||||
"id": enabled.provider_id,
|
||||
"name": enabled.name,
|
||||
"iconClass": enabled.icon_class or None,
|
||||
"iconImage": enabled.icon_image.url if enabled.icon_image else None,
|
||||
"loginUrl": pipeline.get_login_url(
|
||||
enabled.provider_id,
|
||||
pipeline.AUTH_ENTRY_LOGIN,
|
||||
redirect_url=redirect_to,
|
||||
),
|
||||
"registerUrl": pipeline.get_login_url(
|
||||
enabled.provider_id,
|
||||
pipeline.AUTH_ENTRY_REGISTER,
|
||||
redirect_url=redirect_to,
|
||||
),
|
||||
}
|
||||
context["providers" if not enabled.secondary else "secondaryProviders"].append(info)
|
||||
if not enterprise_customer_for_request(request):
|
||||
for enabled in third_party_auth.provider.Registry.displayed_for_login(tpa_hint=tpa_hint):
|
||||
info = {
|
||||
"id": enabled.provider_id,
|
||||
"name": enabled.name,
|
||||
"iconClass": enabled.icon_class or None,
|
||||
"iconImage": enabled.icon_image.url if enabled.icon_image else None,
|
||||
"loginUrl": pipeline.get_login_url(
|
||||
enabled.provider_id,
|
||||
pipeline.AUTH_ENTRY_LOGIN,
|
||||
redirect_url=redirect_to,
|
||||
),
|
||||
"registerUrl": pipeline.get_login_url(
|
||||
enabled.provider_id,
|
||||
pipeline.AUTH_ENTRY_REGISTER,
|
||||
redirect_url=redirect_to,
|
||||
),
|
||||
}
|
||||
context["providers" if not enabled.secondary else "secondaryProviders"].append(info)
|
||||
|
||||
running_pipeline = pipeline.get(request)
|
||||
if running_pipeline is not None:
|
||||
|
||||
@@ -951,6 +951,25 @@ ENTERPRISE_API_CACHE_TIMEOUT = ENV_TOKENS.get(
|
||||
ENTERPRISE_API_CACHE_TIMEOUT
|
||||
)
|
||||
|
||||
############## ENTERPRISE SERVICE LMS CONFIGURATION ##################################
|
||||
# The LMS has some features embedded that are related to the Enterprise service, but
|
||||
# which are not provided by the Enterprise service. These settings override the
|
||||
# base values for the parameters as defined in common.py
|
||||
|
||||
ENTERPRISE_PLATFORM_WELCOME_TEMPLATE = ENV_TOKENS.get(
|
||||
'ENTERPRISE_PLATFORM_WELCOME_TEMPLATE',
|
||||
ENTERPRISE_PLATFORM_WELCOME_TEMPLATE
|
||||
)
|
||||
ENTERPRISE_SPECIFIC_BRANDED_WELCOME_TEMPLATE = ENV_TOKENS.get(
|
||||
'ENTERPRISE_SPECIFIC_BRANDED_WELCOME_TEMPLATE',
|
||||
ENTERPRISE_SPECIFIC_BRANDED_WELCOME_TEMPLATE
|
||||
)
|
||||
ENTERPRISE_EXCLUDED_REGISTRATION_FIELDS = set(
|
||||
ENV_TOKENS.get(
|
||||
'ENTERPRISE_EXCLUDED_REGISTRATION_FIELDS',
|
||||
ENTERPRISE_EXCLUDED_REGISTRATION_FIELDS
|
||||
)
|
||||
)
|
||||
|
||||
############## CATALOG/DISCOVERY SERVICE API CLIENT CONFIGURATION ######################
|
||||
# The LMS communicates with the Catalog service via the EdxRestApiClient class
|
||||
|
||||
@@ -3142,6 +3142,26 @@ ENTERPRISE_SERVICE_WORKER_USERNAME = 'enterprise_worker'
|
||||
ENTERPRISE_API_CACHE_TIMEOUT = 3600 # Value is in seconds
|
||||
ENTERPRISE_CUSTOMER_LOGO_IMAGE_SIZE = 512 # Enterprise logo image size limit in KB's
|
||||
|
||||
############## ENTERPRISE SERVICE LMS CONFIGURATION ##################################
|
||||
# The LMS has some features embedded that are related to the Enterprise service, but
|
||||
# which are not provided by the Enterprise service. These settings provide base values
|
||||
# for those features.
|
||||
|
||||
ENTERPRISE_PLATFORM_WELCOME_TEMPLATE = _(u'Welcome to {platform_name}.')
|
||||
ENTERPRISE_SPECIFIC_BRANDED_WELCOME_TEMPLATE = _(
|
||||
u'{start_bold}{enterprise_name}{end_bold} has partnered with {start_bold}'
|
||||
'{platform_name}{end_bold} to offer you high-quality learning opportunities '
|
||||
'from the world\'s best universities.'
|
||||
)
|
||||
ENTERPRISE_EXCLUDED_REGISTRATION_FIELDS = {
|
||||
'age',
|
||||
'level_of_education',
|
||||
'gender',
|
||||
'goals',
|
||||
'year_of_birth',
|
||||
'mailing_address',
|
||||
}
|
||||
|
||||
############## Settings for Course Enrollment Modes ######################
|
||||
COURSE_ENROLLMENT_MODES = {
|
||||
"audit": 1,
|
||||
|
||||
@@ -3,16 +3,50 @@
|
||||
@import '../base/grid-settings';
|
||||
@import "neat/neat"; // lib - Neat
|
||||
|
||||
.login-register {
|
||||
@media (min-width: 768px) {
|
||||
.enterprise-content {
|
||||
width: 20%;
|
||||
float: left;
|
||||
height: 100%;
|
||||
padding-left: $baseline;
|
||||
padding-right: $baseline;
|
||||
}
|
||||
|
||||
.login-register.border-left {
|
||||
border-left: 1px solid #d9d9d9;
|
||||
padding-left: ($baseline*1.5);
|
||||
padding-right: $baseline;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.enterprise-content {
|
||||
margin: auto auto;
|
||||
display: block;
|
||||
padding-left: ($baseline/2);
|
||||
padding-right: ($baseline/2);
|
||||
|
||||
img.enterprise-logo {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.window-wrap {
|
||||
background: $white;
|
||||
}
|
||||
|
||||
.login-register-content {
|
||||
@include box-sizing(border-box);
|
||||
@include outer-container;
|
||||
$grid-columns: 12;
|
||||
background: $white;
|
||||
min-height: 100%;
|
||||
width: 100%;
|
||||
padding-left: ($baseline/2);
|
||||
padding-right: ($baseline/2);
|
||||
$third-party-button-height: ($baseline*1.75);
|
||||
justify-content: center;
|
||||
margin-top: $baseline;
|
||||
background: $white;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
-webkit-flex-wrap: wrap;
|
||||
-moz-flex-wrap: wrap;
|
||||
|
||||
h2 {
|
||||
@extend %t-title4;
|
||||
@@ -35,6 +69,21 @@
|
||||
@extend %expand-clickable-area;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.login-register {
|
||||
$grid-columns: 12;
|
||||
background: $white;
|
||||
min-height: 100%;
|
||||
padding-left: ($baseline/2);
|
||||
padding-right: ($baseline/2);
|
||||
$third-party-button-height: ($baseline*1.75);
|
||||
display: inline-block;
|
||||
max-width: 500px;
|
||||
|
||||
.instructions {
|
||||
@extend %t-copy-base;
|
||||
}
|
||||
@@ -587,3 +636,26 @@
|
||||
.supplemental-link {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.enterprise-content {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
max-width: 500px;
|
||||
|
||||
.centered-div {
|
||||
margin: 0 auto;
|
||||
margin-right: 0px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: $gray-d2;
|
||||
}
|
||||
}
|
||||
|
||||
13
lms/templates/student_account/enterprise_sidebar.html
Normal file
13
lms/templates/student_account/enterprise_sidebar.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<div id="enterprise-content-container" class="enterprise-content">
|
||||
<div class="centered-div">
|
||||
% if enterprise_logo_url:
|
||||
<img src="${enterprise_logo_url}" alt="${enterprise_name}" class="enterprise-logo">
|
||||
% endif
|
||||
<h2>
|
||||
${enterprise_branded_welcome_string}
|
||||
</h2>
|
||||
<h2>
|
||||
${platform_welcome_string}
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
@@ -29,11 +29,22 @@
|
||||
<script type="text/template" id="${template_name}-tpl">
|
||||
<%static:include path="student_account/${template_name}.underscore" />
|
||||
</script>
|
||||
% endfor
|
||||
% endfor
|
||||
</%block>
|
||||
|
||||
<div class="section-bkg-wrapper">
|
||||
<main id="main" aria-label="Content" tabindex="-1">
|
||||
<div id="login-and-registration-container" class="login-register" />
|
||||
<div id="content-container" class="login-register-content">
|
||||
% if enable_enterprise_sidebar:
|
||||
<%include file="enterprise_sidebar.html" />
|
||||
<%
|
||||
border_class = 'border-left'
|
||||
%>
|
||||
% else:
|
||||
<%
|
||||
border_class = ''
|
||||
%>
|
||||
% endif
|
||||
<div id="login-and-registration-container" class="login-register ${border_class}"></div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,8 @@ from slumber.exceptions import HttpClientError, HttpServerError
|
||||
from edx_rest_api_client.client import EdxRestApiClient
|
||||
try:
|
||||
from enterprise import utils as enterprise_utils
|
||||
from enterprise.models import EnterpriseCourseEnrollment
|
||||
from enterprise.models import EnterpriseCourseEnrollment, EnterpriseCustomer
|
||||
from enterprise.tpa_pipeline import get_enterprise_customer_for_request
|
||||
from enterprise.utils import consent_necessary_for_course
|
||||
except ImportError:
|
||||
pass
|
||||
@@ -233,6 +234,32 @@ def enterprise_enabled():
|
||||
return 'enterprise' in settings.INSTALLED_APPS and getattr(settings, 'ENABLE_ENTERPRISE_INTEGRATION', True)
|
||||
|
||||
|
||||
def enterprise_customer_for_request(request, tpa_hint=None):
|
||||
"""
|
||||
Check all the context clues of the request to determine if
|
||||
the request being made is tied to a particular EnterpriseCustomer.
|
||||
"""
|
||||
if not enterprise_enabled():
|
||||
return None
|
||||
|
||||
ec = get_enterprise_customer_for_request(request)
|
||||
|
||||
if not ec and tpa_hint:
|
||||
try:
|
||||
ec = EnterpriseCustomer.objects.get(enterprise_customer_identity_provider__provider_id=tpa_hint)
|
||||
except EnterpriseCustomer.DoesNotExist:
|
||||
pass
|
||||
|
||||
ec_uuid = request.GET.get('enterprise_customer')
|
||||
if not ec and ec_uuid:
|
||||
try:
|
||||
ec = EnterpriseCustomer.objects.get(uuid=ec_uuid)
|
||||
except (EnterpriseCustomer.DoesNotExist, ValueError):
|
||||
ec = None
|
||||
|
||||
return ec
|
||||
|
||||
|
||||
def consent_needed_for_course(user, course_id):
|
||||
"""
|
||||
Wrap the enterprise app check to determine if the user needs to grant
|
||||
|
||||
@@ -10,6 +10,7 @@ from django.test.utils import override_settings
|
||||
|
||||
from openedx.features.enterprise_support.api import (
|
||||
enterprise_enabled,
|
||||
enterprise_customer_for_request,
|
||||
insert_enterprise_pipeline_elements,
|
||||
data_sharing_consent_required,
|
||||
set_enterprise_branding_filter_param,
|
||||
@@ -117,6 +118,48 @@ class TestEnterpriseApi(unittest.TestCase):
|
||||
logo_url = get_enterprise_customer_logo_url(request)
|
||||
self.assertEqual(logo_url, None)
|
||||
|
||||
@override_settings(ENABLE_ENTERPRISE_INTEGRATION=True)
|
||||
@mock.patch('openedx.features.enterprise_support.api.get_enterprise_customer_for_request')
|
||||
@mock.patch('openedx.features.enterprise_support.api.EnterpriseCustomer')
|
||||
def test_enterprise_customer_for_request(self, ec_class_mock, get_ec_pipeline_mock):
|
||||
"""
|
||||
Test that the correct EnterpriseCustomer, if any, is returned.
|
||||
"""
|
||||
def get_ec_mock(**kwargs):
|
||||
by_provider_id_kw = 'enterprise_customer_identity_provider__provider_id'
|
||||
provider_id = kwargs.get(by_provider_id_kw, '')
|
||||
uuid = kwargs.get('uuid', '')
|
||||
if uuid == 'real-uuid' or provider_id == 'real-provider-id':
|
||||
return 'this-is-actually-an-enterprise-customer'
|
||||
elif uuid == 'not-a-uuid':
|
||||
raise ValueError
|
||||
else:
|
||||
raise Exception
|
||||
|
||||
ec_class_mock.DoesNotExist = Exception
|
||||
ec_class_mock.objects.get.side_effect = get_ec_mock
|
||||
|
||||
get_ec_pipeline_mock.return_value = None
|
||||
|
||||
request = mock.MagicMock()
|
||||
request.GET.get.return_value = 'real-uuid'
|
||||
self.assertEqual(enterprise_customer_for_request(request), 'this-is-actually-an-enterprise-customer')
|
||||
request.GET.get.return_value = 'not-a-uuid'
|
||||
self.assertEqual(enterprise_customer_for_request(request), None)
|
||||
request.GET.get.return_value = 'fake-uuid'
|
||||
self.assertEqual(enterprise_customer_for_request(request), None)
|
||||
request.GET.get.return_value = None
|
||||
self.assertEqual(
|
||||
enterprise_customer_for_request(request, tpa_hint='real-provider-id'),
|
||||
'this-is-actually-an-enterprise-customer'
|
||||
)
|
||||
self.assertEqual(enterprise_customer_for_request(request, tpa_hint='fake-provider-id'), None)
|
||||
self.assertEqual(enterprise_customer_for_request(request, tpa_hint=None), None)
|
||||
|
||||
get_ec_pipeline_mock.return_value = 'also-a-real-enterprise'
|
||||
|
||||
self.assertEqual(enterprise_customer_for_request(request), 'also-a-real-enterprise')
|
||||
|
||||
def check_data_sharing_consent(self, consent_required=False, consent_url=None):
|
||||
"""
|
||||
Used to test the data_sharing_consent_required view decorator.
|
||||
|
||||
Reference in New Issue
Block a user