def setUp(self): """ Setup components used by each test.""" super().setUp() self.student = UserFactory() registration = Registration() registration.register(self.student) self.msg = compose_activation_email("http://www.example.com", self.student, registration)
def setUp(self): """ Setup components used by each test.""" super(SendActivationEmailTestCase, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments self.student = UserFactory() registration = Registration() registration.register(self.student) self.msg = compose_activation_email("http://www.example.com", self.student, registration)
def test_do_not_send_email_and_do_activate(self): """ Tests that when an inactive user logs-in using the social auth, an activation email is not sent. """ pipeline_partial = {'kwargs': {'social': {'uid': 'fake uid'}}} user = UserFactory(is_active=False) Registration().register(user) request = RequestFactory().get(settings.SOCIAL_AUTH_INACTIVE_USER_URL) request.user = user with patch( 'common.djangoapps.student.views.management.compose_and_send_activation_email' ) as email: with patch( 'common.djangoapps.third_party_auth.provider.Registry.get_from_pipeline' ) as reg: with patch('common.djangoapps.third_party_auth.pipeline.get', return_value=pipeline_partial): with patch( 'common.djangoapps.third_party_auth.pipeline.running', return_value=True): with patch( 'common.djangoapps.third_party_auth.is_enabled', return_value=True): reg.skip_email_verification = True inactive_user_view(request) self.assertEqual(user.is_active, True) self.assertEqual( email.called, False, msg='method should not have been called')
def setUp(self): update_email_marketing_config(enabled=False) self.request_factory = RequestFactory() self.user = UserFactory.create(username='******', email=TEST_EMAIL) self.registration = Registration() self.registration.register(self.user) self.request = self.request_factory.get("foo") update_email_marketing_config(enabled=True) # create some test course objects self.course_id_string = 'edX/toy/2012_Fall' self.course_id = CourseKey.from_string(self.course_id_string) self.course_url = 'http://testserver/courses/edX/toy/2012_Fall/info' self.site = Site.objects.get_current() self.request.site = self.site super(EmailMarketingTests, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
def setUp(self): super(TestActivateAccount, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = UserFactory.create( username=self.username, email=self.email, password=self.password, is_active=False, ) # Set Up Registration self.registration = Registration() self.registration.register(self.user) self.registration.save() self.platform_name = configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) self.activation_email_support_link = configuration_helpers.get_value( 'ACTIVATION_EMAIL_SUPPORT_LINK', settings.ACTIVATION_EMAIL_SUPPORT_LINK ) or settings.SUPPORT_SITE_LINK
def setUp(self): """ Create a user, then log in. """ super().setUp() self.user = UserFactory() Registration().register(self.user) result = self.client.login(username=self.user.username, password="******") assert result, 'Could not log in' self.path = reverse('send_account_activation_email')
def test_authenticated_user_cannot_activate_another_account(self): """ Verify that if a user is authenticated and tries to activate another account, error message is shown. """ # create a new user and registration link second_user = UserFactory.create( username='******', email='*****@*****.**', password='******', is_active=False, ) registration = Registration() registration.register(second_user) registration.save() # Login first user self.login() # Try activating second user's account response = self.client.get(reverse('activate', args=[registration.activation_key]), follow=True) self.assertContains(response, 'Your account could not be activated') # verify that both users have their is_active state set to False self._assert_user_active_state(expected_active_state=False) second_user.refresh_from_db() assert second_user.is_active is False
def test_send_email_to_inactive_user(self, email): """ Tests that when an inactive user logs-in using the social auth, system sends an activation email to the user. """ inactive_user = UserFactory(is_active=False) Registration().register(inactive_user) request = RequestFactory().get(settings.SOCIAL_AUTH_INACTIVE_USER_URL) request.user = inactive_user with patch('common.djangoapps.edxmako.request_context.get_current_request', return_value=request): with patch('common.djangoapps.third_party_auth.pipeline.running', return_value=False): inactive_user_view(request) assert email.called is True, 'method should have been called'
def test_inactive_user_view_prevents_invalid_redirect(self, mock_redirect): inactive_user = UserFactory(is_active=False) Registration().register(inactive_user) request = RequestFactory().get(settings.SOCIAL_AUTH_INACTIVE_USER_URL, {'next': 'https://evil.com'}) request.user = inactive_user with patch( 'common.djangoapps.edxmako.request_context.get_current_request', return_value=request): with patch('common.djangoapps.third_party_auth.pipeline.running', return_value=False): inactive_user_view(request) mock_redirect.assert_called_with('dashboard')
def create_user(self, uname, name, password=None): """ Creates a user """ if not uname: return _('Must provide username') if not name: return _('Must provide full name') msg = u'' if not password: return _('Password must be supplied') email = uname if '@' not in email: msg += _('email address required (not username)') return msg new_password = password user = User(username=uname, email=email, is_active=True) user.set_password(new_password) try: user.save() except IntegrityError: msg += _(u'Oops, failed to create user {user}, {error}').format( user=user, error="IntegrityError" ) return msg reg = Registration() reg.register(user) profile = UserProfile(user=user) profile.name = name profile.save() msg += _(u'User {user} created successfully!').format(user=user) return msg
def do_create_account(form, custom_form=None): """ Given cleaned post variables, create the User and UserProfile objects, as well as the registration for this user. Returns a tuple (User, UserProfile, Registration). Note: this function is also used for creating test users. """ # Check if ALLOW_PUBLIC_ACCOUNT_CREATION flag turned off to restrict user account creation if not configuration_helpers.get_value( 'ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION', True)): raise PermissionDenied() errors = {} errors.update(form.errors) if custom_form: errors.update(custom_form.errors) if errors: raise ValidationError(errors) proposed_username = form.cleaned_data["username"] user = User(username=proposed_username, email=form.cleaned_data["email"], is_active=False) password = normalize_password(form.cleaned_data["password"]) user.set_password(password) registration = Registration() # TODO: Rearrange so that if part of the process fails, the whole process fails. # Right now, we can have e.g. no registration e-mail sent out and a zombie account try: with transaction.atomic(): user.save() if custom_form: custom_model = custom_form.save(commit=False) custom_model.user = user custom_model.save() except IntegrityError: # Figure out the cause of the integrity error # TODO duplicate email is already handled by form.errors above as a ValidationError. # The checks for duplicate email/username should occur in the same place with an # AccountValidationError and a consistent user message returned (i.e. both should # return "It looks like {username} belongs to an existing account. Try again with a # different username.") if username_exists_or_retired(user.username): raise AccountValidationError( USERNAME_EXISTS_MSG_FMT.format(username=proposed_username), field="username") elif email_exists_or_retired(user.email): raise AccountValidationError(_( "An account with the Email '{email}' already exists.").format( email=user.email), field="email") else: raise registration.register(user) profile_fields = [ "name", "level_of_education", "gender", "mailing_address", "city", "country", "goals", "year_of_birth" ] profile = UserProfile( user=user, **{key: form.cleaned_data.get(key) for key in profile_fields}) extended_profile = form.cleaned_extended_profile if extended_profile: profile.meta = json.dumps(extended_profile) try: profile.save() except Exception: log.exception( "UserProfile creation failed for user {id}.".format(id=user.id)) raise return user, profile, registration
class EmailMarketingTests(TestCase): """ Tests for the EmailMarketing signals and tasks classes. """ def setUp(self): update_email_marketing_config(enabled=False) self.request_factory = RequestFactory() self.user = UserFactory.create(username='******', email=TEST_EMAIL) self.registration = Registration() self.registration.register(self.user) self.request = self.request_factory.get("foo") update_email_marketing_config(enabled=True) # create some test course objects self.course_id_string = 'edX/toy/2012_Fall' self.course_id = CourseKey.from_string(self.course_id_string) self.course_url = 'http://testserver/courses/edX/toy/2012_Fall/info' self.site = Site.objects.get_current() self.request.site = self.site super(EmailMarketingTests, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments @freeze_time(datetime.datetime.now()) @patch('lms.djangoapps.email_marketing.signals.crum.get_current_request') @patch('sailthru.sailthru_client.SailthruClient.api_post') def test_drop_cookie(self, mock_sailthru, mock_get_current_request): """ Test add_email_marketing_cookies """ response = JsonResponse({ "success": True, "redirect_url": 'test.com/test', }) self.request.COOKIES['anonymous_interest'] = 'cookie_content' mock_get_current_request.return_value = self.request cookies = {'cookie': 'test_cookie'} mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': cookies})) with LogCapture(LOGGER_NAME, level=logging.INFO) as logger: add_email_marketing_cookies(None, response=response, user=self.user) logger.check( (LOGGER_NAME, 'INFO', 'Started at {start} and ended at {end}, time spent:{delta} milliseconds'.format( start=datetime.datetime.now().isoformat(' '), end=datetime.datetime.now().isoformat(' '), delta=0 if six.PY2 else 0.0) ), (LOGGER_NAME, 'INFO', 'sailthru_hid cookie:{cookies[cookie]} successfully retrieved for user {user}'.format( cookies=cookies, user=TEST_EMAIL) ) ) mock_sailthru.assert_called_with('user', {'fields': {'keys': 1}, 'cookies': {'anonymous_interest': 'cookie_content'}, 'id': TEST_EMAIL, 'vars': {'last_login_date': ANY}}) self.assertTrue('sailthru_hid' in response.cookies) # lint-amnesty, pylint: disable=wrong-assert-type self.assertEqual(response.cookies['sailthru_hid'].value, "test_cookie") @patch('sailthru.sailthru_client.SailthruClient.api_post') def test_get_cookies_via_sailthu(self, mock_sailthru): cookies = {'cookie': 'test_cookie'} mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': cookies})) post_parms = { 'id': self.user.email, 'fields': {'keys': 1}, 'vars': {'last_login_date': datetime.datetime.now().strftime("%Y-%m-%d")}, 'cookies': {'anonymous_interest': 'cookie_content'} } expected_cookie = get_email_cookies_via_sailthru.delay(self.user.email, post_parms) mock_sailthru.assert_called_with('user', {'fields': {'keys': 1}, 'cookies': {'anonymous_interest': 'cookie_content'}, 'id': TEST_EMAIL, 'vars': {'last_login_date': ANY}}) self.assertEqual(cookies['cookie'], expected_cookie.result) @patch('sailthru.sailthru_client.SailthruClient.api_post') def test_drop_cookie_error_path(self, mock_sailthru): """ test that error paths return no cookie """ response = JsonResponse({ "success": True, "redirect_url": 'test.com/test', }) mock_sailthru.return_value = SailthruResponse(JsonResponse({'keys': {'cookiexx': 'test_cookie'}})) add_email_marketing_cookies(None, response=response, user=self.user) self.assertFalse('sailthru_hid' in response.cookies) # lint-amnesty, pylint: disable=wrong-assert-type mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': "error", "errormsg": "errormsg"})) add_email_marketing_cookies(None, response=response, user=self.user) self.assertFalse('sailthru_hid' in response.cookies) # lint-amnesty, pylint: disable=wrong-assert-type mock_sailthru.side_effect = SailthruClientError add_email_marketing_cookies(None, response=response, user=self.user) self.assertFalse('sailthru_hid' in response.cookies) # lint-amnesty, pylint: disable=wrong-assert-type @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_get') def test_add_user(self, mock_sailthru_get, mock_sailthru_post, mock_log_error): """ test async method in tasks that actually updates Sailthru """ site_dict = {'id': self.site.id, 'domain': self.site.domain, 'name': self.site.name} mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) mock_sailthru_get.return_value = SailthruResponse(JsonResponse({'lists': [{'name': 'new list'}], 'ok': True})) update_user.delay( {'gender': 'm', 'username': '******', 'activated': 1}, TEST_EMAIL, site_dict, new_user=True ) self.assertFalse(mock_log_error.called) self.assertEqual(mock_sailthru_post.call_args[0][0], "user") userparms = mock_sailthru_post.call_args[0][1] self.assertEqual(userparms['key'], "email") self.assertEqual(userparms['id'], TEST_EMAIL) self.assertEqual(userparms['vars']['gender'], "m") self.assertEqual(userparms['vars']['username'], "test") self.assertEqual(userparms['vars']['activated'], 1) self.assertEqual(userparms['lists']['new list'], 1) @patch('lms.djangoapps.email_marketing.signals.get_email_cookies_via_sailthru.delay') def test_drop_cookie_task_error(self, mock_email_cookies): """ Tests that task error is handled """ mock_email_cookies.return_value = {} mock_email_cookies.get.side_effect = Exception with LogCapture(LOGGER_NAME, level=logging.INFO) as logger: add_email_marketing_cookies(None, response=None, user=self.user) logger.check(( LOGGER_NAME, 'ERROR', 'Exception Connecting to celery task for {}'.format( self.user.email ) )) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_email_not_sent_to_enterprise_learners(self, mock_sailthru_post): """ tests that welcome email is not sent to the enterprise learner """ mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) update_user.delay( sailthru_vars={ 'is_enterprise_learner': True, 'enterprise_name': 'test name', }, email=self.user.email ) self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send") @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_add_user_list_not_called_on_white_label_domain(self, mock_sailthru_post): """ test user is not added to Sailthru user lists if registered from a whitel labe site """ existing_site = Site.objects.create(domain='testwhitelabel.com', name='White Label') site_dict = {'id': existing_site.id, 'domain': existing_site.domain, 'name': existing_site.name} update_user.delay( {'gender': 'm', 'username': '******', 'activated': 1}, TEST_EMAIL, site=site_dict, new_user=True ) self.assertFalse(mock_sailthru_post.called) @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_update_user_error_logging(self, mock_sailthru, mock_log_error): """ Ensure that error returned from Sailthru api is logged """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'})) update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) # force Sailthru API exception mock_log_error.reset_mock() mock_sailthru.side_effect = SailthruClientError update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) # force Sailthru API exception on 2nd call mock_log_error.reset_mock() mock_sailthru.side_effect = [SailthruResponse(JsonResponse({'ok': True})), SailthruClientError] update_user.delay({}, self.user.email, activation=True) self.assertTrue(mock_log_error.called) # force Sailthru API error return on 2nd call mock_log_error.reset_mock() mock_sailthru.side_effect = [SailthruResponse(JsonResponse({'ok': True})), SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'}))] update_user.delay({}, self.user.email, activation=True) self.assertTrue(mock_log_error.called) @patch('lms.djangoapps.email_marketing.tasks.update_user.retry') @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_update_user_error_retryable(self, mock_sailthru, mock_log_error, mock_retry): """ Ensure that retryable error is retried """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'})) update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) self.assertTrue(mock_retry.called) @patch('lms.djangoapps.email_marketing.tasks.update_user.retry') @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_update_user_error_nonretryable(self, mock_sailthru, mock_log_error, mock_retry): """ Ensure that non-retryable error is not retried """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 1, 'errormsg': 'Got an error'})) update_user.delay({}, self.user.email) self.assertTrue(mock_log_error.called) self.assertFalse(mock_retry.called) @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_just_return_tasks(self, mock_sailthru, mock_log_error): """ Ensure that disabling Sailthru just returns """ update_email_marketing_config(enabled=False) update_user.delay(self.user.username, self.user.email) self.assertFalse(mock_log_error.called) self.assertFalse(mock_sailthru.called) update_user_email.delay(self.user.username, "*****@*****.**") self.assertFalse(mock_log_error.called) self.assertFalse(mock_sailthru.called) update_email_marketing_config(enabled=True) @patch('lms.djangoapps.email_marketing.signals.log.error') def test_just_return_signals(self, mock_log_error): """ Ensure that disabling Sailthru just returns """ update_email_marketing_config(enabled=False) add_email_marketing_cookies(None) self.assertFalse(mock_log_error.called) email_marketing_register_user(None, None, None) self.assertFalse(mock_log_error.called) update_email_marketing_config(enabled=True) # test anonymous users anon = AnonymousUser() email_marketing_register_user(None, anon, None) self.assertFalse(mock_log_error.called) email_marketing_user_field_changed(None, user=anon) self.assertFalse(mock_log_error.called) user = User(username='******', email='*****@*****.**') email_marketing_user_field_changed(None, user=user) self.assertFalse(mock_log_error.called) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_change_email(self, mock_sailthru): """ test async method in task that changes email in Sailthru """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'ok': True})) update_user_email.delay(TEST_EMAIL, "*****@*****.**") self.assertEqual(mock_sailthru.call_args[0][0], "user") userparms = mock_sailthru.call_args[0][1] self.assertEqual(userparms['key'], "email") self.assertEqual(userparms['id'], "*****@*****.**") self.assertEqual(userparms['keys']['email'], TEST_EMAIL) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_get_or_create_sailthru_list(self, mock_sailthru_client): """ Test the task the create sailthru lists. """ mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []})) _get_or_create_user_list(mock_sailthru_client, 'test1_user_list') mock_sailthru_client.api_get.assert_called_with("list", {}) mock_sailthru_client.api_post.assert_called_with( "list", {'list': 'test1_user_list', 'primary': 0, 'public_name': 'test1_user_list'} ) # test existing user list mock_sailthru_client.api_get.return_value = \ SailthruResponse(JsonResponse({'lists': [{'name': 'test1_user_list'}]})) _get_or_create_user_list(mock_sailthru_client, 'test2_user_list') mock_sailthru_client.api_get.assert_called_with("list", {}) mock_sailthru_client.api_post.assert_called_with( "list", {'list': 'test2_user_list', 'primary': 0, 'public_name': 'test2_user_list'} ) # test get error from Sailthru mock_sailthru_client.api_get.return_value = \ SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'})) self.assertEqual(_get_or_create_user_list( mock_sailthru_client, 'test1_user_list'), None ) # test post error from Sailthru mock_sailthru_client.api_post.return_value = \ SailthruResponse(JsonResponse({'error': 43, 'errormsg': 'Got an error'})) mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []})) self.assertEqual(_get_or_create_user_list(mock_sailthru_client, 'test2_user_list'), None) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_get_sailthru_list_map_no_list(self, mock_sailthru_client): """Test when no list returned from sailthru""" mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []})) self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {}) mock_sailthru_client.api_get.assert_called_with("list", {}) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_get_sailthru_list_map_error(self, mock_sailthru_client): """Test when error occurred while fetching data from sailthru""" mock_sailthru_client.api_get.return_value = SailthruResponse( JsonResponse({'error': 43, 'errormsg': 'Got an error'}) ) self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {}) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_get_sailthru_list_map_exception(self, mock_sailthru_client): """Test when exception raised while fetching data from sailthru""" mock_sailthru_client.api_get.side_effect = SailthruClientError self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {}) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_get_sailthru_list(self, mock_sailthru_client): """Test fetch list data from sailthru""" mock_sailthru_client.api_get.return_value = \ SailthruResponse(JsonResponse({'lists': [{'name': 'test1_user_list'}]})) self.assertEqual( _get_list_from_email_marketing_provider(mock_sailthru_client), {'test1_user_list': {'name': 'test1_user_list'}} ) mock_sailthru_client.api_get.assert_called_with("list", {}) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_create_sailthru_list(self, mock_sailthru_client): """Test create list in sailthru""" mock_sailthru_client.api_post.return_value = SailthruResponse(JsonResponse({'ok': True})) self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), True) self.assertEqual(mock_sailthru_client.api_post.call_args[0][0], "list") listparms = mock_sailthru_client.api_post.call_args[0][1] self.assertEqual(listparms['list'], 'test_list_name') self.assertEqual(listparms['primary'], 0) self.assertEqual(listparms['public_name'], 'test_list_name') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_create_sailthru_list_error(self, mock_sailthru_client): """Test error occurrence while creating sailthru list""" mock_sailthru_client.api_post.return_value = SailthruResponse( JsonResponse({'error': 43, 'errormsg': 'Got an error'}) ) self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient') def test_create_sailthru_list_exception(self, mock_sailthru_client): """Test exception raised while creating sailthru list""" mock_sailthru_client.api_post.side_effect = SailthruClientError self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False) @patch('lms.djangoapps.email_marketing.tasks.log.error') @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') def test_error_logging(self, mock_sailthru, mock_log_error): """ Ensure that error returned from Sailthru api is logged """ mock_sailthru.return_value = SailthruResponse(JsonResponse({'error': 100, 'errormsg': 'Got an error'})) update_user_email.delay(self.user.username, "*****@*****.**") self.assertTrue(mock_log_error.called) mock_sailthru.side_effect = SailthruClientError update_user_email.delay(self.user.username, "*****@*****.**") self.assertTrue(mock_log_error.called) @patch('lms.djangoapps.email_marketing.signals.crum.get_current_request') @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_register_user(self, mock_update_user, mock_get_current_request): """ make sure register user call invokes update_user and includes activation_key """ mock_get_current_request.return_value = self.request email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertTrue(mock_update_user.called) self.assertEqual(mock_update_user.call_args[0][0]['activation_key'], self.registration.activation_key) self.assertLessEqual(mock_update_user.call_args[0][0]['signupNumber'], 9) @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_register_user_no_request(self, mock_update_user): """ make sure register user call invokes update_user and includes activation_key """ email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertTrue(mock_update_user.called) self.assertEqual(mock_update_user.call_args[0][0]['activation_key'], self.registration.activation_key) @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_register_user_language_preference(self, mock_update_user): """ make sure register user call invokes update_user and includes language preference """ # If the user hasn't set an explicit language preference, we should send the application's default. self.assertIsNone(self.user.preferences.model.get_value(self.user, LANGUAGE_KEY)) email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], settings.LANGUAGE_CODE) # If the user has set an explicit language preference, we should send it. self.user.preferences.create(key=LANGUAGE_KEY, value='es-419') email_marketing_register_user(None, user=self.user, registration=self.registration) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], 'es-419') @patch.dict(settings.FEATURES, {"ENABLE_THIRD_PARTY_AUTH": False}) @patch('lms.djangoapps.email_marketing.signals.crum.get_current_request') @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') @ddt.data(('auth_userprofile', 'gender', 'f', True), ('auth_user', 'is_active', 1, True), ('auth_userprofile', 'shoe_size', 1, False), ('user_api_userpreference', 'pref-lang', 'en', True)) @ddt.unpack def test_modify_field(self, table, setting, value, result, mock_update_user, mock_get_current_request): """ Test that correct fields call update_user """ mock_get_current_request.return_value = self.request email_marketing_user_field_changed(None, self.user, table=table, setting=setting, new_value=value) self.assertEqual(mock_update_user.called, result) @patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post') @patch('lms.djangoapps.email_marketing.signals.third_party_auth.provider.Registry.get_from_pipeline') @patch('lms.djangoapps.email_marketing.signals.third_party_auth.pipeline.get') @patch('lms.djangoapps.email_marketing.signals.crum.get_current_request') @ddt.data(True, False) def test_modify_field_with_sso(self, send_welcome_email, mock_get_current_request, mock_pipeline_get, mock_registry_get_from_pipeline, mock_sailthru_post): """ Test that welcome email is sent appropriately in the context of SSO registration """ mock_get_current_request.return_value = self.request mock_pipeline_get.return_value = 'saml-idp' mock_registry_get_from_pipeline.return_value = Mock(send_welcome_email=send_welcome_email) mock_sailthru_post.return_value = SailthruResponse(JsonResponse({'ok': True})) email_marketing_user_field_changed(None, self.user, table='auth_user', setting='is_active', new_value=True) if send_welcome_email: self.assertEqual(mock_sailthru_post.call_args[0][0], "send") else: self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send") @patch('lms.djangoapps.email_marketing.tasks.update_user.delay') def test_modify_language_preference(self, mock_update_user): """ Test that update_user is called with new language preference """ # If the user hasn't set an explicit language preference, we should send the application's default. self.assertIsNone(self.user.preferences.model.get_value(self.user, LANGUAGE_KEY)) email_marketing_user_field_changed( None, self.user, table='user_api_userpreference', setting=LANGUAGE_KEY, new_value=None ) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], settings.LANGUAGE_CODE) # If the user has set an explicit language preference, we should send it. self.user.preferences.create(key=LANGUAGE_KEY, value='fr') email_marketing_user_field_changed( None, self.user, table='user_api_userpreference', setting=LANGUAGE_KEY, new_value='fr' ) self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], 'fr') @patch('lms.djangoapps.email_marketing.tasks.update_user_email.delay') def test_modify_email(self, mock_update_user): """ Test that change to email calls update_user_email """ email_marketing_user_field_changed(None, self.user, table='auth_user', setting='email', old_value='*****@*****.**') mock_update_user.assert_called_with(self.user.email, '*****@*****.**') # make sure nothing called if disabled mock_update_user.reset_mock() update_email_marketing_config(enabled=False) email_marketing_user_field_changed(None, self.user, table='auth_user', setting='email', old_value='*****@*****.**') self.assertFalse(mock_update_user.called)
class TestActivateAccount(TestCase): """Tests for account creation""" def setUp(self): super(TestActivateAccount, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = UserFactory.create( username=self.username, email=self.email, password=self.password, is_active=False, ) # Set Up Registration self.registration = Registration() self.registration.register(self.user) self.registration.save() self.platform_name = configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME) self.activation_email_support_link = configuration_helpers.get_value( 'ACTIVATION_EMAIL_SUPPORT_LINK', settings.ACTIVATION_EMAIL_SUPPORT_LINK ) or settings.SUPPORT_SITE_LINK def login(self): """ Login with test user. Since, only active users can login, so we must activate the user before login. This method does the following tasks in order, 1. Stores user's active/in-active status in a variable. 2. Makes sure user account is active. 3. Authenticated user with the client. 4. Reverts user's original active/in-active status. """ is_active = self.user.is_active # Make sure user is active before login self.user.is_active = True self.user.save() self.client.login(username=self.username, password=self.password) # Revert user activation status self.user.is_active = is_active self.user.save() def assert_no_tracking(self, mock_segment_identify): """ Assert that activate sets the flag but does not call segment. """ # Ensure that the user starts inactive self.assertFalse(self.user.is_active) # Until you explicitly activate it self.registration.activate() self.assertTrue(self.user.is_active) self.assertFalse(mock_segment_identify.called) @patch('common.djangoapps.student.models.USER_ACCOUNT_ACTIVATED') def test_activation_signal(self, mock_signal): """ Verify that USER_ACCOUNT_ACTIVATED is emitted upon account email activation. """ assert not self.user.is_active, 'Ensure that the user starts inactive' assert not mock_signal.send_robust.call_count, 'Ensure no signal is fired before activation' self.registration.activate() # Until you explicitly activate it assert self.user.is_active, 'Sanity check for .activate()' mock_signal.send_robust.assert_called_once_with(Registration, user=self.user) # Ensure the signal is emitted def test_account_activation_message(self): """ Verify that account correct activation message is displayed. If logged in user has not activated their account, make sure that an account activation message is displayed on dashboard sidebar. """ # Log in with test user. self.login() expected_message = ( u"Check your {email_start}{email}{email_end} inbox for an account activation link from " u"{platform_name}. If you need help, contact {link_start}{platform_name} Support{link_end}." ).format( platform_name=self.platform_name, email_start="<strong>", email_end="</strong>", email=self.user.email, link_start="<a target='_blank' href='{activation_email_support_link}'>".format( activation_email_support_link=self.activation_email_support_link, ), link_end="</a>", ) response = self.client.get(reverse('dashboard')) self.assertContains(response, expected_message) # Now make sure account activation message goes away when user activated the account self.user.is_active = True self.user.save() self.login() response = self.client.get(reverse('dashboard')) self.assertNotContains(response, expected_message) def _assert_user_active_state(self, expected_active_state): user = User.objects.get(username=self.user.username) self.assertEqual(user.is_active, expected_active_state) def test_account_activation_notification_on_logistration(self): """ Verify that logistration page displays success/error/info messages about account activation. """ login_page_url = "{login_url}?next={redirect_url}".format( login_url=reverse('signin_user'), redirect_url=reverse('dashboard'), ) self._assert_user_active_state(expected_active_state=False) # Access activation link, message should say that account has been activated. response = self.client.get(reverse('activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Success! You have activated your account.') self._assert_user_active_state(expected_active_state=True) # Access activation link again, message should say that account is already active. response = self.client.get(reverse('activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'This account has already been activated.') self._assert_user_active_state(expected_active_state=True) # Open account activation page with an invalid activation link, # there should be an error message displayed. response = self.client.get(reverse('activate', args=[uuid4().hex]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Your account could not be activated') @override_settings(FEATURES=FEATURES_WITH_AUTHN_MFE_ENABLED) @override_waffle_flag(REDIRECT_TO_AUTHN_MICROFRONTEND, active=True) def test_unauthenticated_user_redirects_to_mfe(self): """ Verify that if Authn MFE is enabled then authenticated user redirects to login page with correct query param. """ login_page_url = "{authn_mfe}/login?account_activation_status=".format( authn_mfe=settings.AUTHN_MICROFRONTEND_URL ) self._assert_user_active_state(expected_active_state=False) # Access activation link, the user is redirected to login page with success query param response = self.client.get(reverse('activate', args=[self.registration.activation_key])) self.assertEqual(response.url, login_page_url + 'success') # Access activation link again, the user is redirected to login page with info query param response = self.client.get(reverse('activate', args=[self.registration.activation_key])) self.assertEqual(response.url, login_page_url + 'info') # Open account activation page with an invalid activation link, the query param should contain error response = self.client.get(reverse('activate', args=[uuid4().hex])) self.assertEqual(response.url, login_page_url + 'error')
def _create_sample_data(self): """ Creates the users and register them. """ for __ in range(3): Registration().register(UserFactory.create())
class TestActivateAccount(TestCase): """Tests for account creation""" def setUp(self): super().setUp() self.username = "******" self.email = "*****@*****.**" self.password = "******" self.user = UserFactory.create( username=self.username, email=self.email, password=self.password, is_active=False, ) # Set Up Registration self.registration = Registration() self.registration.register(self.user) self.registration.save() self.platform_name = configuration_helpers.get_value( 'PLATFORM_NAME', settings.PLATFORM_NAME) self.activation_email_support_link = configuration_helpers.get_value( 'ACTIVATION_EMAIL_SUPPORT_LINK', settings. ACTIVATION_EMAIL_SUPPORT_LINK) or settings.SUPPORT_SITE_LINK def login(self): """ Login with test user. Since, only active users can login, so we must activate the user before login. This method does the following tasks in order, 1. Stores user's active/in-active status in a variable. 2. Makes sure user account is active. 3. Authenticated user with the client. 4. Reverts user's original active/in-active status. """ is_active = self.user.is_active # Make sure user is active before login self.user.is_active = True self.user.save() self.client.login(username=self.username, password=self.password) # Revert user activation status self.user.is_active = is_active self.user.save() def assert_no_tracking(self, mock_segment_identify): """ Assert that activate sets the flag but does not call segment. """ # Ensure that the user starts inactive assert not self.user.is_active # Until you explicitly activate it self.registration.activate() assert self.user.is_active assert not mock_segment_identify.called @patch('common.djangoapps.student.models.USER_ACCOUNT_ACTIVATED') def test_activation_signal(self, mock_signal): """ Verify that USER_ACCOUNT_ACTIVATED is emitted upon account email activation. """ assert not self.user.is_active, 'Ensure that the user starts inactive' assert not mock_signal.send_robust.call_count, 'Ensure no signal is fired before activation' self.registration.activate() # Until you explicitly activate it assert self.user.is_active, 'Sanity check for .activate()' mock_signal.send_robust.assert_called_once_with( Registration, user=self.user) # Ensure the signal is emitted def test_activation_timestamp(self): """ Assert that activate sets the flag but does not call segment. """ # Ensure that the user starts inactive assert not self.user.is_active # Until you explicitly activate it timestamp_before_activation = datetime.utcnow() self.registration.activate() assert self.user.is_active assert self.registration.activation_timestamp > timestamp_before_activation def test_account_activation_message(self): """ Verify that account correct activation message is displayed. If logged in user has not activated their account, make sure that an account activation message is displayed on dashboard sidebar. """ # Log in with test user. self.login() expected_message = ( "Check your {email_start}{email}{email_end} inbox for an account activation link from " "{platform_name}. If you need help, contact {link_start}{platform_name} Support{link_end}." ).format( platform_name=self.platform_name, email_start="<strong>", email_end="</strong>", email=self.user.email, link_start= "<a target='_blank' href='{activation_email_support_link}'>". format(activation_email_support_link=self. activation_email_support_link, ), link_end="</a>", ) response = self.client.get(reverse('dashboard')) self.assertContains(response, expected_message) # Now make sure account activation message goes away when user activated the account self.user.is_active = True self.user.save() self.login() response = self.client.get(reverse('dashboard')) self.assertNotContains(response, expected_message) def _assert_user_active_state(self, expected_active_state): user = User.objects.get(username=self.user.username) assert user.is_active == expected_active_state def test_account_activation_notification_on_logistration(self): """ Verify that logistration page displays success/error/info messages about account activation. """ login_page_url = "{login_url}?next={redirect_url}".format( login_url=reverse('signin_user'), redirect_url=reverse('dashboard'), ) self._assert_user_active_state(expected_active_state=False) # Access activation link, message should say that account has been activated. response = self.client.get(reverse( 'activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Success! You have activated your account.') self._assert_user_active_state(expected_active_state=True) # Access activation link again, message should say that account is already active. response = self.client.get(reverse( 'activate', args=[self.registration.activation_key]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'This account has already been activated.') self._assert_user_active_state(expected_active_state=True) # Open account activation page with an invalid activation link, # there should be an error message displayed. response = self.client.get(reverse('activate', args=[uuid4().hex]), follow=True) self.assertRedirects(response, login_page_url) self.assertContains(response, 'Your account could not be activated') @override_settings(LOGIN_REDIRECT_WHITELIST=['localhost:1991']) @override_settings(FEATURES={ **FEATURES_WITH_AUTHN_MFE_ENABLED, 'ENABLE_ENTERPRISE_INTEGRATION': True }) @override_waffle_flag(REDIRECT_TO_AUTHN_MICROFRONTEND, active=True) def test_authenticated_account_activation_with_valid_next_url(self): """ Verify that an activation link with a valid next URL will redirect the activated enterprise user to that next URL, even if the AuthN MFE is active and redirects to it are enabled. """ self._assert_user_active_state(expected_active_state=False) EnterpriseCustomerUserFactory(user_id=self.user.id) # Make sure the user is authenticated before activation. self.login() redirect_url = 'http://*****:*****@override_settings(LOGIN_REDIRECT_WHITELIST=['localhost:9876']) @override_settings(FEATURES=FEATURES_WITH_AUTHN_MFE_ENABLED) @override_waffle_flag(REDIRECT_TO_AUTHN_MICROFRONTEND, active=False) def test_account_activation_invalid_next_url_redirects_dashboard(self): """ Verify that an activation link with an invalid next URL (i.e. it's for a domain not in the allowed list of redirect destinations) will redirect the activated, but unauthenticated, user to a login URL that points to 'dashboard' as the next URL. """ self._assert_user_active_state(expected_active_state=False) redirect_url = 'http://localhost:1991/pied-piper/learn' base_activation_url = reverse('activate', args=[self.registration.activation_key]) activation_url = '{base}?{params}'.format( base=base_activation_url, params=urlencode({'next': redirect_url}), ) response = self.client.get(activation_url, follow=True, HTTP_ACCEPT='*/*') expected_destination = "{login_url}?next={redirect_url}".format( login_url=reverse('signin_user'), redirect_url=reverse('dashboard'), ) self.assertRedirects(response, expected_destination) self._assert_user_active_state(expected_active_state=True) @override_settings(FEATURES=FEATURES_WITH_AUTHN_MFE_ENABLED) @override_waffle_flag(REDIRECT_TO_AUTHN_MICROFRONTEND, active=True) def test_unauthenticated_user_redirects_to_mfe(self): """ Verify that if Authn MFE is enabled then authenticated user redirects to login page with correct query param. """ login_page_url = "{authn_mfe}/login?account_activation_status=".format( authn_mfe=settings.AUTHN_MICROFRONTEND_URL) self._assert_user_active_state(expected_active_state=False) # Access activation link, the user is redirected to login page with success query param response = self.client.get( reverse('activate', args=[self.registration.activation_key])) assert response.url == (login_page_url + 'success') # Access activation link again, the user is redirected to login page with info query param response = self.client.get( reverse('activate', args=[self.registration.activation_key])) assert response.url == (login_page_url + 'info') # Open account activation page with an invalid activation link, the query param should contain error response = self.client.get(reverse('activate', args=[uuid4().hex])) assert response.url == (login_page_url + 'error') @override_settings(LOGIN_REDIRECT_WHITELIST=['localhost:1991']) @override_settings(FEATURES=FEATURES_WITH_AUTHN_MFE_ENABLED) @override_waffle_flag(REDIRECT_TO_AUTHN_MICROFRONTEND, active=True) def test_unauthenticated_user_redirects_to_mfe_with_valid_next_url(self): """ Verify that if Authn MFE is enabled then authenticated user redirects to login page with correct account_activation_status param. Additionally, if a valid `next` redirect URL is provided to the activation URL, it should be included as a parameter in the login page the requesting user is redirected to. """ login_page_url = "{authn_mfe}/login?account_activation_status=".format( authn_mfe=settings.AUTHN_MICROFRONTEND_URL) self._assert_user_active_state(expected_active_state=False) redirect_url = 'http://*****:*****@fake.edx.org', password='******', is_active=False, ) registration = Registration() registration.register(second_user) registration.save() # Login first user self.login() # Try activating second user's account response = self.client.get(reverse('activate', args=[registration.activation_key]), follow=True) self.assertContains(response, 'Your account could not be activated') # verify that both users have their is_active state set to False self._assert_user_active_state(expected_active_state=False) second_user.refresh_from_db() assert second_user.is_active is False