diff --git a/common/djangoapps/student/tests/test_microsite.py b/common/djangoapps/student/tests/test_microsite.py index b447ad3a13c10e2b8c2d08eb2ea18f2141b07bb1..d76aa9a72a85aea9bc4630ed69df9d66556c9521 100644 --- a/common/djangoapps/student/tests/test_microsite.py +++ b/common/djangoapps/student/tests/test_microsite.py @@ -4,8 +4,24 @@ Test for User Creation from Micro-Sites from django.test import TestCase from student.models import UserSignupSource import mock +import json from django.core.urlresolvers import reverse +from django.contrib.auth.models import User +FAKE_MICROSITE = { + "SITE_NAME": "openedx.localhost", + "REGISTRATION_EXTRA_FIELDS": { + "address1": "required", + "city": "required", + "state": "required", + "country": "required", + "company": "required", + "title": "required" + }, + "extended_profile_fields": [ + "address1", "state", "company", "title" + ] +} def fake_site_name(name, default=None): # pylint: disable=W0613 """ @@ -14,8 +30,13 @@ def fake_site_name(name, default=None): # pylint: disable=W0613 if name == 'SITE_NAME': return 'openedx.localhost' else: - return None + return default +def fake_microsite_get_value(name, default=None): # pylint: disable=W0613 + """ + create a fake microsite site name + """ + return FAKE_MICROSITE.get(name, default) class TestMicrosite(TestCase): """Test for Account Creation from a white labeled Micro-Sites""" @@ -30,6 +51,14 @@ class TestMicrosite(TestCase): "honor_code": "true", "terms_of_service": "true", } + self.extended_params = dict(self.params.items() + { + "address1": "foo", + "city": "foo", + "state": "foo", + "country": "foo", + "company": "foo", + "title": "foo" + }.items()) @mock.patch("microsite_configuration.microsite.get_value", fake_site_name) def test_user_signup_source(self): @@ -49,3 +78,27 @@ class TestMicrosite(TestCase): response = self.client.post(self.url, self.params) self.assertEqual(response.status_code, 200) self.assertEqual(len(UserSignupSource.objects.filter(site='openedx.localhost')), 0) + + @mock.patch("microsite_configuration.microsite.get_value", fake_microsite_get_value) + def test_user_signup_missing_enhanced_profile(self): + """ + test to create a user form the microsite but don't provide any of the microsite specific + profile information + """ + response = self.client.post(self.url, self.params) + self.assertEqual(response.status_code, 400) + + @mock.patch("microsite_configuration.microsite.get_value", fake_microsite_get_value) + def test_user_signup_including_enhanced_profile(self): + """ + test to create a user form the microsite but don't provide any of the microsite specific + profile information + """ + response = self.client.post(self.url, self.extended_params) + self.assertEqual(response.status_code, 200) + user = User.objects.get(username=self.username) + meta = json.loads(user.profile.meta) + self.assertEqual(meta['address1'], 'foo') + self.assertEqual(meta['state'], 'foo') + self.assertEqual(meta['company'], 'foo') + self.assertEqual(meta['title'], 'foo') diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 4ad74eb2281cc6da1c5979fff0898a911eca1088..b26213624fa4561e3461229144b940809f1cf2eb 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -6,6 +6,7 @@ import logging import re import uuid import time +import json from collections import defaultdict from pytz import UTC @@ -1039,7 +1040,7 @@ def user_signup_handler(sender, **kwargs): # pylint: disable=W0613 log.info(u'user {} originated from a white labeled "Microsite"'.format(kwargs['instance'].id)) -def _do_create_account(post_vars): +def _do_create_account(post_vars, extended_profile=None): """ Given cleaned post variables, create the User and UserProfile objects, as well as the registration for this user. @@ -1089,6 +1090,10 @@ def _do_create_account(post_vars): profile.country = post_vars.get('country') profile.goals = post_vars.get('goals') + # add any extended profile information in the denormalized 'meta' field in the profile + if extended_profile: + profile.meta = json.dumps(extended_profile) + try: profile.year_of_birth = int(post_vars['year_of_birth']) except (ValueError, KeyError): @@ -1115,7 +1120,12 @@ def create_account(request, post_override=None): # pylint: disable-msg=too-many js = {'success': False} # pylint: disable-msg=invalid-name post_vars = post_override if post_override else request.POST - extra_fields = getattr(settings, 'REGISTRATION_EXTRA_FIELDS', {}) + + # allow for microsites to define their own set of required/optional/hidden fields + extra_fields = microsite.get_value( + 'REGISTRATION_EXTRA_FIELDS', + getattr(settings, 'REGISTRATION_EXTRA_FIELDS', {}) + ) if settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH') and pipeline.running(request): post_vars = dict(post_vars.items()) @@ -1188,7 +1198,7 @@ def create_account(request, post_override=None): # pylint: disable-msg=too-many else: min_length = 2 - if len(post_vars[field_name]) < min_length: + if field_name not in post_vars or len(post_vars[field_name]) < min_length: error_str = { 'username': _('Username must be minimum of two characters long'), 'email': _('A properly formatted e-mail is required'), @@ -1204,7 +1214,12 @@ def create_account(request, post_override=None): # pylint: disable-msg=too-many 'city': _('A city is required'), 'country': _('A country is required') } - js['value'] = error_str[field_name] + + if field_name in error_str: + js['value'] = error_str[field_name] + else: + js['value'] = _('You are missing one or more required fields') + js['field'] = field_name return JsonResponse(js, status=400) @@ -1248,10 +1263,22 @@ def create_account(request, post_override=None): # pylint: disable-msg=too-many js['field'] = 'password' return JsonResponse(js, status=400) + # allow microsites to define 'extended profile fields' which are + # captured on user signup (for example via an overriden registration.html) + # and then stored in the UserProfile + extended_profile_fields = microsite.get_value('extended_profile_fields', []) + extended_profile = None + + for field in extended_profile_fields: + if field in post_vars: + if not extended_profile: + extended_profile = {} + extended_profile[field] = post_vars[field] + # Ok, looks like everything is legit. Create the account. try: with transaction.commit_on_success(): - ret = _do_create_account(post_vars) + ret = _do_create_account(post_vars, extended_profile) except AccountValidationError as e: return JsonResponse({'success': False, 'value': e.message, 'field': e.field}, status=400)