add openid authentication
This commit is contained in:
@@ -61,6 +61,15 @@ def index(request):
|
||||
if settings.COURSEWARE_ENABLED and request.user.is_authenticated():
|
||||
return redirect(reverse('dashboard'))
|
||||
|
||||
return main_index()
|
||||
|
||||
def main_index(extra_context = {}):
|
||||
'''
|
||||
Render the edX main page.
|
||||
|
||||
extra_context is used to allow immediate display of certain modal windows, eg signup,
|
||||
as used by external_auth.
|
||||
'''
|
||||
feed_data = cache.get("students_index_rss_feed_data")
|
||||
if feed_data == None:
|
||||
if hasattr(settings, 'RSS_URL'):
|
||||
@@ -81,8 +90,9 @@ def index(request):
|
||||
for course in courses:
|
||||
universities[course.org].append(course)
|
||||
|
||||
return render_to_response('index.html', {'universities': universities, 'entries': entries})
|
||||
|
||||
context = {'universities': universities, 'entries': entries}
|
||||
context.update(extra_context)
|
||||
return render_to_response('index.html', context)
|
||||
|
||||
def course_from_id(id):
|
||||
course_loc = CourseDescriptor.id_to_location(id)
|
||||
@@ -257,11 +267,26 @@ def change_setting(request):
|
||||
|
||||
@ensure_csrf_cookie
|
||||
def create_account(request, post_override=None):
|
||||
''' JSON call to enroll in the course. '''
|
||||
'''
|
||||
JSON call to create new edX account.
|
||||
Used by form in signup_modal.html, which is included into navigation.html
|
||||
'''
|
||||
js = {'success': False}
|
||||
|
||||
post_vars = post_override if post_override else request.POST
|
||||
|
||||
# if doing signup for an external authorization, then get email, password, name from the eamap
|
||||
# don't use the ones from the form, since the user could have hacked those
|
||||
doExternalAuth = 'ExternalAuthMap' in request.session
|
||||
if doExternalAuth:
|
||||
eamap = request.session['ExternalAuthMap']
|
||||
email = eamap.external_email
|
||||
name = eamap.external_name
|
||||
password = eamap.internal_password
|
||||
post_vars = dict(post_vars.items())
|
||||
post_vars.update(dict(email=email, name=name, password=password, username=post_vars['username']))
|
||||
log.debug('extauth test: post_vars = %s' % post_vars)
|
||||
|
||||
# Confirm we have a properly formed request
|
||||
for a in ['username', 'email', 'password', 'name']:
|
||||
if a not in post_vars:
|
||||
@@ -356,8 +381,9 @@ def create_account(request, post_override=None):
|
||||
'key': r.activation_key,
|
||||
}
|
||||
|
||||
# composes activation email
|
||||
subject = render_to_string('emails/activation_email_subject.txt', d)
|
||||
# Email subject *must not* contain newlines
|
||||
# Email subject *must not* contain newlines
|
||||
subject = ''.join(subject.splitlines())
|
||||
message = render_to_string('emails/activation_email.txt', d)
|
||||
|
||||
@@ -382,6 +408,17 @@ def create_account(request, post_override=None):
|
||||
|
||||
try_change_enrollment(request)
|
||||
|
||||
if doExternalAuth:
|
||||
eamap.user = login_user
|
||||
eamap.dtsignup = datetime.datetime.now()
|
||||
eamap.save()
|
||||
log.debug('Updated ExternalAuthMap for %s to be %s' % (post_vars['username'],eamap))
|
||||
|
||||
if settings.MITX_FEATURES.get('BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'):
|
||||
log.debug('bypassing activation email')
|
||||
login_user.is_active = True
|
||||
login_user.save()
|
||||
|
||||
js = {'success': True}
|
||||
return HttpResponse(json.dumps(js), mimetype="application/json")
|
||||
|
||||
|
||||
@@ -55,6 +55,18 @@ CACHES = {
|
||||
# Dummy secret key for dev
|
||||
SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd'
|
||||
|
||||
################################ OpenID Auth #################################
|
||||
MITX_FEATURES['AUTH_USE_OPENID'] = True
|
||||
MITX_FEATURES['BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'] = True
|
||||
|
||||
INSTALLED_APPS += ('external_auth',)
|
||||
INSTALLED_APPS += ('django_openid_auth',)
|
||||
|
||||
OPENID_CREATE_USERS = False
|
||||
OPENID_UPDATE_DETAILS_FROM_SREG = True
|
||||
OPENID_SSO_SERVER_URL = 'https://www.google.com/accounts/o8/id' # TODO: accept more endpoints
|
||||
OPENID_USE_AS_ADMIN_LOGIN = False
|
||||
|
||||
################################ DEBUG TOOLBAR #################################
|
||||
INSTALLED_APPS += ('debug_toolbar',)
|
||||
MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',)
|
||||
|
||||
@@ -7,142 +7,110 @@ sessions. Assumes structure:
|
||||
/mitx # The location of this repo
|
||||
/log # Where we're going to write log files
|
||||
"""
|
||||
|
||||
import socket
|
||||
|
||||
if 'eecs1' in socket.gethostname():
|
||||
MITX_ROOT_URL = '/mitx2'
|
||||
|
||||
from .common import *
|
||||
from .logsettings import get_logger_config
|
||||
from .dev import *
|
||||
|
||||
if 'eecs1' in socket.gethostname():
|
||||
# MITX_ROOT_URL = '/mitx2'
|
||||
MITX_ROOT_URL = 'https://eecs1.mit.edu/mitx2'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# edx4edx content server
|
||||
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
||||
MITX_FEATURES['REROUTE_ACTIVATION_EMAIL'] = 'ichuang@mit.edu'
|
||||
EDX4EDX_ROOT = ENV_ROOT / "data/edx4edx"
|
||||
|
||||
#EMAIL_BACKEND = 'django_ses.SESBackend'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# ichuang
|
||||
|
||||
DEBUG = True
|
||||
ENABLE_MULTICOURSE = True # set to False to disable multicourse display (see lib.util.views.mitxhome)
|
||||
QUICKEDIT = False
|
||||
TEMPLATE_DEBUG = True
|
||||
|
||||
MAKO_TEMPLATES['course'] = [DATA_DIR, EDX4EDX_ROOT ]
|
||||
MITX_FEATURES['DISABLE_START_DATES'] = True
|
||||
|
||||
#MITX_FEATURES['USE_DJANGO_PIPELINE'] = False
|
||||
MITX_FEATURES['DISPLAY_HISTOGRAMS_TO_STAFF'] = False
|
||||
MITX_FEATURES['DISPLAY_EDIT_LINK'] = True
|
||||
MITX_FEATURES['DEBUG_LEVEL'] = 10 # 0 = lowest level, least verbose, 255 = max level, most verbose
|
||||
WIKI_ENABLED = True
|
||||
|
||||
COURSE_SETTINGS = {'6.002x_Fall_2012': {'number' : '6.002x',
|
||||
'title' : 'Circuits and Electronics',
|
||||
'xmlpath': '/6002x-fall-2012/',
|
||||
'active' : True,
|
||||
'default_chapter' : 'Week_1',
|
||||
'default_section' : 'Administrivia_and_Circuit_Elements',
|
||||
'location': 'i4x://edx/6002xs12/course/6.002x_Fall_2012',
|
||||
},
|
||||
'8.02_Spring_2013': {'number' : '8.02x',
|
||||
'title' : 'Electricity & Magnetism',
|
||||
'xmlpath': '/802x/',
|
||||
'github_url': 'https://github.com/MITx/8.02x',
|
||||
'active' : True,
|
||||
'default_chapter' : 'Introduction',
|
||||
'default_section' : 'Introduction_%28Lewin_2002%29',
|
||||
},
|
||||
'6.189_Spring_2013': {'number' : '6.189x',
|
||||
'title' : 'IAP Python Programming',
|
||||
'xmlpath': '/6.189x/',
|
||||
'github_url': 'https://github.com/MITx/6.189x',
|
||||
'active' : True,
|
||||
'default_chapter' : 'Week_1',
|
||||
'default_section' : 'Variables_and_Binding',
|
||||
},
|
||||
'8.01_Fall_2012': {'number' : '8.01x',
|
||||
'title' : 'Mechanics',
|
||||
'xmlpath': '/8.01x/',
|
||||
'github_url': 'https://github.com/MITx/8.01x',
|
||||
'active': True,
|
||||
'default_chapter' : 'Mechanics_Online_Spring_2012',
|
||||
'default_section' : 'Introduction_to_the_course',
|
||||
'location': 'i4x://edx/6002xs12/course/8.01_Fall_2012',
|
||||
},
|
||||
'edx4edx': {'number' : 'edX.01',
|
||||
'title' : 'edx4edx: edX Author Course',
|
||||
'xmlpath': '/edx4edx/',
|
||||
'github_url': 'https://github.com/MITx/edx4edx',
|
||||
'active' : True,
|
||||
'default_chapter' : 'Introduction',
|
||||
'default_section' : 'edx4edx_Course',
|
||||
'location': 'i4x://edx/6002xs12/course/edx4edx',
|
||||
},
|
||||
'7.03x_Fall_2012': {'number' : '7.03x',
|
||||
'title' : 'Genetics',
|
||||
'xmlpath': '/7.03x/',
|
||||
'github_url': 'https://github.com/MITx/7.03x',
|
||||
'active' : True,
|
||||
'default_chapter' : 'Week_2',
|
||||
'default_section' : 'ps1_question_1',
|
||||
},
|
||||
'3.091x_Fall_2012': {'number' : '3.091x',
|
||||
'title' : 'Introduction to Solid State Chemistry',
|
||||
'xmlpath': '/3.091x/',
|
||||
'github_url': 'https://github.com/MITx/3.091x',
|
||||
'active' : True,
|
||||
'default_chapter' : 'Week_1',
|
||||
'default_section' : 'Problem_Set_1',
|
||||
},
|
||||
'18.06x_Linear_Algebra': {'number' : '18.06x',
|
||||
'title' : 'Linear Algebra',
|
||||
'xmlpath': '/18.06x/',
|
||||
'github_url': 'https://github.com/MITx/18.06x',
|
||||
'default_chapter' : 'Unit_1',
|
||||
'default_section' : 'Midterm_1',
|
||||
'active' : True,
|
||||
},
|
||||
'6.00x_Fall_2012': {'number' : '6.00x',
|
||||
'title' : 'Introduction to Computer Science and Programming',
|
||||
'xmlpath': '/6.00x/',
|
||||
'github_url': 'https://github.com/MITx/6.00x',
|
||||
'active' : True,
|
||||
'default_chapter' : 'Week_0',
|
||||
'default_section' : 'Problem_Set_0',
|
||||
'location': 'i4x://edx/6002xs12/course/6.00x_Fall_2012',
|
||||
},
|
||||
'7.00x_Fall_2012': {'number' : '7.00x',
|
||||
'title' : 'Introduction to Biology',
|
||||
'xmlpath': '/7.00x/',
|
||||
'github_url': 'https://github.com/MITx/7.00x',
|
||||
'active' : True,
|
||||
'default_chapter' : 'Unit 1',
|
||||
'default_section' : 'Introduction',
|
||||
},
|
||||
}
|
||||
LOGGING = get_logger_config(ENV_ROOT / "log",
|
||||
logging_env="dev",
|
||||
tracking_filename="tracking.log",
|
||||
debug=True)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': ENV_ROOT / "db" / "mitx.db",
|
||||
}
|
||||
}
|
||||
|
||||
MIDDLEWARE_CLASSES = MIDDLEWARE_CLASSES + (
|
||||
'ssl_auth.ssl_auth.NginxProxyHeaderMiddleware', # ssl authentication behind nginx proxy
|
||||
)
|
||||
CACHES = {
|
||||
# This is the cache used for most things. Askbot will not work without a
|
||||
# functioning cache -- it relies on caching to load its settings in places.
|
||||
# In staging/prod envs, the sessions also live here.
|
||||
'default': {
|
||||
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||
'LOCATION': 'mitx_loc_mem_cache',
|
||||
'KEY_FUNCTION': 'util.memcache.safe_key',
|
||||
},
|
||||
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'ssl_auth.ssl_auth.SSLLoginBackend',
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
)
|
||||
# The general cache is what you get if you use our util.cache. It's used for
|
||||
# things like caching the course.xml file for different A/B test groups.
|
||||
# We set it to be a DummyCache to force reloading of course.xml in dev.
|
||||
# In staging environments, we would grab VERSION from data uploaded by the
|
||||
# push process.
|
||||
'general': {
|
||||
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
|
||||
'KEY_PREFIX': 'general',
|
||||
'VERSION': 4,
|
||||
'KEY_FUNCTION': 'util.memcache.safe_key',
|
||||
}
|
||||
}
|
||||
|
||||
INSTALLED_APPS = INSTALLED_APPS + (
|
||||
'ssl_auth',
|
||||
)
|
||||
# Dummy secret key for dev
|
||||
SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd'
|
||||
|
||||
LOGIN_REDIRECT_URL = MITX_ROOT_URL + '/'
|
||||
LOGIN_URL = MITX_ROOT_URL + '/'
|
||||
################################ OpenID Auth #################################
|
||||
MITX_FEATURES['AUTH_USE_OPENID'] = True
|
||||
|
||||
INSTALLED_APPS += ('external_auth',)
|
||||
INSTALLED_APPS += ('django_openid_auth',)
|
||||
#INSTALLED_APPS += ('ssl_auth',)
|
||||
|
||||
#MIDDLEWARE_CLASSES += (
|
||||
# #'ssl_auth.ssl_auth.NginxProxyHeaderMiddleware', # ssl authentication behind nginx proxy
|
||||
# )
|
||||
|
||||
#AUTHENTICATION_BACKENDS = (
|
||||
# 'django_openid_auth.auth.OpenIDBackend',
|
||||
# 'django.contrib.auth.backends.ModelBackend',
|
||||
# )
|
||||
|
||||
OPENID_CREATE_USERS = False
|
||||
OPENID_UPDATE_DETAILS_FROM_SREG = True
|
||||
OPENID_SSO_SERVER_URL = 'https://www.google.com/accounts/o8/id'
|
||||
OPENID_USE_AS_ADMIN_LOGIN = False
|
||||
#import external_auth.views as edXauth
|
||||
#OPENID_RENDER_FAILURE = edXauth.edXauth_openid
|
||||
|
||||
################################ DEBUG TOOLBAR #################################
|
||||
INSTALLED_APPS += ('debug_toolbar',)
|
||||
MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',)
|
||||
INTERNAL_IPS = ('127.0.0.1',)
|
||||
|
||||
DEBUG_TOOLBAR_PANELS = (
|
||||
'debug_toolbar.panels.version.VersionDebugPanel',
|
||||
'debug_toolbar.panels.timer.TimerDebugPanel',
|
||||
'debug_toolbar.panels.settings_vars.SettingsVarsDebugPanel',
|
||||
'debug_toolbar.panels.headers.HeaderDebugPanel',
|
||||
'debug_toolbar.panels.request_vars.RequestVarsDebugPanel',
|
||||
'debug_toolbar.panels.sql.SQLDebugPanel',
|
||||
'debug_toolbar.panels.signals.SignalDebugPanel',
|
||||
'debug_toolbar.panels.logger.LoggingPanel',
|
||||
|
||||
# Enabling the profiler has a weird bug as of django-debug-toolbar==0.9.4 and
|
||||
# Django=1.3.1/1.4 where requests to views get duplicated (your method gets
|
||||
# hit twice). So you can uncomment when you need to diagnose performance
|
||||
# problems, but you shouldn't leave it on.
|
||||
# 'debug_toolbar.panels.profiling.ProfilingDebugPanel',
|
||||
)
|
||||
|
||||
############################ FILE UPLOADS (ASKBOT) #############################
|
||||
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
|
||||
MEDIA_ROOT = ENV_ROOT / "uploads"
|
||||
MEDIA_URL = "/static/uploads/"
|
||||
STATICFILES_DIRS.append(("uploads", MEDIA_ROOT))
|
||||
FILE_UPLOAD_TEMP_DIR = ENV_ROOT / "uploads"
|
||||
FILE_UPLOAD_HANDLERS = (
|
||||
'django.core.files.uploadhandler.MemoryFileUploadHandler',
|
||||
'django.core.files.uploadhandler.TemporaryFileUploadHandler',
|
||||
)
|
||||
|
||||
########################### PIPELINE #################################
|
||||
|
||||
PIPELINE_SASS_ARGUMENTS = '-r {proj_dir}/static/sass/bourbon/lib/bourbon.rb'.format(proj_dir=PROJECT_ROOT)
|
||||
|
||||
11
lms/templates/extauth_failure.html
Normal file
11
lms/templates/extauth_failure.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>OpenID failed</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>OpenID failed</h1>
|
||||
<p>${message}</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -144,3 +144,12 @@
|
||||
<iframe width="640" height="360" src="http://www.youtube.com/embed/C2OQ51tu7W4?showinfo=0" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
% if show_signup_immediately is not UNDEFINED:
|
||||
<script type="text/javascript">
|
||||
function dosignup(){
|
||||
document.getElementById('signup').click();
|
||||
}
|
||||
$(window).load(dosignup);
|
||||
</script>
|
||||
% endif
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
<span>Not enrolled? <a href="#signup-modal" class="close-login" rel="leanModal">Sign up.</a></span>
|
||||
<a href="#forgot-password-modal" rel="leanModal" class="pwd-reset">Forgot password?</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="${MITX_ROOT_URL}/openid/login">login via openid</a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div class="close-modal">
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
<div id="register_error" name="register_error"></div>
|
||||
|
||||
<div class="input-group">
|
||||
% if has_extauth_info is UNDEFINED:
|
||||
<label data-field="email">E-mail*</label>
|
||||
<input name="email" type="email" placeholder="E-mail*">
|
||||
<label data-field="password">Password*</label>
|
||||
@@ -27,6 +28,18 @@
|
||||
<input name="username" type="text" placeholder="Public Username*">
|
||||
<label data-field="name">Full Name</label>
|
||||
<input name="name" type="text" placeholder="Full Name*">
|
||||
% else:
|
||||
<p><i>Welcome</i> ${extauth_email}</p><br/>
|
||||
<label data-field="email">E-mail*</label>
|
||||
<input name="email" type="hidden" value="${extauth_email}" placeholder="E-mail*">
|
||||
<p><i>Enter a public username:</i></p>
|
||||
<label data-field="username">Public Username*</label>
|
||||
<input name="username" type="text" value="${extauth_username}" placeholder="Public Username*">
|
||||
<label data-field="password">Password*</label>
|
||||
<input name="password" type="hidden" value="DoExtAuth" placeholder="Password*">
|
||||
<label data-field="name">Full Name</label>
|
||||
<input name="name" type="hidden" value="${extauth_name}" placeholder="Full Name*">
|
||||
% endif
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
@@ -93,11 +106,13 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
% if has_extauth_info is UNDEFINED:
|
||||
<section class="login-extra">
|
||||
<p>
|
||||
<span>Already have an account? <a href="#login-modal" class="close-signup" rel="leanModal">Login.</a></span>
|
||||
</p>
|
||||
</section>
|
||||
% endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
12
lms/urls.py
12
lms/urls.py
@@ -160,12 +160,22 @@ if settings.DEBUG:
|
||||
## Jasmine
|
||||
urlpatterns=urlpatterns + (url(r'^_jasmine/', include('django_jasmine.urls')),)
|
||||
|
||||
if settings.MITX_FEATURES.get('AUTH_USE_OPENID'):
|
||||
urlpatterns += (
|
||||
url(r'^openid/login/$', 'django_openid_auth.views.login_begin', name='openid-login'),
|
||||
url(r'^openid/complete/$', 'external_auth.views.edXauth_openid_login_complete', name='openid-complete'),
|
||||
url(r'^openid/logo.gif$', 'django_openid_auth.views.logo', name='openid-logo'),
|
||||
)
|
||||
urlpatterns += (
|
||||
url(r'^extauth/$', 'external_auth.views.edXauth_signup', name='extauth-signup'),
|
||||
)
|
||||
# urlpatterns += (url(r'^openid/', include('django_openid_auth.urls')),)
|
||||
|
||||
urlpatterns = patterns(*urlpatterns)
|
||||
|
||||
if settings.DEBUG:
|
||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
|
||||
|
||||
#Custom error pages
|
||||
handler404 = 'static_template_view.views.render_404'
|
||||
handler500 = 'static_template_view.views.render_500'
|
||||
|
||||
@@ -8,6 +8,7 @@ lxml
|
||||
boto
|
||||
mako
|
||||
python-memcached
|
||||
python-openid
|
||||
path.py
|
||||
django_debug_toolbar
|
||||
-e git://github.com/MITx/django-pipeline.git#egg=django-pipeline
|
||||
@@ -37,6 +38,7 @@ django-jasmine
|
||||
django-keyedcache
|
||||
django-mako
|
||||
django-masquerade
|
||||
django-openid-auth
|
||||
django-robots
|
||||
django-ses
|
||||
django-storages
|
||||
|
||||
Reference in New Issue
Block a user