From f02fe4c2036c38ed93c639b2717f50253fbd545d Mon Sep 17 00:00:00 2001 From: uzairr Date: Fri, 19 Nov 2021 11:53:40 +0500 Subject: [PATCH] feat: allow login if email opt-in is enabled allow login to in-active users if email opt-in is enabled Fixes: VAN-768 --- cms/envs/common.py | 2 ++ .../StudentAccountDeletionInitializer.js | 3 ++- .../components/StudentAccountDeletion.jsx | 4 +++- .../student_account/account_settings.html | 1 + .../core/djangoapps/user_authn/views/login.py | 4 +++- .../user_authn/views/tests/test_login.py | 19 +++++++++++++++++++ 6 files changed, 30 insertions(+), 3 deletions(-) diff --git a/cms/envs/common.py b/cms/envs/common.py index 8d3236f7fe..aacfdeafa9 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -486,6 +486,8 @@ ENABLE_COPPA_COMPLIANCE = False ENABLE_JASMINE = False +MARKETING_EMAILS_OPT_IN = False + # List of logout URIs for each IDA that the learner should be logged out of when they logout of the LMS. Only applies to # IDA for which the social auth flow uses DOT (Django OAuth Toolkit). IDA_LOGOUT_URI_LIST = [] diff --git a/lms/static/js/student_account/StudentAccountDeletionInitializer.js b/lms/static/js/student_account/StudentAccountDeletionInitializer.js index f062264d16..9431ddb055 100644 --- a/lms/static/js/student_account/StudentAccountDeletionInitializer.js +++ b/lms/static/js/student_account/StudentAccountDeletionInitializer.js @@ -22,7 +22,8 @@ const wrapperRendered = setInterval(() => { additionalSiteSpecificDeletionText: window.additionalSiteSpecificDeletionText, mktgRootLink: window.mktgRootLink, platformName: window.platformName, - siteName: window.siteName + siteName: window.siteName, + mktgEmailOptIn: window.mktgEmailOptIn }, }); } diff --git a/lms/static/js/student_account/components/StudentAccountDeletion.jsx b/lms/static/js/student_account/components/StudentAccountDeletion.jsx index 30713689bb..741bd5a9e7 100644 --- a/lms/static/js/student_account/components/StudentAccountDeletion.jsx +++ b/lms/static/js/student_account/components/StudentAccountDeletion.jsx @@ -57,10 +57,11 @@ export class StudentAccountDeletion extends React.Component { ); const activationError = StringUtils.interpolate( - gettext('Before proceeding, please {htmlStart}activate your account{htmlEnd}.'), + gettext('Before proceeding, please {htmlStart}{emailMsg}{htmlEnd}.'), { htmlStart: '', htmlEnd: '', + emailMsg: this.props.mktgEmailOptIn ? 'confirm your email' : 'activate your account', }, ); @@ -173,6 +174,7 @@ StudentAccountDeletion.propTypes = { mktgRootLink: PropTypes.string, platformName: PropTypes.string, siteName: PropTypes.string, + mktgEmailOptIn: PropTypes.bool.isRequired, }; StudentAccountDeletion.defaultProps = { diff --git a/lms/templates/student_account/account_settings.html b/lms/templates/student_account/account_settings.html index 4bdca0a81b..9f43b0b601 100644 --- a/lms/templates/student_account/account_settings.html +++ b/lms/templates/student_account/account_settings.html @@ -83,6 +83,7 @@ from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_f window.mktgRootLink = "${ static.marketing_link('ROOT') | n, js_escaped_string }"; window.platformName = "${ platform_name | n, js_escaped_string }"; window.siteName = "${ static.get_value('SITE_NAME', settings.SITE_NAME) | n, js_escaped_string }"; + window.mktgEmailOptIn = ${ settings.MARKETING_EMAILS_OPT_IN | n, dump_js_escaped_json };; <%static:webpack entry="StudentAccountDeletionInitializer"> diff --git a/openedx/core/djangoapps/user_authn/views/login.py b/openedx/core/djangoapps/user_authn/views/login.py index f061c5a654..62982825a3 100644 --- a/openedx/core/djangoapps/user_authn/views/login.py +++ b/openedx/core/djangoapps/user_authn/views/login.py @@ -561,7 +561,9 @@ def login_user(request, api_version='v1'): _enforce_password_policy_compliance(request, possibly_authenticated_user) check_pwned_password_and_send_track_event.delay(user.id, request.POST.get('password'), user.is_staff) - if possibly_authenticated_user is None or not possibly_authenticated_user.is_active: + if possibly_authenticated_user is None or not ( + possibly_authenticated_user.is_active or settings.MARKETING_EMAILS_OPT_IN + ): _handle_failed_authentication(user, possibly_authenticated_user) _handle_successful_authentication_and_login(possibly_authenticated_user, request) diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_login.py b/openedx/core/djangoapps/user_authn/views/tests/test_login.py index daf6b7f660..ba786c8cbc 100644 --- a/openedx/core/djangoapps/user_authn/views/tests/test_login.py +++ b/openedx/core/djangoapps/user_authn/views/tests/test_login.py @@ -99,6 +99,25 @@ class LoginTest(SiteMixin, CacheIsolationTestCase, OpenEdxEventsTestMixin): FEATURES_WITH_AUTHN_MFE_ENABLED = settings.FEATURES.copy() FEATURES_WITH_AUTHN_MFE_ENABLED['ENABLE_AUTHN_MICROFRONTEND'] = True + @override_settings(MARKETING_EMAILS_OPT_IN=True) + def test_login_success_with_opt_in_flag_enabled(self): + self.user.is_active = False + self.user.save() + response, mock_audit_log = self._login_response( + self.user_email, self.password, patched_audit_log='common.djangoapps.student.models.AUDIT_LOG' + ) + self._assert_response(response, success=True) + self._assert_audit_log(mock_audit_log, 'info', ['Login success', self.user_email]) + + @override_settings(MARKETING_EMAILS_OPT_IN=False) + def test_login_failed_with_opt_in_flag_disabled(self): + self.user.is_active = False + self.user.save() + response, mock_audit_log = self._login_response(self.user_email, self.password) + self._assert_audit_log( + mock_audit_log, 'warning', ['Login failed - Account not active for user.id: 1, resending activation'] + ) + @patch.dict(settings.FEATURES, { "ENABLE_THIRD_PARTY_AUTH": True })