diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index e545ecda03798ab8f1822ec8f11a5bf43b984175..542cd3597b93810724864bbd9e346d55ebb4a24e 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -18,6 +18,7 @@ import pytz from bs4 import BeautifulSoup from mock import patch, Mock import requests +from waffle.testutils import override_switch from django.conf import settings from django.core.urlresolvers import reverse @@ -41,18 +42,21 @@ from shoppingcart.models import Order, CertificateItem from student.tests.factories import UserFactory, CourseEnrollmentFactory from student.models import CourseEnrollment from util.testing import UrlResetMixin -from lms.djangoapps.verify_student.views import ( - checkout_with_ecommerce_service, render_to_response, PayAndVerifyView, -) -from lms.djangoapps.verify_student.models import ( - VerificationDeadline, SoftwareSecurePhotoVerification, -) from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.django import modulestore from xmodule.modulestore import ModuleStoreEnum +from lms.djangoapps.verify_student.models import ( + VerificationDeadline, SoftwareSecurePhotoVerification, +) +from lms.djangoapps.verify_student.views import ( + checkout_with_ecommerce_service, render_to_response, PayAndVerifyView, + DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH, +) + + def mock_render_to_response(*args, **kwargs): return render_to_response(*args, **kwargs) @@ -672,6 +676,25 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin): PayAndVerifyView.WEBCAM_REQ, ]) + @override_switch(DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH, active=True) + @ddt.data("verify_student_start_flow", "verify_student_begin_flow") + def test_disable_account_activation_requirement_flag_active(self, payment_flow): + """ + Here we are validating that the activation requirement step is not + being returned in the requirements response when the waffle flag is active + """ + self.user.is_active = False + self.user.save() + course = self._create_course("verified") + response = self._get_page(payment_flow, course.id) + + # Confirm that ID and webcam requirements are displayed, + # and that activation requirement is hidden. + self._assert_requirements_displayed(response, [ + PayAndVerifyView.PHOTO_ID_REQ, + PayAndVerifyView.WEBCAM_REQ, + ]) + @ddt.data("verify_student_start_flow", "verify_student_begin_flow") def test_no_contribution(self, payment_flow): # Do NOT specify a contribution for the course in a session var. diff --git a/lms/djangoapps/verify_student/views.py b/lms/djangoapps/verify_student/views.py index ca72ea3ea54cebb20706f9a015efa1d738609b85..c1351d28d448e7797e9ac96f12fa22bc676f1451 100644 --- a/lms/djangoapps/verify_student/views.py +++ b/lms/djangoapps/verify_student/views.py @@ -11,6 +11,7 @@ from ipware.ip import get_ip from django.conf import settings from django.contrib.auth.decorators import login_required +from django.contrib.staticfiles.storage import staticfiles_storage from django.core.mail import send_mail from django.core.urlresolvers import reverse from django.db import transaction @@ -26,6 +27,7 @@ import analytics from eventtracking import tracker from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey +import waffle from commerce.utils import EcommerceService from course_modes.models import CourseMode @@ -52,11 +54,11 @@ from lms.djangoapps.verify_student.image import decode_image_data, InvalidImageD from util.json_request import JsonResponse from util.db import outer_atomic from xmodule.modulestore.django import modulestore -from django.contrib.staticfiles.storage import staticfiles_storage - log = logging.getLogger(__name__) +DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH = 'verify_student_disable_account_activation_requirement' + class PayAndVerifyView(View): """ @@ -195,6 +197,19 @@ class PayAndVerifyView(View): VERIFICATION_DEADLINE = "verification" UPGRADE_DEADLINE = "upgrade" + def _get_user_active_status(self, user): + """ + Returns the user's active status to the caller + Overrides the actual value if account activation has been disabled via waffle switch + + Arguments: + user (User): Current user involved in the onboarding/verification flow + """ + user_is_active = user.is_active + if waffle.switch_is_active(DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH): + user_is_active = True + return user_is_active + @method_decorator(login_required) def get( self, request, course_id, @@ -348,7 +363,11 @@ class PayAndVerifyView(View): already_paid, relevant_course_mode ) - requirements = self._requirements(display_steps, request.user.is_active) + + # Override the actual value if account activation has been disabled + # Also see the reference to this parameter in context dictionary further down + user_is_active = self._get_user_active_status(request.user) + requirements = self._requirements(display_steps, user_is_active) if current_step is None: current_step = display_steps[0]['name'] @@ -408,7 +427,7 @@ class PayAndVerifyView(View): 'current_step': current_step, 'disable_courseware_js': True, 'display_steps': display_steps, - 'is_active': json.dumps(request.user.is_active), + 'is_active': json.dumps(user_is_active), 'user_email': request.user.email, 'message_key': message, 'platform_name': configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME), @@ -486,7 +505,7 @@ class PayAndVerifyView(View): else: url = reverse('verify_student_start_flow', kwargs=course_kwargs) - if user_is_trying_to_pay and user.is_active and not already_paid: + if user_is_trying_to_pay and self._get_user_active_status(user) and not already_paid: # If the user is trying to pay, has activated their account, and the ecommerce service # is enabled redirect him to the ecommerce checkout page. ecommerce_service = EcommerceService() @@ -594,6 +613,10 @@ class PayAndVerifyView(View): self.WEBCAM_REQ: False, } + # Remove the account activation requirement if disabled via waffle + if waffle.switch_is_active(DISABLE_ACCOUNT_ACTIVATION_REQUIREMENT_SWITCH): + all_requirements.pop(self.ACCOUNT_ACTIVATION_REQ) + display_steps = set(step['name'] for step in display_steps) for step, step_requirements in self.STEP_REQUIREMENTS.iteritems():