diff --git a/cms/djangoapps/contentstore/views/public.py b/cms/djangoapps/contentstore/views/public.py
index 50ceee25a9..c850afaa58 100644
--- a/cms/djangoapps/contentstore/views/public.py
+++ b/cms/djangoapps/contentstore/views/public.py
@@ -10,7 +10,6 @@ from django.views.decorators.clickjacking import xframe_options_deny
from django.views.decorators.csrf import ensure_csrf_cookie
from edxmako.shortcuts import render_to_response
-from openedx.core.djangoapps.external_auth.views import redirect_with_get, ssl_get_cert_from_request, ssl_login_shortcut
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from waffle.decorators import waffle_switch
from contentstore.config import waffle
@@ -27,15 +26,10 @@ def signup(request):
csrf_token = csrf(request)['csrf_token']
if request.user.is_authenticated:
return redirect('/course/')
- if settings.FEATURES.get('AUTH_USE_CERTIFICATES_IMMEDIATE_SIGNUP'):
- # Redirect to course to login to process their certificate if SSL is enabled
- # and registration is disabled.
- return redirect_with_get('login', request.GET, False)
return render_to_response('register.html', {'csrf': csrf_token})
-@ssl_login_shortcut
@ensure_csrf_cookie
@xframe_options_deny
def login_page(request):
@@ -43,19 +37,6 @@ def login_page(request):
Display the login form.
"""
csrf_token = csrf(request)['csrf_token']
- if (settings.FEATURES['AUTH_USE_CERTIFICATES'] and
- ssl_get_cert_from_request(request)):
- # SSL login doesn't require a login view, so redirect
- # to course now that the user is authenticated via
- # the decorator.
- next_url = request.GET.get('next')
- if next_url:
- return redirect(next_url)
- else:
- return redirect('/course/')
- if settings.FEATURES.get('AUTH_USE_CAS'):
- # If CAS is enabled, redirect auth handling to there
- return redirect(reverse('cas-login'))
return render_to_response(
'login.html',
diff --git a/cms/envs/aws.py b/cms/envs/aws.py
index 14e76e83fa..e0c9d9526b 100644
--- a/cms/envs/aws.py
+++ b/cms/envs/aws.py
@@ -273,26 +273,6 @@ HEARTBEAT_CHECKS = ENV_TOKENS.get('HEARTBEAT_CHECKS', HEARTBEAT_CHECKS)
HEARTBEAT_EXTENDED_CHECKS = ENV_TOKENS.get('HEARTBEAT_EXTENDED_CHECKS', HEARTBEAT_EXTENDED_CHECKS)
HEARTBEAT_CELERY_TIMEOUT = ENV_TOKENS.get('HEARTBEAT_CELERY_TIMEOUT', HEARTBEAT_CELERY_TIMEOUT)
-# Django CAS external authentication settings
-CAS_EXTRA_LOGIN_PARAMS = ENV_TOKENS.get("CAS_EXTRA_LOGIN_PARAMS", None)
-if FEATURES.get('AUTH_USE_CAS'):
- CAS_SERVER_URL = ENV_TOKENS.get("CAS_SERVER_URL", None)
- AUTHENTICATION_BACKENDS = [
- 'django.contrib.auth.backends.ModelBackend',
- 'django_cas.backends.CASBackend',
- ]
-
- INSTALLED_APPS.append('django_cas')
-
- MIDDLEWARE_CLASSES.append('django_cas.middleware.CASMiddleware')
- CAS_ATTRIBUTE_CALLBACK = ENV_TOKENS.get('CAS_ATTRIBUTE_CALLBACK', None)
- if CAS_ATTRIBUTE_CALLBACK:
- import importlib
- CAS_USER_DETAILS_RESOLVER = getattr(
- importlib.import_module(CAS_ATTRIBUTE_CALLBACK['module']),
- CAS_ATTRIBUTE_CALLBACK['function']
- )
-
# Specific setting for the File Upload Service to store media in a bucket.
FILE_UPLOAD_STORAGE_BUCKET_NAME = ENV_TOKENS.get('FILE_UPLOAD_STORAGE_BUCKET_NAME', FILE_UPLOAD_STORAGE_BUCKET_NAME)
FILE_UPLOAD_STORAGE_PREFIX = ENV_TOKENS.get('FILE_UPLOAD_STORAGE_PREFIX', FILE_UPLOAD_STORAGE_PREFIX)
diff --git a/cms/envs/common.py b/cms/envs/common.py
index 6204937f1f..43ddc34150 100644
--- a/cms/envs/common.py
+++ b/cms/envs/common.py
@@ -182,8 +182,6 @@ FEATURES = {
# Doing so will cause all courses to be released on production
'DISABLE_START_DATES': False, # When True, all courses will be active, regardless of start date
- 'AUTH_USE_CERTIFICATES': False,
-
# email address for studio staff (eg to request course creation)
'STUDIO_REQUEST_EMAIL': '',
@@ -1026,7 +1024,6 @@ INSTALLED_APPS = [
'openedx.core.djangoapps.contentserver',
'course_creators',
- 'openedx.core.djangoapps.external_auth',
'student.apps.StudentConfig', # misleading name due to sharing with lms
'openedx.core.djangoapps.course_groups', # not used in cms (yet), but tests run
'xblock_config.apps.XBlockConfig',
diff --git a/cms/envs/production.py b/cms/envs/production.py
index 9d1b70362d..86f8c6dbb7 100644
--- a/cms/envs/production.py
+++ b/cms/envs/production.py
@@ -279,26 +279,6 @@ HEARTBEAT_CHECKS = ENV_TOKENS.get('HEARTBEAT_CHECKS', HEARTBEAT_CHECKS)
HEARTBEAT_EXTENDED_CHECKS = ENV_TOKENS.get('HEARTBEAT_EXTENDED_CHECKS', HEARTBEAT_EXTENDED_CHECKS)
HEARTBEAT_CELERY_TIMEOUT = ENV_TOKENS.get('HEARTBEAT_CELERY_TIMEOUT', HEARTBEAT_CELERY_TIMEOUT)
-# Django CAS external authentication settings
-CAS_EXTRA_LOGIN_PARAMS = ENV_TOKENS.get("CAS_EXTRA_LOGIN_PARAMS", None)
-if FEATURES.get('AUTH_USE_CAS'):
- CAS_SERVER_URL = ENV_TOKENS.get("CAS_SERVER_URL", None)
- AUTHENTICATION_BACKENDS = [
- 'django.contrib.auth.backends.ModelBackend',
- 'django_cas.backends.CASBackend',
- ]
-
- INSTALLED_APPS.append('django_cas')
-
- MIDDLEWARE_CLASSES.append('django_cas.middleware.CASMiddleware')
- CAS_ATTRIBUTE_CALLBACK = ENV_TOKENS.get('CAS_ATTRIBUTE_CALLBACK', None)
- if CAS_ATTRIBUTE_CALLBACK:
- import importlib
- CAS_USER_DETAILS_RESOLVER = getattr(
- importlib.import_module(CAS_ATTRIBUTE_CALLBACK['module']),
- CAS_ATTRIBUTE_CALLBACK['function']
- )
-
# Specific setting for the File Upload Service to store media in a bucket.
FILE_UPLOAD_STORAGE_BUCKET_NAME = ENV_TOKENS.get('FILE_UPLOAD_STORAGE_BUCKET_NAME', FILE_UPLOAD_STORAGE_BUCKET_NAME)
FILE_UPLOAD_STORAGE_PREFIX = ENV_TOKENS.get('FILE_UPLOAD_STORAGE_PREFIX', FILE_UPLOAD_STORAGE_PREFIX)
diff --git a/cms/urls.py b/cms/urls.py
index 812e12d86b..04edae7027 100644
--- a/cms/urls.py
+++ b/cms/urls.py
@@ -9,7 +9,6 @@ import contentstore.views
from cms.djangoapps.contentstore.views.organization import OrganizationListView
import openedx.core.djangoapps.common_views.xblock
import openedx.core.djangoapps.debug.views
-import openedx.core.djangoapps.external_auth.views
import openedx.core.djangoapps.lang_pref.views
from openedx.core.djangoapps.password_policy import compliance as password_policy_compliance
from openedx.core.djangoapps.password_policy.forms import PasswordPolicyAwareAdminAuthForm
@@ -199,13 +198,6 @@ if settings.FEATURES.get('ENABLE_EXPORT_GIT'):
if settings.FEATURES.get('ENABLE_SERVICE_STATUS'):
urlpatterns.append(url(r'^status/', include('openedx.core.djangoapps.service_status.urls')))
-if settings.FEATURES.get('AUTH_USE_CAS'):
- import django_cas.views
-
- urlpatterns += [
- url(r'^cas-auth/login/$', openedx.core.djangoapps.external_auth.views.cas_login, name="cas-login"),
- url(r'^cas-auth/logout/$', django_cas.views.logout, {'next_page': '/'}, name="cas-logout"),
- ]
# The password pages in the admin tool are disabled so that all password
# changes go through our user portal and follow complexity requirements.
urlpatterns.append(url(r'^admin/password_change/$', handler404))
diff --git a/common/djangoapps/student/tests/test_password_policy.py b/common/djangoapps/student/tests/test_password_policy.py
index 7b4d015165..8a93ae3949 100644
--- a/common/djangoapps/student/tests/test_password_policy.py
+++ b/common/djangoapps/student/tests/test_password_policy.py
@@ -3,9 +3,7 @@
This test file will verify proper password policy enforcement, which is an option feature
"""
import json
-from importlib import import_module
-from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.urls import reverse
from django.test import TestCase
@@ -13,7 +11,6 @@ from django.test.client import RequestFactory
from django.test.utils import override_settings
from mock import patch
-from openedx.core.djangoapps.external_auth.models import ExternalAuthMap
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
from openedx.core.djangoapps.user_authn.views.deprecated import create_account
from util.password_policy_validators import create_validator_config
@@ -254,31 +251,6 @@ class TestPasswordPolicy(TestCase):
obj = json.loads(response.content)
self.assertTrue(obj['success'])
- @override_settings(AUTH_PASSWORD_VALIDATORS=[
- create_validator_config('util.password_policy_validators.MinimumLengthValidator', {'min_length': 6})
- ], SESSION_ENGINE='django.contrib.sessions.backends.cache')
- def test_ext_auth_password_length_too_short(self):
- """
- Tests that even if password policy is enforced, ext_auth registrations aren't subject to it
- """
- self.url_params['password'] = u'aaa' # shouldn't pass validation
- request = self.request_factory.post(self.url, self.url_params)
- request.site = SiteFactory.create()
- # now indicate we are doing ext_auth by setting 'ExternalAuthMap' in the session.
- request.session = import_module(settings.SESSION_ENGINE).SessionStore() # empty session
- extauth = ExternalAuthMap(external_id='withmap@stanford.edu',
- external_email='withmap@stanford.edu',
- internal_password=self.url_params['password'],
- external_domain='shib:https://idp.stanford.edu/')
- request.session['ExternalAuthMap'] = extauth
- request.user = AnonymousUser()
-
- with patch('edxmako.request_context.get_current_request', return_value=request):
- response = create_account(request)
- self.assertEqual(response.status_code, 200)
- obj = json.loads(response.content)
- self.assertTrue(obj['success'])
-
class TestUsernamePasswordNonmatch(TestCase):
"""
diff --git a/common/djangoapps/student/views/management.py b/common/djangoapps/student/views/management.py
index c07b57fbb1..d1c4d12382 100644
--- a/common/djangoapps/student/views/management.py
+++ b/common/djangoapps/student/views/management.py
@@ -134,8 +134,7 @@ def index(request, extra_context=None, user=AnonymousUser()):
"""
Render the edX main page.
- extra_context is used to allow immediate display of certain modal windows, eg signup,
- as used by external_auth.
+ extra_context is used to allow immediate display of certain modal windows, eg signup.
"""
if extra_context is None:
extra_context = {}
diff --git a/common/djangoapps/util/cache.py b/common/djangoapps/util/cache.py
index 7ee469d732..26ae2a6963 100644
--- a/common/djangoapps/util/cache.py
+++ b/common/djangoapps/util/cache.py
@@ -53,8 +53,7 @@ def cache_if_anonymous(*get_parameters):
# If that page is cached the authentication doesn't
# happen, so we disable the cache when that feature is enabled.
if (
- not request.user.is_authenticated and
- not settings.FEATURES['AUTH_USE_CERTIFICATES']
+ not request.user.is_authenticated
):
# Use the cache. The same view accessed through different domain names may
# return different things, so include the domain name in the key.
diff --git a/lms/djangoapps/branding/views.py b/lms/djangoapps/branding/views.py
index f9a7232963..d5cb206036 100644
--- a/lms/djangoapps/branding/views.py
+++ b/lms/djangoapps/branding/views.py
@@ -43,16 +43,6 @@ def index(request):
settings.FEATURES.get('ALWAYS_REDIRECT_HOMEPAGE_TO_DASHBOARD_FOR_AUTHENTICATED_USER', True)):
return redirect(reverse('dashboard'))
- if settings.FEATURES.get('AUTH_USE_CERTIFICATES'):
- from openedx.core.djangoapps.external_auth.views import ssl_login
- # Set next URL to dashboard if it isn't set to avoid
- # caching a redirect to / that causes a redirect loop on logout
- if not request.GET.get('next'):
- req_new = request.GET.copy()
- req_new['next'] = reverse('dashboard')
- request.GET = req_new
- return ssl_login(request)
-
enable_mktg_site = configuration_helpers.get_value(
'ENABLE_MKTG_SITE',
settings.FEATURES.get('ENABLE_MKTG_SITE', False)
diff --git a/lms/djangoapps/courseware/access.py b/lms/djangoapps/courseware/access.py
index 6626e9ced7..ccdac8abc3 100644
--- a/lms/djangoapps/courseware/access.py
+++ b/lms/djangoapps/courseware/access.py
@@ -43,7 +43,6 @@ from lms.djangoapps.ccx.custom_exception import CCXLocatorValidationException
from lms.djangoapps.ccx.models import CustomCourseForEdX
from mobile_api.models import IgnoreMobileAvailableFlagConfig
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
-from openedx.core.djangoapps.external_auth.models import ExternalAuthMap
from openedx.features.course_duration_limits.access import check_course_expired
from student import auth
from student.models import CourseEnrollmentAllowed
@@ -248,22 +247,10 @@ def _can_enroll_courselike(user, courselike):
Returns:
AccessResponse, indicating whether the user can enroll.
"""
- enrollment_domain = courselike.enrollment_domain
# Courselike objects (e.g., course descriptors and CourseOverviews) have an attribute named `id`
# which actually points to a CourseKey. Sigh.
course_key = courselike.id
- # If using a registration method to restrict enrollment (e.g., Shibboleth)
- if settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and enrollment_domain:
- if user is not None and user.is_authenticated and \
- ExternalAuthMap.objects.filter(user=user, external_domain=enrollment_domain):
- debug("Allow: external_auth of " + enrollment_domain)
- reg_method_ok = True
- else:
- reg_method_ok = False
- else:
- reg_method_ok = True
-
# If the user appears in CourseEnrollmentAllowed paired with the given course key,
# they may enroll, except if the CEA has already been used by a different user.
# Note that as dictated by the legacy database schema, the filter call includes
@@ -289,7 +276,7 @@ def _can_enroll_courselike(user, courselike):
now = datetime.now(UTC)
enrollment_start = courselike.enrollment_start or datetime.min.replace(tzinfo=UTC)
enrollment_end = courselike.enrollment_end or datetime.max.replace(tzinfo=UTC)
- if reg_method_ok and enrollment_start < now < enrollment_end:
+ if enrollment_start < now < enrollment_end:
debug("Allow: in enrollment period")
return ACCESS_GRANTED
diff --git a/lms/djangoapps/courseware/tests/test_about.py b/lms/djangoapps/courseware/tests/test_about.py
index 1f6a483c63..92032597e3 100644
--- a/lms/djangoapps/courseware/tests/test_about.py
+++ b/lms/djangoapps/courseware/tests/test_about.py
@@ -390,46 +390,6 @@ class AboutWithInvitationOnly(SharedModuleStoreTestCase):
self.assertIn(REG_STR, resp.content)
-@patch.dict(settings.FEATURES, {'RESTRICT_ENROLL_BY_REG_METHOD': True})
-class AboutTestCaseShibCourse(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
- """
- Test cases covering about page behavior for courses that use shib enrollment domain ("shib courses")
- """
- @classmethod
- def setUpClass(cls):
- super(AboutTestCaseShibCourse, cls).setUpClass()
- cls.course = CourseFactory.create(enrollment_domain="shib:https://idp.stanford.edu/")
- cls.about = ItemFactory.create(
- category="about", parent_location=cls.course.location,
- data="OOGIE BLOOGIE", display_name="overview"
- )
-
- def test_logged_in_shib_course(self):
- """
- For shib courses, logged in users will see the enroll button, but get rejected once they click there
- """
- self.setup_user()
- url = reverse('about_course', args=[text_type(self.course.id)])
- resp = self.client.get(url)
- self.assertEqual(resp.status_code, 200)
- self.assertIn("OOGIE BLOOGIE", resp.content)
- self.assertIn(u"Enroll in {}".format(self.course.id.course), resp.content.decode('utf-8'))
- self.assertIn(SHIB_ERROR_STR, resp.content)
- self.assertIn(REG_STR, resp.content)
-
- def test_anonymous_user_shib_course(self):
- """
- For shib courses, anonymous users will also see the enroll button
- """
- url = reverse('about_course', args=[text_type(self.course.id)])
- resp = self.client.get(url)
- self.assertEqual(resp.status_code, 200)
- self.assertIn("OOGIE BLOOGIE", resp.content)
- self.assertIn(u"Enroll in {}".format(self.course.id.course), resp.content.decode('utf-8'))
- self.assertIn(SHIB_ERROR_STR, resp.content)
- self.assertIn(REG_STR, resp.content)
-
-
class AboutWithClosedEnrollment(ModuleStoreTestCase):
"""
This test case will check the About page for a course that has enrollment start/end
diff --git a/lms/djangoapps/dashboard/management/commands/tests/test_git_add_course.py b/lms/djangoapps/dashboard/management/commands/tests/test_git_add_course.py
index 2954bee812..7b03f3eb21 100644
--- a/lms/djangoapps/dashboard/management/commands/tests/test_git_add_course.py
+++ b/lms/djangoapps/dashboard/management/commands/tests/test_git_add_course.py
@@ -37,9 +37,6 @@ TEST_MONGODB_LOG = {
'db': 'test_xlog',
}
-FEATURES_WITH_SSL_AUTH = settings.FEATURES.copy()
-FEATURES_WITH_SSL_AUTH['AUTH_USE_CERTIFICATES'] = True
-
@override_settings(
MONGODB_LOG=TEST_MONGODB_LOG,
diff --git a/lms/djangoapps/dashboard/sysadmin.py b/lms/djangoapps/dashboard/sysadmin.py
index e42a9ac6de..abf1a466fb 100644
--- a/lms/djangoapps/dashboard/sysadmin.py
+++ b/lms/djangoapps/dashboard/sysadmin.py
@@ -12,14 +12,11 @@ import subprocess
import mongoengine
from django.conf import settings
-from django.contrib.auth import authenticate
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
-from django.core.exceptions import PermissionDenied
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.db import IntegrityError
from django.http import Http404, HttpResponse
-from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.html import escape
from django.utils.translation import ugettext as _
@@ -37,8 +34,6 @@ from courseware.courses import get_course_by_id
from dashboard.git_import import GitImportError
from dashboard.models import CourseImportLog
from edxmako.shortcuts import render_to_response
-from openedx.core.djangoapps.external_auth.models import ExternalAuthMap
-from openedx.core.djangoapps.user_api.accounts.utils import generate_password
from openedx.core.djangolib.markup import HTML
from student.models import CourseEnrollment, Registration, UserProfile
from student.roles import CourseInstructorRole, CourseStaffRole
@@ -115,82 +110,24 @@ class Users(SysadminDashboardView):
courses loaded, and user statistics
"""
- def fix_external_auth_map_passwords(self):
- """
- This corrects any passwords that have drifted from eamap to
- internal django auth. Needs to be removed when fixed in external_auth
- """
-
- msg = ''
- for eamap in ExternalAuthMap.objects.all():
- euser = eamap.user
- epass = eamap.internal_password
- if euser is None:
- continue
- try:
- testuser = authenticate(username=euser.username, password=epass)
- except (TypeError, PermissionDenied, AttributeError) as err:
- # Translators: This message means that the user could not be authenticated (that is, we could
- # not log them in for some reason - maybe they don't have permission, or their password was wrong)
- msg += _(u'Failed in authenticating {username}, error {error}\n').format(
- username=euser,
- error=err
- )
- continue
- if testuser is None:
- # Translators: This message means that the user could not be authenticated (that is, we could
- # not log them in for some reason - maybe they don't have permission, or their password was wrong)
- msg += _(u'Failed in authenticating {username}\n').format(username=euser)
- # Translators: this means that the password has been corrected (sometimes the database needs to be resynchronized)
- # Translate this as meaning "the password was fixed" or "the password was corrected".
- msg += _('fixed password')
- euser.set_password(epass)
- euser.save()
- continue
- if not msg:
- # Translators: this means everything happened successfully, yay!
- msg = _('All ok!')
- return msg
-
def create_user(self, uname, name, password=None):
- """ Creates a user (both SSL and regular)"""
+ """ Creates a user """
if not uname:
return _('Must provide username')
if not name:
return _('Must provide full name')
- email_domain = getattr(settings, 'SSL_AUTH_EMAIL_DOMAIN', 'MIT.EDU')
-
msg = u''
- if settings.FEATURES['AUTH_USE_CERTIFICATES']:
- if '@' not in uname:
- email = '{0}@{1}'.format(uname, email_domain)
- else:
- email = uname
- if not email.endswith('@{0}'.format(email_domain)):
- # Translators: Domain is an email domain, such as "@gmail.com"
- msg += _(u'Email address must end in {domain}').format(domain="@{0}".format(email_domain))
- return msg
- mit_domain = 'ssl:MIT'
- if ExternalAuthMap.objects.filter(external_id=email,
- external_domain=mit_domain):
- msg += _(u'Failed - email {email_addr} already exists as {external_id}').format(
- email_addr=email,
- external_id="external_id"
- )
- return msg
- new_password = generate_password()
- else:
- if not password:
- return _('Password must be supplied if not using certificates')
+ if not password:
+ return _('Password must be supplied')
- email = uname
+ email = uname
- if '@' not in email:
- msg += _('email address required (not username)')
- return msg
- new_password = password
+ 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)
@@ -210,22 +147,6 @@ class Users(SysadminDashboardView):
profile.name = name
profile.save()
- if settings.FEATURES['AUTH_USE_CERTIFICATES']:
- credential_string = getattr(settings, 'SSL_AUTH_DN_FORMAT_STRING',
- '/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}')
- credentials = credential_string.format(name, email)
- eamap = ExternalAuthMap(
- external_id=email,
- external_email=email,
- external_domain=mit_domain,
- external_name=name,
- internal_password=new_password,
- external_credentials=json.dumps(credentials),
- )
- eamap.user = user
- eamap.dtsignup = timezone.now()
- eamap.save()
-
msg += _(u'User {user} created successfully!').format(user=user)
return msg
@@ -303,12 +224,6 @@ class Users(SysadminDashboardView):
(User.objects.all().iterator()))
return self.return_csv('users_{0}.csv'.format(
request.META['SERVER_NAME']), header, data)
- elif action == 'repair_eamap':
- self.msg = HTML(u'
{0}
{1}
{2}').format(
- _('Repair Results'),
- self.fix_external_auth_map_passwords(),
- self.msg)
- self.datatable = {}
elif action == 'create_user':
uname = request.POST.get('student_uname', '').strip()
name = request.POST.get('student_fullname', '').strip()
diff --git a/lms/djangoapps/dashboard/tests/test_sysadmin.py b/lms/djangoapps/dashboard/tests/test_sysadmin.py
index 1acf797b74..61ad286d43 100644
--- a/lms/djangoapps/dashboard/tests/test_sysadmin.py
+++ b/lms/djangoapps/dashboard/tests/test_sysadmin.py
@@ -21,6 +21,7 @@ from six import text_type
from dashboard.git_import import GitImportErrorNoDir
from dashboard.models import CourseImportLog
+from openedx.core.djangolib.markup import Text
from student.roles import CourseStaffRole, GlobalStaff
from student.tests.factories import UserFactory
from util.date_utils import DEFAULT_DATE_TIME_FORMAT, get_time_display
@@ -39,9 +40,6 @@ TEST_MONGODB_LOG = {
'db': 'test_xlog',
}
-FEATURES_WITH_SSL_AUTH = settings.FEATURES.copy()
-FEATURES_WITH_SSL_AUTH['AUTH_USE_CERTIFICATES'] = True
-
class SysadminBaseTestCase(SharedModuleStoreTestCase):
"""
@@ -156,7 +154,7 @@ class TestSysAdminMongoCourseImport(SysadminBaseTestCase):
# Create git loaded course
response = self._add_edx4edx()
- self.assertIn(escape(text_type(GitImportErrorNoDir(settings.GIT_REPO_DIR))),
+ self.assertIn(Text(text_type(GitImportErrorNoDir(settings.GIT_REPO_DIR))),
response.content.decode('UTF-8'))
def test_mongo_course_add_delete(self):
diff --git a/lms/envs/aws.py b/lms/envs/aws.py
index e4b75802d2..9d6bde5551 100644
--- a/lms/envs/aws.py
+++ b/lms/envs/aws.py
@@ -382,26 +382,6 @@ SSL_AUTH_DN_FORMAT_STRING = ENV_TOKENS.get(
u"/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}"
)
-# Django CAS external authentication settings
-CAS_EXTRA_LOGIN_PARAMS = ENV_TOKENS.get("CAS_EXTRA_LOGIN_PARAMS", None)
-if FEATURES.get('AUTH_USE_CAS'):
- CAS_SERVER_URL = ENV_TOKENS.get("CAS_SERVER_URL", None)
- AUTHENTICATION_BACKENDS = [
- 'django.contrib.auth.backends.ModelBackend',
- 'django_cas.backends.CASBackend',
- ]
-
- INSTALLED_APPS.append('django_cas')
-
- MIDDLEWARE_CLASSES.append('django_cas.middleware.CASMiddleware')
- CAS_ATTRIBUTE_CALLBACK = ENV_TOKENS.get('CAS_ATTRIBUTE_CALLBACK', None)
- if CAS_ATTRIBUTE_CALLBACK:
- import importlib
- CAS_USER_DETAILS_RESOLVER = getattr(
- importlib.import_module(CAS_ATTRIBUTE_CALLBACK['module']),
- CAS_ATTRIBUTE_CALLBACK['function']
- )
-
# Video Caching. Pairing country codes with CDN URLs.
# Example: {'CN': 'http://api.xuetangx.com/edx/video?s3_url='}
VIDEO_CDN_URL = ENV_TOKENS.get('VIDEO_CDN_URL', {})
diff --git a/lms/envs/common.py b/lms/envs/common.py
index 859fce1d93..b015946259 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -108,19 +108,6 @@ FEATURES = {
'DISABLE_LOGIN_BUTTON': False, # used in systems where login is automatic, eg MIT SSL
- # extrernal access methods
- 'AUTH_USE_OPENID': False,
- 'AUTH_USE_CERTIFICATES': False,
- 'AUTH_USE_OPENID_PROVIDER': False,
- # Even though external_auth is in common, shib assumes the LMS views / urls, so it should only be enabled
- # in LMS
- 'AUTH_USE_SHIB': False,
- 'AUTH_USE_CAS': False,
-
- # This flag disables the requirement of having to agree to the TOS for users registering
- # with Shib. Feature was requested by Stanford's office of general counsel
- 'SHIB_DISABLE_TOS': False,
-
# Toggles OAuth2 authentication provider
'ENABLE_OAUTH2_PROVIDER': False,
@@ -137,9 +124,6 @@ FEATURES = {
# Set to hide the courses list on the Learner Dashboard if they are not enrolled in any courses yet.
'HIDE_DASHBOARD_COURSES_UNTIL_ACTIVATED': False,
- # Enables ability to restrict enrollment in specific courses by the user account login method
- 'RESTRICT_ENROLL_BY_REG_METHOD': False,
-
# enable analytics server.
# WARNING: THIS SHOULD ALWAYS BE SET TO FALSE UNDER NORMAL
# LMS OPERATION. See analytics.py for details about what
@@ -2068,10 +2052,6 @@ INSTALLED_APPS = [
# Student support tools
'support',
- # External auth (OpenID, shib)
- 'openedx.core.djangoapps.external_auth',
- 'django_openid_auth',
-
# django-oauth2-provider (deprecated)
'provider',
'provider.oauth2',
@@ -2474,19 +2454,6 @@ if FEATURES.get('CLASS_DASHBOARD'):
ENABLE_CREDIT_ELIGIBILITY = True
FEATURES['ENABLE_CREDIT_ELIGIBILITY'] = ENABLE_CREDIT_ELIGIBILITY
-######################## CAS authentication ###########################
-
-if FEATURES.get('AUTH_USE_CAS'):
- CAS_SERVER_URL = 'https://provide_your_cas_url_here'
- AUTHENTICATION_BACKENDS = [
- 'django.contrib.auth.backends.ModelBackend',
- 'django_cas.backends.CASBackend',
- ]
-
- INSTALLED_APPS.append('django_cas')
-
- MIDDLEWARE_CLASSES.append('django_cas.middleware.CASMiddleware')
-
############# Cross-domain requests #################
if FEATURES.get('ENABLE_CORS_HEADERS'):
diff --git a/lms/envs/production.py b/lms/envs/production.py
index cc128c0f14..78935a190c 100644
--- a/lms/envs/production.py
+++ b/lms/envs/production.py
@@ -386,26 +386,6 @@ SSL_AUTH_DN_FORMAT_STRING = ENV_TOKENS.get(
u"/C=US/ST=Massachusetts/O=Massachusetts Institute of Technology/OU=Client CA v1/CN={0}/emailAddress={1}"
)
-# Django CAS external authentication settings
-CAS_EXTRA_LOGIN_PARAMS = ENV_TOKENS.get("CAS_EXTRA_LOGIN_PARAMS", None)
-if FEATURES.get('AUTH_USE_CAS'):
- CAS_SERVER_URL = ENV_TOKENS.get("CAS_SERVER_URL", None)
- AUTHENTICATION_BACKENDS = [
- 'django.contrib.auth.backends.ModelBackend',
- 'django_cas.backends.CASBackend',
- ]
-
- INSTALLED_APPS.append('django_cas')
-
- MIDDLEWARE_CLASSES.append('django_cas.middleware.CASMiddleware')
- CAS_ATTRIBUTE_CALLBACK = ENV_TOKENS.get('CAS_ATTRIBUTE_CALLBACK', None)
- if CAS_ATTRIBUTE_CALLBACK:
- import importlib
- CAS_USER_DETAILS_RESOLVER = getattr(
- importlib.import_module(CAS_ATTRIBUTE_CALLBACK['module']),
- CAS_ATTRIBUTE_CALLBACK['function']
- )
-
# Video Caching. Pairing country codes with CDN URLs.
# Example: {'CN': 'http://api.xuetangx.com/edx/video?s3_url='}
VIDEO_CDN_URL = ENV_TOKENS.get('VIDEO_CDN_URL', {})
diff --git a/lms/envs/test.py b/lms/envs/test.py
index 2d5caf4d29..120acfb57a 100644
--- a/lms/envs/test.py
+++ b/lms/envs/test.py
@@ -251,15 +251,6 @@ THIRD_PARTY_AUTH_CUSTOM_AUTH_FORMS = {
},
}
-################################## OPENID #####################################
-FEATURES['AUTH_USE_OPENID'] = True
-FEATURES['AUTH_USE_OPENID_PROVIDER'] = True
-
-################################## SHIB #######################################
-FEATURES['AUTH_USE_SHIB'] = True
-FEATURES['SHIB_DISABLE_TOS'] = True
-FEATURES['RESTRICT_ENROLL_BY_REG_METHOD'] = True
-
OPENID_CREATE_USERS = False
OPENID_UPDATE_DETAILS_FROM_SREG = True
OPENID_USE_AS_ADMIN_LOGIN = False
diff --git a/lms/templates/courseware/course_about.html b/lms/templates/courseware/course_about.html
index 6104d8fc03..3328baf1d2 100644
--- a/lms/templates/courseware/course_about.html
+++ b/lms/templates/courseware/course_about.html
@@ -1,4 +1,4 @@
-<%page expression_filter="h" />
+<%page expression_filter="h"/>
<%namespace name='static' file='../static_content.html'/>
<%!
from django.utils.translation import ugettext as _
@@ -8,8 +8,10 @@ from courseware.courses import get_course_about_section
from django.conf import settings
from six import text_type
from edxmako.shortcuts import marketing_link
+from openedx.core.djangolib.js_utils import js_escaped_string
from openedx.core.djangolib.markup import HTML, Text
from openedx.core.lib.courses import course_image_url
+
from six import string_types
%>
@@ -32,21 +34,21 @@ from six import string_types
% if can_add_course_to_cart:
add_course_complete_handler = function(jqXHR, textStatus) {
if (jqXHR.status == 200) {
- location.href = "${cart_link | n, decode.utf8}";
+ location.href = "${cart_link | n, js_escaped_string}";
}
if (jqXHR.status == 400) {
- $("#register_error").text(
- jqXHR.responseText ? jqXHR.responseText : "${_("An error occurred. Please try again later.") | n, decode.utf8}")
+ $("#register_error")
+ .text(jqXHR.responseText ? jqXHR.responseText : "${_("An error occurred. Please try again later.") | n, js_escaped_string}")
.css("display", "block");
}
else if (jqXHR.status == 403) {
- location.href = "${reg_then_add_to_cart_link | n, decode.utf8}";
+ location.href = "${reg_then_add_to_cart_link | n, js_escaped_string}";
}
};
$("#add_to_cart_post").click(function(event){
$.ajax({
- url: "${reverse('add_course_to_cart', args=[text_type(course.id)]) | n, decode.utf8}",
+ url: "${reverse('add_course_to_cart', args=[text_type(course.id)]) | n, js_escaped_string}",
type: "POST",
/* Rant: HAD TO USE COMPLETE B/C PROMISE.DONE FOR SOME REASON DOES NOT WORK ON THIS PAGE. */
complete: add_course_complete_handler
@@ -55,51 +57,21 @@ from six import string_types
});
% endif
- ## making the conditional around this entire JS block for sanity
- %if settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain:
- <%
- perms_error = Text(_('The currently logged-in user account does not have permission to enroll in this course. '
- 'You may need to {start_logout_tag}log out{end_tag} then try the enroll button again. '
- 'Please visit the {start_help_tag}help page{end_tag} for a possible solution.')).format(
- start_help_tag=HTML("").format(url=marketing_link('FAQ')), end_tag=HTML(''),
- start_logout_tag=HTML("").format(url=reverse('logout'))
- )
- %>
- $('#class_enroll_form').on('ajax:complete', function(event, xhr) {
- if(xhr.status == 200) {
- location.href = "${reverse('dashboard') | n, decode.utf8}";
- } else if (xhr.status == 403) {
- location.href = "${reverse('course-specific-register', args=[text_type(course.id)]) | n, decode.utf8 }?course_id=${course.id | n, decode.utf8 }&enrollment_action=enroll";
- } else if (xhr.status == 400) { //This means the user did not have permission
- $('#register_error').text("${perms_error | n, decode.utf8}").css("display", "block");
- } else {
- $('#register_error').text(
- (xhr.responseText ? xhr.responseText : "${_("An error occurred. Please try again later.") | n, decode.utf8}")
- ).css("display", "block");
- }
- });
-
- %else:
-
$('#class_enroll_form').on('ajax:complete', function(event, xhr) {
if(xhr.status == 200) {
if (xhr.responseText == "") {
- location.href = "${reverse('dashboard') | n, decode.utf8}";
+ location.href = "${reverse('dashboard') | n, js_escaped_string}";
}
else {
location.href = xhr.responseText;
}
- } else if (xhr.status == 403) {
- location.href = "${reverse('register_user') | n, decode.utf8 }?course_id=${course.id | n, decode.utf8 }&enrollment_action=enroll";
} else {
$('#register_error').text(
- (xhr.responseText ? xhr.responseText : "${_("An error occurred. Please try again later.") | n, decode.utf8}")
+ (xhr.responseText ? xhr.responseText : "${_("An error occurred. Please try again later.") | n, js_escaped_string}")
).css("display", "block");
}
});
- %endif
-
})(this)
@@ -138,7 +110,10 @@ from six import string_types
%elif in_cart:
- ${Text(_('This course is in your cart.')).format(cart_link=cart_link)}
+ ${Text(_('This course is in your {start_cart_link}cart{end_cart_link}.')).format(
+ start_cart_link=HTML('').format(cart_link=cart_link),
+ end_cart_link=HTML(""),
+ )}
% elif is_course_full:
@@ -167,9 +142,10 @@ from six import string_types
${Text(_("Add {course_name} to Cart {start_span}({price} USD){end_span}")).format(
course_name=course.display_number_with_default,
+ price=course_price,
start_span=HTML(""),
end_span=HTML(""),
- price=course_price)}
+ )}
%elif allow_anonymous:
@@ -179,7 +155,7 @@ from six import string_types
%endif
%else:
- <%
+ <%
if ecommerce_checkout:
reg_href = ecommerce_checkout_link
else:
@@ -358,7 +334,7 @@ from six import string_types