Merge pull request #6079 from edx/sanchez/logistration-opt-in
Hooking the logistration page into the new HTTP endpoint for email opt in
This commit is contained in:
@@ -14,10 +14,12 @@ from unittest import SkipTest, skipUnless
|
||||
import ddt
|
||||
from pytz import UTC
|
||||
import mock
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
from user_api.api import account as account_api, profile as profile_api
|
||||
|
||||
from student.tests.factories import UserFactory
|
||||
from user_api.models import UserOrgTag
|
||||
from user_api.tests.factories import UserPreferenceFactory
|
||||
from django_comment_common import models
|
||||
from opaque_keys.edx.locations import SlashSeparatedCourseKey
|
||||
@@ -1468,3 +1470,59 @@ class RegistrationViewTest(ApiTestCase):
|
||||
# Verify that the form description matches what we'd expect
|
||||
form_desc = json.loads(response.content)
|
||||
self.assertIn(expected_field, form_desc["fields"])
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class UpdateEmailOptInTestCase(ApiTestCase):
|
||||
"""Tests the UpdateEmailOptInPreference view. """
|
||||
|
||||
USERNAME = "steve"
|
||||
EMAIL = "steve@isawesome.com"
|
||||
PASSWORD = "steveopolis"
|
||||
|
||||
def setUp(self):
|
||||
""" Create a course and user, then log in. """
|
||||
super(UpdateEmailOptInTestCase, self).setUp()
|
||||
self.course = CourseFactory.create()
|
||||
self.user = UserFactory.create(username=self.USERNAME, email=self.EMAIL, password=self.PASSWORD)
|
||||
self.client.login(username=self.USERNAME, password=self.PASSWORD)
|
||||
self.url = reverse("preferences_email_opt_in")
|
||||
|
||||
@ddt.data(
|
||||
(u"True", u"True"),
|
||||
(u"true", u"True"),
|
||||
(u"TrUe", u"True"),
|
||||
(u"Banana", u"False"),
|
||||
(u"strawberries", u"False"),
|
||||
(u"False", u"False"),
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_update_email_opt_in(self, opt, result):
|
||||
"""Tests the email opt in preference"""
|
||||
# Register, which should trigger an activation email
|
||||
response = self.client.post(self.url, {
|
||||
"course_id": unicode(self.course.id),
|
||||
"email_opt_in": opt
|
||||
})
|
||||
self.assertHttpOK(response)
|
||||
preference = UserOrgTag.objects.get(
|
||||
user=self.user, org=self.course.id.org, key="email-optin"
|
||||
)
|
||||
self.assertEquals(preference.value, result)
|
||||
|
||||
@ddt.data(
|
||||
(True, False),
|
||||
(False, True),
|
||||
(False, False)
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_update_email_opt_in_wrong_params(self, use_course_id, use_opt_in):
|
||||
"""Tests the email opt in preference"""
|
||||
params = {}
|
||||
if use_course_id:
|
||||
params["course_id"] = unicode(self.course.id)
|
||||
if use_opt_in:
|
||||
params["email_opt_in"] = u"True"
|
||||
|
||||
response = self.client.post(self.url, params)
|
||||
self.assertHttpBadRequest(response)
|
||||
|
||||
@@ -20,6 +20,12 @@ urlpatterns = patterns(
|
||||
r'^v1/forum_roles/(?P<name>[a-zA-Z]+)/users/$',
|
||||
user_api_views.ForumRoleUsersListView.as_view()
|
||||
),
|
||||
|
||||
url(
|
||||
r'^v1/preferences/email_opt_in/$',
|
||||
user_api_views.UpdateEmailOptInPreference.as_view(),
|
||||
name="preferences_email_opt_in"
|
||||
),
|
||||
)
|
||||
|
||||
if settings.FEATURES.get('ENABLE_COMBINED_LOGIN_REGISTRATION'):
|
||||
|
||||
@@ -9,10 +9,12 @@ from django.core.exceptions import ImproperlyConfigured
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect
|
||||
from opaque_keys.edx import locator
|
||||
from rest_framework import authentication
|
||||
from rest_framework import filters
|
||||
from rest_framework import generics
|
||||
from rest_framework import permissions
|
||||
from rest_framework import status
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.exceptions import ParseError
|
||||
@@ -836,3 +838,32 @@ class PreferenceUsersListView(generics.ListAPIView):
|
||||
|
||||
def get_queryset(self):
|
||||
return User.objects.filter(preferences__key=self.kwargs["pref_key"]).prefetch_related("preferences")
|
||||
|
||||
|
||||
class UpdateEmailOptInPreference(APIView):
|
||||
"""View for updating the email opt in preference. """
|
||||
authentication_classes = (authentication.SessionAuthentication,)
|
||||
|
||||
@method_decorator(require_post_params(["course_id", "email_opt_in"]))
|
||||
@method_decorator(ensure_csrf_cookie)
|
||||
def post(self, request):
|
||||
""" Post function for updating the email opt in preference.
|
||||
|
||||
Allows the modification or creation of the email opt in preference at an
|
||||
organizational level.
|
||||
|
||||
Args:
|
||||
request (Request): The request should contain the following POST parameters:
|
||||
* course_id: The slash separated course ID. Used to determine the organization
|
||||
for this preference setting.
|
||||
* email_opt_in: "True" or "False" to determine if the user is opting in for emails from
|
||||
this organization. If the string does not match "True" (case insensitive) it will
|
||||
assume False.
|
||||
|
||||
"""
|
||||
course_id = request.DATA['course_id']
|
||||
org = locator.CourseLocator.from_string(course_id).org
|
||||
# Only check for true. All other values are False.
|
||||
email_opt_in = request.DATA['email_opt_in'].lower() == 'true'
|
||||
profile_api.update_email_opt_in(request.user, org, email_opt_in)
|
||||
return HttpResponse(status=status.HTTP_200_OK)
|
||||
|
||||
@@ -1046,6 +1046,7 @@ student_account_js = [
|
||||
'js/utils/edx.utils.validate.js',
|
||||
'js/src/utility.js',
|
||||
'js/student_account/enrollment.js',
|
||||
'js/student_account/emailoptin.js',
|
||||
'js/student_account/shoppingcart.js',
|
||||
'js/student_account/models/LoginModel.js',
|
||||
'js/student_account/models/RegisterModel.js',
|
||||
|
||||
@@ -293,6 +293,10 @@
|
||||
exports: 'edx.student.account.EnrollmentInterface',
|
||||
deps: ['jquery', 'jquery.cookie']
|
||||
},
|
||||
'js/student_account/emailoptin': {
|
||||
exports: 'edx.student.account.EmailOptInInterface',
|
||||
deps: ['jquery', 'jquery.cookie']
|
||||
},
|
||||
'js/student_account/shoppingcart': {
|
||||
exports: 'edx.student.account.ShoppingCartInterface',
|
||||
deps: ['jquery', 'jquery.cookie', 'underscore']
|
||||
@@ -362,6 +366,7 @@
|
||||
'js/student_account/models/PasswordResetModel',
|
||||
'js/student_account/models/RegisterModel',
|
||||
'js/student_account/views/FormView',
|
||||
'js/student_account/emailoptin',
|
||||
'js/student_account/enrollment',
|
||||
'js/student_account/shoppingcart',
|
||||
]
|
||||
@@ -383,6 +388,7 @@
|
||||
'lms/include/js/spec/student_account/register_spec.js',
|
||||
'lms/include/js/spec/student_account/password_reset_spec.js',
|
||||
'lms/include/js/spec/student_account/enrollment_spec.js',
|
||||
'lms/include/js/spec/student_account/emailoptin_spec.js',
|
||||
'lms/include/js/spec/student_account/shoppingcart_spec.js',
|
||||
'lms/include/js/spec/student_profile/profile_spec.js'
|
||||
]);
|
||||
|
||||
@@ -5,7 +5,8 @@ define([
|
||||
'js/student_account/views/AccessView',
|
||||
'js/student_account/views/FormView',
|
||||
'js/student_account/enrollment',
|
||||
'js/student_account/shoppingcart'
|
||||
'js/student_account/shoppingcart',
|
||||
'js/student_account/emailoptin'
|
||||
], function($, TemplateHelpers, AjaxHelpers, AccessView, FormView, EnrollmentInterface, ShoppingCartInterface) {
|
||||
describe('edx.student.account.AccessView', function() {
|
||||
'use strict';
|
||||
|
||||
28
lms/static/js/spec/student_account/emailoptin_spec.js
Normal file
28
lms/static/js/spec/student_account/emailoptin_spec.js
Normal file
@@ -0,0 +1,28 @@
|
||||
define(['js/common_helpers/ajax_helpers', 'js/student_account/emailoptin'],
|
||||
function( AjaxHelpers, EmailOptInInterface ) {
|
||||
'use strict';
|
||||
|
||||
describe( 'edx.student.account.EmailOptInInterface', function() {
|
||||
|
||||
var COURSE_KEY = 'edX/DemoX/Fall',
|
||||
EMAIL_OPT_IN = 'True',
|
||||
EMAIL_OPT_IN_URL = '/user_api/v1/preferences/email_opt_in/';
|
||||
|
||||
it('Opts in for organization emails', function() {
|
||||
// Spy on Ajax requests
|
||||
var requests = AjaxHelpers.requests( this );
|
||||
|
||||
// Attempt to enroll the user
|
||||
EmailOptInInterface.setPreference( COURSE_KEY, EMAIL_OPT_IN );
|
||||
|
||||
// Expect that the correct request was made to the server
|
||||
AjaxHelpers.expectRequest(
|
||||
requests, 'POST', EMAIL_OPT_IN_URL, 'course_id=edX%2FDemoX%2FFall&email_opt_in=True'
|
||||
);
|
||||
|
||||
// Simulate a successful response from the server
|
||||
AjaxHelpers.respondWithJson(requests, {});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
35
lms/static/js/student_account/emailoptin.js
Normal file
35
lms/static/js/student_account/emailoptin.js
Normal file
@@ -0,0 +1,35 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
edx.student.account.EmailOptInInterface = {
|
||||
|
||||
urls: {
|
||||
emailOptInUrl: '/user_api/v1/preferences/email_opt_in/'
|
||||
},
|
||||
|
||||
headers: {
|
||||
'X-CSRFToken': $.cookie('csrftoken')
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the email opt in setting for the organization associated
|
||||
* with this course.
|
||||
* @param {string} courseKey Slash-separated course key.
|
||||
* @param {string} emailOptIn The preference to opt in or out of organization emails.
|
||||
*/
|
||||
setPreference: function( courseKey, emailOptIn, context ) {
|
||||
return $.ajax({
|
||||
url: this.urls.emailOptInUrl,
|
||||
type: 'POST',
|
||||
data: {course_id: courseKey, email_opt_in: emailOptIn},
|
||||
headers: this.headers,
|
||||
context: context
|
||||
});
|
||||
}
|
||||
};
|
||||
})(jQuery);
|
||||
@@ -170,6 +170,33 @@ var edx = edx || {};
|
||||
* Once authentication has completed successfully, a user may need to:
|
||||
*
|
||||
* - Enroll in a course.
|
||||
* - Update email opt-in preferences
|
||||
*
|
||||
* These actions are delegated from the authComplete function to additional
|
||||
* functions requiring authentication.
|
||||
*
|
||||
*/
|
||||
authComplete: function() {
|
||||
var emailOptIn = edx.student.account.EmailOptInInterface,
|
||||
queryParams = this.queryParams();
|
||||
|
||||
// Set the email opt in preference.
|
||||
if (!_.isUndefined(queryParams.emailOptIn) && queryParams.enrollmentAction) {
|
||||
emailOptIn.setPreference(
|
||||
decodeURIComponent(queryParams.courseId),
|
||||
queryParams.emailOptIn,
|
||||
this
|
||||
).always(this.enrollment);
|
||||
} else {
|
||||
this.enrollment();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Designed to be invoked after authentication has completed. This function enrolls
|
||||
* the student as requested.
|
||||
*
|
||||
* - Enroll in a course.
|
||||
* - Add a course to the shopping cart.
|
||||
* - Be redirected to the dashboard / track selection page / shopping cart.
|
||||
*
|
||||
@@ -191,7 +218,7 @@ var edx = edx || {};
|
||||
* ?course_id: The slash-separated course ID to enroll in or add to the cart.
|
||||
*
|
||||
*/
|
||||
authComplete: function() {
|
||||
enrollment: function() {
|
||||
var enrollment = edx.student.account.EnrollmentInterface,
|
||||
shoppingcart = edx.student.account.ShoppingCartInterface,
|
||||
redirectUrl = '/dashboard',
|
||||
@@ -248,7 +275,8 @@ var edx = edx || {};
|
||||
return {
|
||||
next: $.url( '?next' ),
|
||||
enrollmentAction: $.url( '?enrollment_action' ),
|
||||
courseId: $.url( '?course_id' )
|
||||
courseId: $.url( '?course_id' ),
|
||||
emailOptIn: $.url( '?email_opt_in')
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user