Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
fd49f88e
Commit
fd49f88e
authored
Oct 05, 2016
by
Nimisha Asthagiri
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Moves external_auth from common to openedx/core.
parent
ce1eb237
Show whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
192 additions
and
117 deletions
+192
-117
cms/djangoapps/contentstore/views/public.py
+5
-2
cms/envs/common.py
+1
-1
cms/urls.py
+1
-1
common/djangoapps/student/tests/test_create_account.py
+1
-1
common/djangoapps/student/tests/test_login.py
+1
-1
common/djangoapps/student/tests/test_password_policy.py
+1
-1
common/djangoapps/student/views.py
+8
-8
docs/en_us/platform_api/source/conf.py
+1
-1
lms/djangoapps/branding/views.py
+1
-1
lms/djangoapps/courseware/access.py
+1
-1
lms/djangoapps/dashboard/sysadmin.py
+2
-2
lms/djangoapps/lms_migration/management/commands/create_user.py
+1
-1
lms/djangoapps/student_account/views.py
+1
-1
lms/envs/common.py
+1
-1
lms/urls.py
+25
-9
openedx/core/djangoapps/external_auth/__init__.py
+0
-0
openedx/core/djangoapps/external_auth/admin.py
+4
-1
openedx/core/djangoapps/external_auth/djangostore.py
+14
-5
openedx/core/djangoapps/external_auth/login_and_register.py
+11
-5
openedx/core/djangoapps/external_auth/migrations/0001_initial.py
+0
-0
openedx/core/djangoapps/external_auth/migrations/__init__.py
+0
-0
openedx/core/djangoapps/external_auth/models.py
+5
-3
openedx/core/djangoapps/external_auth/tests/__init__.py
+0
-0
openedx/core/djangoapps/external_auth/tests/test_helper.py
+1
-1
openedx/core/djangoapps/external_auth/tests/test_openid_provider.py
+46
-20
openedx/core/djangoapps/external_auth/tests/test_shib.py
+12
-10
openedx/core/djangoapps/external_auth/tests/test_ssl.py
+11
-10
openedx/core/djangoapps/external_auth/views.py
+37
-30
No files found.
cms/djangoapps/contentstore/views/public.py
View file @
fd49f88e
...
@@ -10,8 +10,11 @@ from django.conf import settings
...
@@ -10,8 +10,11 @@ from django.conf import settings
from
edxmako.shortcuts
import
render_to_response
from
edxmako.shortcuts
import
render_to_response
from
external_auth.views
import
(
ssl_login_shortcut
,
ssl_get_cert_from_request
,
from
openedx.core.djangoapps.external_auth.views
import
(
redirect_with_get
)
ssl_login_shortcut
,
ssl_get_cert_from_request
,
redirect_with_get
,
)
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
__all__
=
[
'signup'
,
'login_page'
,
'howitworks'
]
__all__
=
[
'signup'
,
'login_page'
,
'howitworks'
]
...
...
cms/envs/common.py
View file @
fd49f88e
...
@@ -817,7 +817,7 @@ INSTALLED_APPS = (
...
@@ -817,7 +817,7 @@ INSTALLED_APPS = (
'contentstore'
,
'contentstore'
,
'contentserver'
,
'contentserver'
,
'course_creators'
,
'course_creators'
,
'external_auth'
,
'
openedx.core.djangoapps.
external_auth'
,
'student'
,
# misleading name due to sharing with lms
'student'
,
# misleading name due to sharing with lms
'openedx.core.djangoapps.course_groups'
,
# not used in cms (yet), but tests run
'openedx.core.djangoapps.course_groups'
,
# not used in cms (yet), but tests run
'openedx.core.djangoapps.coursetalk'
,
# not used in cms (yet), but tests run
'openedx.core.djangoapps.coursetalk'
,
# not used in cms (yet), but tests run
...
...
cms/urls.py
View file @
fd49f88e
...
@@ -153,7 +153,7 @@ if settings.FEATURES.get('ENABLE_SERVICE_STATUS'):
...
@@ -153,7 +153,7 @@ if settings.FEATURES.get('ENABLE_SERVICE_STATUS'):
if
settings
.
FEATURES
.
get
(
'AUTH_USE_CAS'
):
if
settings
.
FEATURES
.
get
(
'AUTH_USE_CAS'
):
urlpatterns
+=
(
urlpatterns
+=
(
url
(
r'^cas-auth/login/$'
,
'external_auth.views.cas_login'
,
name
=
"cas-login"
),
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"
),
url
(
r'^cas-auth/logout/$'
,
'django_cas.views.logout'
,
{
'next_page'
:
'/'
},
name
=
"cas-logout"
),
)
)
...
...
common/djangoapps/student/tests/test_create_account.py
View file @
fd49f88e
...
@@ -16,7 +16,7 @@ import mock
...
@@ -16,7 +16,7 @@ import mock
from
openedx.core.djangoapps.user_api.preferences.api
import
get_user_preference
from
openedx.core.djangoapps.user_api.preferences.api
import
get_user_preference
from
lang_pref
import
LANGUAGE_KEY
from
lang_pref
import
LANGUAGE_KEY
from
notification_prefs
import
NOTIFICATION_PREF_KEY
from
notification_prefs
import
NOTIFICATION_PREF_KEY
from
external_auth.models
import
ExternalAuthMap
from
openedx.core.djangoapps.
external_auth.models
import
ExternalAuthMap
import
student
import
student
from
student.models
import
UserAttribute
from
student.models
import
UserAttribute
from
student.views
import
REGISTRATION_AFFILIATE_ID
from
student.views
import
REGISTRATION_AFFILIATE_ID
...
...
common/djangoapps/student/tests/test_login.py
View file @
fd49f88e
...
@@ -16,7 +16,7 @@ import httpretty
...
@@ -16,7 +16,7 @@ import httpretty
from
mock
import
patch
from
mock
import
patch
from
social.apps.django_app.default.models
import
UserSocialAuth
from
social.apps.django_app.default.models
import
UserSocialAuth
from
external_auth.models
import
ExternalAuthMap
from
openedx.core.djangoapps.
external_auth.models
import
ExternalAuthMap
from
openedx.core.djangolib.testing.utils
import
CacheIsolationTestCase
from
openedx.core.djangolib.testing.utils
import
CacheIsolationTestCase
from
student.tests.factories
import
UserFactory
,
RegistrationFactory
,
UserProfileFactory
from
student.tests.factories
import
UserFactory
,
RegistrationFactory
,
UserProfileFactory
from
student.views
import
login_oauth_token
from
student.views
import
login_oauth_token
...
...
common/djangoapps/student/tests/test_password_policy.py
View file @
fd49f88e
...
@@ -11,7 +11,7 @@ from importlib import import_module
...
@@ -11,7 +11,7 @@ from importlib import import_module
from
django.test.utils
import
override_settings
from
django.test.utils
import
override_settings
from
django.conf
import
settings
from
django.conf
import
settings
from
mock
import
patch
from
mock
import
patch
from
external_auth.models
import
ExternalAuthMap
from
openedx.core.djangoapps.
external_auth.models
import
ExternalAuthMap
from
student.views
import
create_account
from
student.views
import
create_account
...
...
common/djangoapps/student/views.py
View file @
fd49f88e
...
@@ -78,9 +78,9 @@ from courseware.access import has_access
...
@@ -78,9 +78,9 @@ from courseware.access import has_access
from
django_comment_common.models
import
Role
from
django_comment_common.models
import
Role
from
external_auth.models
import
ExternalAuthMap
from
openedx.core.djangoapps.
external_auth.models
import
ExternalAuthMap
import
external_auth.views
import
openedx.core.djangoapps.
external_auth.views
from
external_auth.login_and_register
import
(
from
openedx.core.djangoapps.
external_auth.login_and_register
import
(
login
as
external_auth_login
,
login
as
external_auth_login
,
register
as
external_auth_register
register
as
external_auth_register
)
)
...
@@ -470,7 +470,9 @@ def register_user(request, extra_context=None):
...
@@ -470,7 +470,9 @@ def register_user(request, extra_context=None):
if
extra_context
is
not
None
:
if
extra_context
is
not
None
:
context
.
update
(
extra_context
)
context
.
update
(
extra_context
)
if
context
.
get
(
"extauth_domain"
,
''
)
.
startswith
(
external_auth
.
views
.
SHIBBOLETH_DOMAIN_PREFIX
):
if
context
.
get
(
"extauth_domain"
,
''
)
.
startswith
(
openedx
.
core
.
djangoapps
.
external_auth
.
views
.
SHIBBOLETH_DOMAIN_PREFIX
):
return
render_to_response
(
'register-shib.html'
,
context
)
return
render_to_response
(
'register-shib.html'
,
context
)
# If third-party auth is enabled, prepopulate the form with data from the
# If third-party auth is enabled, prepopulate the form with data from the
...
@@ -1195,7 +1197,7 @@ def login_user(request, error=""): # pylint: disable=too-many-statements,unused
...
@@ -1195,7 +1197,7 @@ def login_user(request, error=""): # pylint: disable=too-many-statements,unused
if
settings
.
FEATURES
.
get
(
'AUTH_USE_SHIB'
)
and
user
:
if
settings
.
FEATURES
.
get
(
'AUTH_USE_SHIB'
)
and
user
:
try
:
try
:
eamap
=
ExternalAuthMap
.
objects
.
get
(
user
=
user
)
eamap
=
ExternalAuthMap
.
objects
.
get
(
user
=
user
)
if
eamap
.
external_domain
.
startswith
(
external_auth
.
views
.
SHIBBOLETH_DOMAIN_PREFIX
):
if
eamap
.
external_domain
.
startswith
(
openedx
.
core
.
djangoapps
.
external_auth
.
views
.
SHIBBOLETH_DOMAIN_PREFIX
):
return
JsonResponse
({
return
JsonResponse
({
"success"
:
False
,
"success"
:
False
,
"redirect"
:
reverse
(
'shib-login'
),
"redirect"
:
reverse
(
'shib-login'
),
...
@@ -1637,9 +1639,7 @@ def create_account_with_params(request, params):
...
@@ -1637,9 +1639,7 @@ def create_account_with_params(request, params):
not
settings
.
FEATURES
.
get
(
"AUTH_USE_SHIB"
)
or
not
settings
.
FEATURES
.
get
(
"AUTH_USE_SHIB"
)
or
not
settings
.
FEATURES
.
get
(
"SHIB_DISABLE_TOS"
)
or
not
settings
.
FEATURES
.
get
(
"SHIB_DISABLE_TOS"
)
or
not
do_external_auth
or
not
do_external_auth
or
not
eamap
.
external_domain
.
startswith
(
not
eamap
.
external_domain
.
startswith
(
openedx
.
core
.
djangoapps
.
external_auth
.
views
.
SHIBBOLETH_DOMAIN_PREFIX
)
external_auth
.
views
.
SHIBBOLETH_DOMAIN_PREFIX
)
)
)
form
=
AccountCreationForm
(
form
=
AccountCreationForm
(
...
...
docs/en_us/platform_api/source/conf.py
View file @
fd49f88e
...
@@ -101,7 +101,7 @@ MOCK_MODULES = [
...
@@ -101,7 +101,7 @@ MOCK_MODULES = [
'openid'
,
'openid'
,
'openid.store'
,
'openid.store'
,
'openid.store.interface'
,
'openid.store.interface'
,
'external_auth.views'
,
'
openedx.core.djangoapps.
external_auth.views'
,
'mail_utils'
,
'mail_utils'
,
'ratelimitbackend.backends'
,
'ratelimitbackend.backends'
,
'social.apps.django_app.default'
,
'social.apps.django_app.default'
,
...
...
lms/djangoapps/branding/views.py
View file @
fd49f88e
...
@@ -61,7 +61,7 @@ def index(request):
...
@@ -61,7 +61,7 @@ def index(request):
return
redirect
(
reverse
(
'dashboard'
))
return
redirect
(
reverse
(
'dashboard'
))
if
settings
.
FEATURES
.
get
(
'AUTH_USE_CERTIFICATES'
):
if
settings
.
FEATURES
.
get
(
'AUTH_USE_CERTIFICATES'
):
from
external_auth.views
import
ssl_login
from
openedx.core.djangoapps.
external_auth.views
import
ssl_login
# Set next URL to dashboard if it isn't set to avoid
# Set next URL to dashboard if it isn't set to avoid
# caching a redirect to / that causes a redirect loop on logout
# caching a redirect to / that causes a redirect loop on logout
if
not
request
.
GET
.
get
(
'next'
):
if
not
request
.
GET
.
get
(
'next'
):
...
...
lms/djangoapps/courseware/access.py
View file @
fd49f88e
...
@@ -33,7 +33,7 @@ from xmodule.x_module import XModule
...
@@ -33,7 +33,7 @@ from xmodule.x_module import XModule
from
xmodule.split_test_module
import
get_split_user_partitions
from
xmodule.split_test_module
import
get_split_user_partitions
from
xmodule.partitions.partitions
import
NoSuchUserPartitionError
,
NoSuchUserPartitionGroupError
from
xmodule.partitions.partitions
import
NoSuchUserPartitionError
,
NoSuchUserPartitionGroupError
from
external_auth.models
import
ExternalAuthMap
from
openedx.core.djangoapps.
external_auth.models
import
ExternalAuthMap
from
courseware.masquerade
import
get_masquerade_role
,
is_masquerading_as_student
from
courseware.masquerade
import
get_masquerade_role
,
is_masquerading_as_student
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
from
student
import
auth
from
student
import
auth
...
...
lms/djangoapps/dashboard/sysadmin.py
View file @
fd49f88e
...
@@ -34,8 +34,8 @@ import dashboard.git_import as git_import
...
@@ -34,8 +34,8 @@ import dashboard.git_import as git_import
from
dashboard.git_import
import
GitImportError
from
dashboard.git_import
import
GitImportError
from
student.roles
import
CourseStaffRole
,
CourseInstructorRole
from
student.roles
import
CourseStaffRole
,
CourseInstructorRole
from
dashboard.models
import
CourseImportLog
from
dashboard.models
import
CourseImportLog
from
external_auth.models
import
ExternalAuthMap
from
openedx.core.djangoapps.
external_auth.models
import
ExternalAuthMap
from
external_auth.views
import
generate_password
from
openedx.core.djangoapps.
external_auth.views
import
generate_password
from
student.models
import
CourseEnrollment
,
UserProfile
,
Registration
from
student.models
import
CourseEnrollment
,
UserProfile
,
Registration
import
track.views
import
track.views
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
...
...
lms/djangoapps/lms_migration/management/commands/create_user.py
View file @
fd49f88e
...
@@ -15,7 +15,7 @@ import readline
...
@@ -15,7 +15,7 @@ import readline
from
django.core.management.base
import
BaseCommand
from
django.core.management.base
import
BaseCommand
from
student.models
import
UserProfile
,
Registration
from
student.models
import
UserProfile
,
Registration
from
external_auth.models
import
ExternalAuthMap
from
openedx.core.djangoapps.
external_auth.models
import
ExternalAuthMap
from
django.contrib.auth.models
import
User
,
Group
from
django.contrib.auth.models
import
User
,
Group
from
pytz
import
UTC
from
pytz
import
UTC
...
...
lms/djangoapps/student_account/views.py
View file @
fd49f88e
...
@@ -22,7 +22,7 @@ from edxmako.shortcuts import render_to_response
...
@@ -22,7 +22,7 @@ from edxmako.shortcuts import render_to_response
import
pytz
import
pytz
from
commerce.models
import
CommerceConfiguration
from
commerce.models
import
CommerceConfiguration
from
external_auth.login_and_register
import
(
from
openedx.core.djangoapps.
external_auth.login_and_register
import
(
login
as
external_auth_login
,
login
as
external_auth_login
,
register
as
external_auth_register
register
as
external_auth_register
)
)
...
...
lms/envs/common.py
View file @
fd49f88e
...
@@ -1917,7 +1917,7 @@ INSTALLED_APPS = (
...
@@ -1917,7 +1917,7 @@ INSTALLED_APPS = (
'support'
,
'support'
,
# External auth (OpenID, shib)
# External auth (OpenID, shib)
'external_auth'
,
'
openedx.core.djangoapps.
external_auth'
,
'django_openid_auth'
,
'django_openid_auth'
,
# django-oauth2-provider (deprecated)
# django-oauth2-provider (deprecated)
...
...
lms/urls.py
View file @
fd49f88e
...
@@ -803,27 +803,31 @@ if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
...
@@ -803,27 +803,31 @@ if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
if
settings
.
FEATURES
.
get
(
'AUTH_USE_OPENID'
):
if
settings
.
FEATURES
.
get
(
'AUTH_USE_OPENID'
):
urlpatterns
+=
(
urlpatterns
+=
(
url
(
r'^openid/login/$'
,
'django_openid_auth.views.login_begin'
,
name
=
'openid-login'
),
url
(
r'^openid/login/$'
,
'django_openid_auth.views.login_begin'
,
name
=
'openid-login'
),
url
(
r'^openid/complete/$'
,
'external_auth.views.openid_login_complete'
,
name
=
'openid-complete'
),
url
(
r'^openid/complete/$'
,
'openedx.core.djangoapps.external_auth.views.openid_login_complete'
,
name
=
'openid-complete'
,
),
url
(
r'^openid/logo.gif$'
,
'django_openid_auth.views.logo'
,
name
=
'openid-logo'
),
url
(
r'^openid/logo.gif$'
,
'django_openid_auth.views.logo'
,
name
=
'openid-logo'
),
)
)
if
settings
.
FEATURES
.
get
(
'AUTH_USE_SHIB'
):
if
settings
.
FEATURES
.
get
(
'AUTH_USE_SHIB'
):
urlpatterns
+=
(
urlpatterns
+=
(
url
(
r'^shib-login/$'
,
'external_auth.views.shib_login'
,
name
=
'shib-login'
),
url
(
r'^shib-login/$'
,
'
openedx.core.djangoapps.
external_auth.views.shib_login'
,
name
=
'shib-login'
),
)
)
if
settings
.
FEATURES
.
get
(
'AUTH_USE_CAS'
):
if
settings
.
FEATURES
.
get
(
'AUTH_USE_CAS'
):
urlpatterns
+=
(
urlpatterns
+=
(
url
(
r'^cas-auth/login/$'
,
'external_auth.views.cas_login'
,
name
=
"cas-login"
),
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"
),
url
(
r'^cas-auth/logout/$'
,
'django_cas.views.logout'
,
{
'next_page'
:
'/'
},
name
=
"cas-logout"
),
)
)
if
settings
.
FEATURES
.
get
(
'RESTRICT_ENROLL_BY_REG_METHOD'
):
if
settings
.
FEATURES
.
get
(
'RESTRICT_ENROLL_BY_REG_METHOD'
):
urlpatterns
+=
(
urlpatterns
+=
(
url
(
r'^course_specific_login/{}/$'
.
format
(
settings
.
COURSE_ID_PATTERN
),
url
(
r'^course_specific_login/{}/$'
.
format
(
settings
.
COURSE_ID_PATTERN
),
'external_auth.views.course_specific_login'
,
name
=
'course-specific-login'
),
'
openedx.core.djangoapps.
external_auth.views.course_specific_login'
,
name
=
'course-specific-login'
),
url
(
r'^course_specific_register/{}/$'
.
format
(
settings
.
COURSE_ID_PATTERN
),
url
(
r'^course_specific_register/{}/$'
.
format
(
settings
.
COURSE_ID_PATTERN
),
'external_auth.views.course_specific_register'
,
name
=
'course-specific-register'
),
'
openedx.core.djangoapps.
external_auth.views.course_specific_register'
,
name
=
'course-specific-register'
),
)
)
...
@@ -846,14 +850,26 @@ urlpatterns += (
...
@@ -846,14 +850,26 @@ urlpatterns += (
if
settings
.
FEATURES
.
get
(
'AUTH_USE_OPENID_PROVIDER'
):
if
settings
.
FEATURES
.
get
(
'AUTH_USE_OPENID_PROVIDER'
):
urlpatterns
+=
(
urlpatterns
+=
(
url
(
r'^openid/provider/login/$'
,
'external_auth.views.provider_login'
,
name
=
'openid-provider-login'
),
url
(
r'^openid/provider/login/$'
,
'openedx.core.djangoapps.external_auth.views.provider_login'
,
name
=
'openid-provider-login'
,
),
url
(
url
(
r'^openid/provider/login/(?:.+)$'
,
r'^openid/provider/login/(?:.+)$'
,
'external_auth.views.provider_identity'
,
'
openedx.core.djangoapps.
external_auth.views.provider_identity'
,
name
=
'openid-provider-login-identity'
name
=
'openid-provider-login-identity'
),
),
url
(
r'^openid/provider/identity/$'
,
'external_auth.views.provider_identity'
,
name
=
'openid-provider-identity'
),
url
(
url
(
r'^openid/provider/xrds/$'
,
'external_auth.views.provider_xrds'
,
name
=
'openid-provider-xrds'
)
r'^openid/provider/identity/$'
,
'openedx.core.djangoapps.external_auth.views.provider_identity'
,
name
=
'openid-provider-identity'
,
),
url
(
r'^openid/provider/xrds/$'
,
'openedx.core.djangoapps.external_auth.views.provider_xrds'
,
name
=
'openid-provider-xrds'
,
),
)
)
if
settings
.
FEATURES
.
get
(
'ENABLE_OAUTH2_PROVIDER'
):
if
settings
.
FEATURES
.
get
(
'ENABLE_OAUTH2_PROVIDER'
):
...
...
common
/djangoapps/external_auth/__init__.py
→
openedx/core
/djangoapps/external_auth/__init__.py
View file @
fd49f88e
File moved
common
/djangoapps/external_auth/admin.py
→
openedx/core
/djangoapps/external_auth/admin.py
View file @
fd49f88e
...
@@ -2,11 +2,14 @@
...
@@ -2,11 +2,14 @@
django admin pages for courseware model
django admin pages for courseware model
'''
'''
from
external_auth.models
import
*
from
openedx.core.djangoapps.external_auth.models
import
ExternalAuthMap
from
ratelimitbackend
import
admin
from
ratelimitbackend
import
admin
class
ExternalAuthMapAdmin
(
admin
.
ModelAdmin
):
class
ExternalAuthMapAdmin
(
admin
.
ModelAdmin
):
"""
Admin model for ExternalAuthMap
"""
search_fields
=
[
'external_id'
,
'user__username'
]
search_fields
=
[
'external_id'
,
'user__username'
]
date_hierarchy
=
'dtcreated'
date_hierarchy
=
'dtcreated'
...
...
common
/djangoapps/external_auth/djangostore.py
→
openedx/core
/djangoapps/external_auth/djangostore.py
View file @
fd49f88e
...
@@ -18,19 +18,28 @@ log = logging.getLogger('DjangoOpenIDStore')
...
@@ -18,19 +18,28 @@ log = logging.getLogger('DjangoOpenIDStore')
def
get_url_key
(
server_url
):
def
get_url_key
(
server_url
):
key
=
ASSOCIATIONS_KEY_PREFIX
+
server_url
"""
return
key
Returns the URL key for the given server_url.
"""
return
ASSOCIATIONS_KEY_PREFIX
+
server_url
def
get_nonce_key
(
server_url
,
timestamp
,
salt
):
def
get_nonce_key
(
server_url
,
timestamp
,
salt
):
key
=
'{prefix}{url}.{ts}.{salt}'
.
format
(
prefix
=
NONCE_KEY_PREFIX
,
"""
Returns the nonce for the given parameters.
"""
return
'{prefix}{url}.{ts}.{salt}'
.
format
(
prefix
=
NONCE_KEY_PREFIX
,
url
=
server_url
,
url
=
server_url
,
ts
=
timestamp
,
ts
=
timestamp
,
salt
=
salt
)
salt
=
salt
,
return
key
)
class
DjangoOpenIDStore
(
OpenIDStore
):
class
DjangoOpenIDStore
(
OpenIDStore
):
"""
django implementation of OpenIDStore.
"""
def
__init__
(
self
):
def
__init__
(
self
):
log
.
info
(
'DjangoStore cache:'
+
str
(
cache
.
__class__
))
log
.
info
(
'DjangoStore cache:'
+
str
(
cache
.
__class__
))
...
...
common
/djangoapps/external_auth/login_and_register.py
→
openedx/core
/djangoapps/external_auth/login_and_register.py
View file @
fd49f88e
...
@@ -7,7 +7,7 @@ import re
...
@@ -7,7 +7,7 @@ import re
from
django.conf
import
settings
from
django.conf
import
settings
from
django.shortcuts
import
redirect
from
django.shortcuts
import
redirect
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
import
external_auth.views
import
openedx.core.djangoapps.
external_auth.views
from
xmodule.modulestore.django
import
modulestore
from
xmodule.modulestore.django
import
modulestore
from
opaque_keys.edx.keys
import
CourseKey
from
opaque_keys.edx.keys
import
CourseKey
...
@@ -56,11 +56,14 @@ def login(request):
...
@@ -56,11 +56,14 @@ def login(request):
# is not handling the request.
# is not handling the request.
response
=
None
response
=
None
if
settings
.
FEATURES
[
'AUTH_USE_CERTIFICATES'
]
and
external_auth
.
views
.
ssl_get_cert_from_request
(
request
):
if
(
settings
.
FEATURES
[
'AUTH_USE_CERTIFICATES'
]
and
openedx
.
core
.
djangoapps
.
external_auth
.
views
.
ssl_get_cert_from_request
(
request
)
):
# SSL login doesn't require a view, so redirect
# SSL login doesn't require a view, so redirect
# branding and allow that to process the login if it
# branding and allow that to process the login if it
# is enabled and the header is in the request.
# is enabled and the header is in the request.
response
=
external_auth
.
views
.
redirect_with_get
(
'root'
,
request
.
GET
)
response
=
openedx
.
core
.
djangoapps
.
external_auth
.
views
.
redirect_with_get
(
'root'
,
request
.
GET
)
elif
settings
.
FEATURES
.
get
(
'AUTH_USE_CAS'
):
elif
settings
.
FEATURES
.
get
(
'AUTH_USE_CAS'
):
# If CAS is enabled, redirect auth handling to there
# If CAS is enabled, redirect auth handling to there
response
=
redirect
(
reverse
(
'cas-login'
))
response
=
redirect
(
reverse
(
'cas-login'
))
...
@@ -69,7 +72,10 @@ def login(request):
...
@@ -69,7 +72,10 @@ def login(request):
if
redirect_to
:
if
redirect_to
:
course_id
=
_parse_course_id_from_string
(
redirect_to
)
course_id
=
_parse_course_id_from_string
(
redirect_to
)
if
course_id
and
_get_course_enrollment_domain
(
course_id
):
if
course_id
and
_get_course_enrollment_domain
(
course_id
):
response
=
external_auth
.
views
.
course_specific_login
(
request
,
course_id
.
to_deprecated_string
())
response
=
openedx
.
core
.
djangoapps
.
external_auth
.
views
.
course_specific_login
(
request
,
course_id
.
to_deprecated_string
(),
)
return
response
return
response
...
@@ -88,5 +94,5 @@ def register(request):
...
@@ -88,5 +94,5 @@ def register(request):
if
settings
.
FEATURES
.
get
(
'AUTH_USE_CERTIFICATES_IMMEDIATE_SIGNUP'
):
if
settings
.
FEATURES
.
get
(
'AUTH_USE_CERTIFICATES_IMMEDIATE_SIGNUP'
):
# Redirect to branding to process their certificate if SSL is enabled
# Redirect to branding to process their certificate if SSL is enabled
# and registration is disabled.
# and registration is disabled.
response
=
external_auth
.
views
.
redirect_with_get
(
'root'
,
request
.
GET
)
response
=
openedx
.
core
.
djangoapps
.
external_auth
.
views
.
redirect_with_get
(
'root'
,
request
.
GET
)
return
response
return
response
common
/djangoapps/external_auth/migrations/0001_initial.py
→
openedx/core
/djangoapps/external_auth/migrations/0001_initial.py
View file @
fd49f88e
File moved
common
/djangoapps/external_auth/migrations/__init__.py
→
openedx/core
/djangoapps/external_auth/migrations/__init__.py
View file @
fd49f88e
File moved
common
/djangoapps/external_auth/models.py
→
openedx/core
/djangoapps/external_auth/models.py
View file @
fd49f88e
...
@@ -6,7 +6,7 @@ file and check it in at the same time as your model changes. To do that,
...
@@ -6,7 +6,7 @@ file and check it in at the same time as your model changes. To do that,
1. Go to the edx-platform dir
1. Go to the edx-platform dir
2. ./manage.py lms schemamigration student --auto description_of_your_change
2. ./manage.py lms schemamigration student --auto description_of_your_change
3. Add the migration file created in edx-platform/
common
/djangoapps/external_auth/migrations/
3. Add the migration file created in edx-platform/
openedx/core
/djangoapps/external_auth/migrations/
"""
"""
from
django.db
import
models
from
django.db
import
models
...
@@ -14,6 +14,9 @@ from django.contrib.auth.models import User
...
@@ -14,6 +14,9 @@ from django.contrib.auth.models import User
class
ExternalAuthMap
(
models
.
Model
):
class
ExternalAuthMap
(
models
.
Model
):
"""
Model class for external auth.
"""
class
Meta
(
object
):
class
Meta
(
object
):
app_label
=
"external_auth"
app_label
=
"external_auth"
unique_together
=
((
'external_id'
,
'external_domain'
),
)
unique_together
=
((
'external_id'
,
'external_domain'
),
)
...
@@ -29,5 +32,4 @@ class ExternalAuthMap(models.Model):
...
@@ -29,5 +32,4 @@ class ExternalAuthMap(models.Model):
dtsignup
=
models
.
DateTimeField
(
'signup date'
,
null
=
True
)
# set after signup
dtsignup
=
models
.
DateTimeField
(
'signup date'
,
null
=
True
)
# set after signup
def
__unicode__
(
self
):
def
__unicode__
(
self
):
s
=
"[
%
s] = (
%
s /
%
s)"
%
(
self
.
external_id
,
self
.
external_name
,
self
.
external_email
)
return
"[
%
s] = (
%
s /
%
s)"
%
(
self
.
external_id
,
self
.
external_name
,
self
.
external_email
)
return
s
common
/djangoapps/external_auth/tests/__init__.py
→
openedx/core
/djangoapps/external_auth/tests/__init__.py
View file @
fd49f88e
File moved
common
/djangoapps/external_auth/tests/test_helper.py
→
openedx/core
/djangoapps/external_auth/tests/test_helper.py
View file @
fd49f88e
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
Tests for utility functions in external_auth module
Tests for utility functions in external_auth module
"""
"""
from
django.test
import
TestCase
from
django.test
import
TestCase
from
external_auth.views
import
_safe_postlogin_redirect
from
openedx.core.djangoapps.
external_auth.views
import
_safe_postlogin_redirect
class
ExternalAuthHelperFnTest
(
TestCase
):
class
ExternalAuthHelperFnTest
(
TestCase
):
...
...
common
/djangoapps/external_auth/tests/test_openid_provider.py
→
openedx/core
/djangoapps/external_auth/tests/test_openid_provider.py
View file @
fd49f88e
...
@@ -17,7 +17,7 @@ from django.test.client import RequestFactory
...
@@ -17,7 +17,7 @@ from django.test.client import RequestFactory
from
unittest
import
skipUnless
from
unittest
import
skipUnless
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
from
external_auth.views
import
provider_login
from
openedx.core.djangoapps.
external_auth.views
import
provider_login
class
MyFetcher
(
HTTPFetcher
):
class
MyFetcher
(
HTTPFetcher
):
...
@@ -130,27 +130,53 @@ class OpenIdProviderTest(TestCase):
...
@@ -130,27 +130,53 @@ class OpenIdProviderTest(TestCase):
self
.
assertEqual
(
resp
.
status_code
,
code
,
self
.
assertEqual
(
resp
.
status_code
,
code
,
"got code {0} for url '{1}'. Expected code {2}"
"got code {0} for url '{1}'. Expected code {2}"
.
format
(
resp
.
status_code
,
url
,
code
))
.
format
(
resp
.
status_code
,
url
,
code
))
self
.
assertContains
(
resp
,
'<input name="openid.mode" type="hidden" value="checkid_setup" />'
,
html
=
True
)
for
expected_input
in
(
self
.
assertContains
(
resp
,
'<input name="openid.ns" type="hidden" value="http://specs.openid.net/auth/2.0" />'
,
html
=
True
)
'<input name="openid.ns" type="hidden" value="http://specs.openid.net/auth/2.0" />'
,
self
.
assertContains
(
resp
,
'<input name="openid.identity" type="hidden" value="http://specs.openid.net/auth/2.0/identifier_select" />'
,
html
=
True
)
self
.
assertContains
(
resp
,
'<input name="openid.claimed_id" type="hidden" value="http://specs.openid.net/auth/2.0/identifier_select" />'
,
html
=
True
)
'<input name="openid.ns.ax" type="hidden" value="http://openid.net/srv/ax/1.0" />'
,
self
.
assertContains
(
resp
,
'<input name="openid.ns.ax" type="hidden" value="http://openid.net/srv/ax/1.0" />'
,
html
=
True
)
self
.
assertContains
(
resp
,
'<input name="openid.ax.mode" type="hidden" value="fetch_request" />'
,
html
=
True
)
'<input name="openid.ax.type.fullname" type="hidden" value="http://axschema.org/namePerson" />'
,
self
.
assertContains
(
resp
,
'<input name="openid.ax.required" type="hidden" value="email,fullname,old_email,firstname,old_nickname,lastname,old_fullname,nickname" />'
,
html
=
True
)
self
.
assertContains
(
resp
,
'<input name="openid.ax.type.fullname" type="hidden" value="http://axschema.org/namePerson" />'
,
html
=
True
)
'<input type="submit" value="Continue" />'
,
self
.
assertContains
(
resp
,
'<input name="openid.ax.type.lastname" type="hidden" value="http://axschema.org/namePerson/last" />'
,
html
=
True
)
self
.
assertContains
(
resp
,
'<input name="openid.ax.type.firstname" type="hidden" value="http://axschema.org/namePerson/first" />'
,
html
=
True
)
'<input name="openid.ax.type.email" type="hidden" value="http://axschema.org/contact/email" />'
,
self
.
assertContains
(
resp
,
'<input name="openid.ax.type.nickname" type="hidden" value="http://axschema.org/namePerson/friendly" />'
,
html
=
True
)
self
.
assertContains
(
resp
,
'<input name="openid.ax.type.email" type="hidden" value="http://axschema.org/contact/email" />'
,
html
=
True
)
'<input name="openid.ax.type.lastname" '
self
.
assertContains
(
resp
,
'<input name="openid.ax.type.old_email" type="hidden" value="http://schema.openid.net/contact/email" />'
,
html
=
True
)
'type="hidden" value="http://axschema.org/namePerson/last" />'
,
self
.
assertContains
(
resp
,
'<input name="openid.ax.type.old_nickname" type="hidden" value="http://schema.openid.net/namePerson/friendly" />'
,
html
=
True
)
self
.
assertContains
(
resp
,
'<input name="openid.ax.type.old_fullname" type="hidden" value="http://schema.openid.net/namePerson" />'
,
html
=
True
)
'<input name="openid.ax.type.firstname" '
self
.
assertContains
(
resp
,
'<input type="submit" value="Continue" />'
,
html
=
True
)
'type="hidden" value="http://axschema.org/namePerson/first" />'
,
# this should work on the server:
self
.
assertContains
(
resp
,
'<input name="openid.realm" type="hidden" value="http://testserver/" />'
,
html
=
True
)
'<input name="openid.ax.required" type="hidden" '
'value="email,fullname,old_email,firstname,old_nickname,lastname,old_fullname,nickname" />'
,
'<input name="openid.ax.type.nickname" '
'type="hidden" value="http://axschema.org/namePerson/friendly" />'
,
'<input name="openid.ax.type.old_email" '
'type="hidden" value="http://schema.openid.net/contact/email" />'
,
'<input name="openid.ax.type.old_nickname" '
'type="hidden" value="http://schema.openid.net/namePerson/friendly" />'
,
'<input name="openid.ax.type.old_fullname" '
'type="hidden" value="http://schema.openid.net/namePerson" />'
,
'<input name="openid.identity" '
'type="hidden" value="http://specs.openid.net/auth/2.0/identifier_select" />'
,
'<input name="openid.claimed_id" '
'type="hidden" value="http://specs.openid.net/auth/2.0/identifier_select" />'
,
# should work on the test server as well
'<input name="openid.realm" '
'type="hidden" value="http://testserver/" />'
,
):
self
.
assertContains
(
resp
,
expected_input
,
html
=
True
)
# not included here are elements that will vary from run to run:
# not included here are elements that will vary from run to run:
# <input name="openid.return_to" type="hidden" value="http://testserver/openid/complete/?janrain_nonce=2013-01-23T06%3A20%3A17ZaN7j6H" />
# <input name="openid.return_to" type="hidden"
# value="http://testserver/openid/complete/?janrain_nonce=2013-01-23T06%3A20%3A17ZaN7j6H" />
# <input name="openid.assoc_handle" type="hidden" value="{HMAC-SHA1}{50ff8120}{rh87+Q==}" />
# <input name="openid.assoc_handle" type="hidden" value="{HMAC-SHA1}{50ff8120}{rh87+Q==}" />
def
attempt_login
(
self
,
expected_code
,
login_method
=
'POST'
,
**
kwargs
):
def
attempt_login
(
self
,
expected_code
,
login_method
=
'POST'
,
**
kwargs
):
...
...
common
/djangoapps/external_auth/tests/test_shib.py
→
openedx/core
/djangoapps/external_auth/tests/test_shib.py
View file @
fd49f88e
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
#pylint: disable=no-member
"""
"""
Tests for Shibboleth Authentication
Tests for Shibboleth Authentication
@jbau
@jbau
...
@@ -14,8 +15,8 @@ from django.test.utils import override_settings
...
@@ -14,8 +15,8 @@ from django.test.utils import override_settings
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
django.contrib.auth.models
import
AnonymousUser
,
User
from
django.contrib.auth.models
import
AnonymousUser
,
User
from
importlib
import
import_module
from
importlib
import
import_module
from
external_auth.models
import
ExternalAuthMap
from
openedx.core.djangoapps.
external_auth.models
import
ExternalAuthMap
from
external_auth.views
import
(
from
openedx.core.djangoapps.
external_auth.views
import
(
shib_login
,
course_specific_login
,
course_specific_register
,
_flatten_to_ascii
shib_login
,
course_specific_login
,
course_specific_register
,
_flatten_to_ascii
)
)
from
mock
import
patch
from
mock
import
patch
...
@@ -125,6 +126,7 @@ class ShibSPTest(CacheIsolationTestCase):
...
@@ -125,6 +126,7 @@ class ShibSPTest(CacheIsolationTestCase):
of an existing user that already has an ExternalAuthMap causes an error (403)
of an existing user that already has an ExternalAuthMap causes an error (403)
* shib credentials that do not match an existing ExternalAuthMap causes the registration form to appear
* shib credentials that do not match an existing ExternalAuthMap causes the registration form to appear
"""
"""
# pylint: disable=too-many-statements
user_w_map
=
UserFactory
.
create
(
email
=
'withmap@stanford.edu'
)
user_w_map
=
UserFactory
.
create
(
email
=
'withmap@stanford.edu'
)
extauth
=
ExternalAuthMap
(
external_id
=
'withmap@stanford.edu'
,
extauth
=
ExternalAuthMap
(
external_id
=
'withmap@stanford.edu'
,
...
@@ -155,7 +157,7 @@ class ShibSPTest(CacheIsolationTestCase):
...
@@ -155,7 +157,7 @@ class ShibSPTest(CacheIsolationTestCase):
for
remote_user
in
remote_users
:
for
remote_user
in
remote_users
:
self
.
client
.
logout
()
self
.
client
.
logout
()
with
patch
(
'external_auth.views.AUDIT_LOG'
)
as
mock_audit_log
:
with
patch
(
'
openedx.core.djangoapps.
external_auth.views.AUDIT_LOG'
)
as
mock_audit_log
:
response
=
self
.
client
.
get
(
response
=
self
.
client
.
get
(
reverse
(
'shib-login'
),
reverse
(
'shib-login'
),
**
{
**
{
...
@@ -214,7 +216,7 @@ class ShibSPTest(CacheIsolationTestCase):
...
@@ -214,7 +216,7 @@ class ShibSPTest(CacheIsolationTestCase):
# no audit logging calls
# no audit logging calls
self
.
assertEquals
(
len
(
audit_log_calls
),
0
)
self
.
assertEquals
(
len
(
audit_log_calls
),
0
)
def
_
base_test_extauth
_auto_activate_user_with_flag
(
self
,
log_user_string
=
"inactive@stanford.edu"
):
def
_
test
_auto_activate_user_with_flag
(
self
,
log_user_string
=
"inactive@stanford.edu"
):
"""
"""
Tests that FEATURES['BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'] means extauth automatically
Tests that FEATURES['BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'] means extauth automatically
linked users, activates them, and logs them in
linked users, activates them, and logs them in
...
@@ -231,7 +233,7 @@ class ShibSPTest(CacheIsolationTestCase):
...
@@ -231,7 +233,7 @@ class ShibSPTest(CacheIsolationTestCase):
})
})
request
.
user
=
AnonymousUser
()
request
.
user
=
AnonymousUser
()
with
patch
(
'external_auth.views.AUDIT_LOG'
)
as
mock_audit_log
:
with
patch
(
'
openedx.core.djangoapps.
external_auth.views.AUDIT_LOG'
)
as
mock_audit_log
:
response
=
shib_login
(
request
)
response
=
shib_login
(
request
)
audit_log_calls
=
mock_audit_log
.
method_calls
audit_log_calls
=
mock_audit_log
.
method_calls
# reload user from db, since the view function works via db side-effects
# reload user from db, since the view function works via db side-effects
...
@@ -256,7 +258,7 @@ class ShibSPTest(CacheIsolationTestCase):
...
@@ -256,7 +258,7 @@ class ShibSPTest(CacheIsolationTestCase):
"""
"""
Wrapper to run base_test_extauth_auto_activate_user_with_flag with {'SQUELCH_PII_IN_LOGS': False}
Wrapper to run base_test_extauth_auto_activate_user_with_flag with {'SQUELCH_PII_IN_LOGS': False}
"""
"""
self
.
_
base_test_extauth
_auto_activate_user_with_flag
(
log_user_string
=
"inactive@stanford.edu"
)
self
.
_
test
_auto_activate_user_with_flag
(
log_user_string
=
"inactive@stanford.edu"
)
@unittest.skipUnless
(
settings
.
FEATURES
.
get
(
'AUTH_USE_SHIB'
),
"AUTH_USE_SHIB not set"
)
@unittest.skipUnless
(
settings
.
FEATURES
.
get
(
'AUTH_USE_SHIB'
),
"AUTH_USE_SHIB not set"
)
@patch.dict
(
settings
.
FEATURES
,
{
'BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'
:
True
,
'SQUELCH_PII_IN_LOGS'
:
True
})
@patch.dict
(
settings
.
FEATURES
,
{
'BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'
:
True
,
'SQUELCH_PII_IN_LOGS'
:
True
})
...
@@ -264,7 +266,7 @@ class ShibSPTest(CacheIsolationTestCase):
...
@@ -264,7 +266,7 @@ class ShibSPTest(CacheIsolationTestCase):
"""
"""
Wrapper to run base_test_extauth_auto_activate_user_with_flag with {'SQUELCH_PII_IN_LOGS': True}
Wrapper to run base_test_extauth_auto_activate_user_with_flag with {'SQUELCH_PII_IN_LOGS': True}
"""
"""
self
.
_
base_test_extauth
_auto_activate_user_with_flag
(
log_user_string
=
"user.id: 1"
)
self
.
_
test
_auto_activate_user_with_flag
(
log_user_string
=
"user.id: 1"
)
@unittest.skipUnless
(
settings
.
FEATURES
.
get
(
'AUTH_USE_SHIB'
),
"AUTH_USE_SHIB not set"
)
@unittest.skipUnless
(
settings
.
FEATURES
.
get
(
'AUTH_USE_SHIB'
),
"AUTH_USE_SHIB not set"
)
@data
(
*
gen_all_identities
())
@data
(
*
gen_all_identities
())
...
@@ -279,11 +281,11 @@ class ShibSPTest(CacheIsolationTestCase):
...
@@ -279,11 +281,11 @@ class ShibSPTest(CacheIsolationTestCase):
response
=
client
.
get
(
path
=
'/shib-login/'
,
data
=
{},
follow
=
False
,
**
identity
)
response
=
client
.
get
(
path
=
'/shib-login/'
,
data
=
{},
follow
=
False
,
**
identity
)
self
.
assertEquals
(
response
.
status_code
,
200
)
self
.
assertEquals
(
response
.
status_code
,
200
)
mail_input_
HTML
=
'<input class="" id="email" type="email" name="email"'
mail_input_
html
=
'<input class="" id="email" type="email" name="email"'
if
not
identity
.
get
(
'mail'
):
if
not
identity
.
get
(
'mail'
):
self
.
assertContains
(
response
,
mail_input_
HTML
)
self
.
assertContains
(
response
,
mail_input_
html
)
else
:
else
:
self
.
assertNotContains
(
response
,
mail_input_
HTML
)
self
.
assertNotContains
(
response
,
mail_input_
html
)
sn_empty
=
not
identity
.
get
(
'sn'
)
sn_empty
=
not
identity
.
get
(
'sn'
)
given_name_empty
=
not
identity
.
get
(
'givenName'
)
given_name_empty
=
not
identity
.
get
(
'givenName'
)
displayname_empty
=
not
identity
.
get
(
'displayName'
)
displayname_empty
=
not
identity
.
get
(
'displayName'
)
...
...
common
/djangoapps/external_auth/tests/test_ssl.py
→
openedx/core
/djangoapps/external_auth/tests/test_ssl.py
View file @
fd49f88e
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
Provides unit tests for SSL based authentication portions
Provides unit tests for SSL based authentication portions
of the external_auth app.
of the external_auth app.
"""
"""
# pylint: disable=no-member
import
copy
import
copy
import
unittest
import
unittest
...
@@ -14,10 +15,10 @@ from django.core.urlresolvers import reverse
...
@@ -14,10 +15,10 @@ from django.core.urlresolvers import reverse
from
django.test.client
import
Client
from
django.test.client
import
Client
from
django.test.client
import
RequestFactory
from
django.test.client
import
RequestFactory
from
django.test.utils
import
override_settings
from
django.test.utils
import
override_settings
from
external_auth.models
import
ExternalAuthMap
import
external_auth.views
from
mock
import
Mock
,
patch
from
mock
import
Mock
,
patch
from
openedx.core.djangoapps.external_auth.models
import
ExternalAuthMap
import
openedx.core.djangoapps.external_auth.views
as
external_auth_views
from
student.models
import
CourseEnrollment
from
student.models
import
CourseEnrollment
from
student.roles
import
CourseStaffRole
from
student.roles
import
CourseStaffRole
from
student.tests.factories
import
UserFactory
from
student.tests.factories
import
UserFactory
...
@@ -87,7 +88,7 @@ class SSLClientTest(ModuleStoreTestCase):
...
@@ -87,7 +88,7 @@ class SSLClientTest(ModuleStoreTestCase):
redirects them to the signup page.
redirects them to the signup page.
"""
"""
with
self
.
_create_ssl_request
(
'/'
)
as
request
:
with
self
.
_create_ssl_request
(
'/'
)
as
request
:
response
=
external_auth
.
views
.
ssl_login
(
request
)
response
=
external_auth
_
views
.
ssl_login
(
request
)
# Response should contain template for signup form, eamap should have user, and internal
# Response should contain template for signup form, eamap should have user, and internal
# auth should not have a user
# auth should not have a user
...
@@ -127,7 +128,7 @@ class SSLClientTest(ModuleStoreTestCase):
...
@@ -127,7 +128,7 @@ class SSLClientTest(ModuleStoreTestCase):
and the user is redirected to slash.
and the user is redirected to slash.
"""
"""
with
self
.
_create_ssl_request
(
'/'
)
as
request
:
with
self
.
_create_ssl_request
(
'/'
)
as
request
:
external_auth
.
views
.
ssl_login
(
request
)
external_auth
_
views
.
ssl_login
(
request
)
# Assert our user exists in both eamap and Users, and that we are logged in
# Assert our user exists in both eamap and Users, and that we are logged in
try
:
try
:
...
@@ -250,7 +251,7 @@ class SSLClientTest(ModuleStoreTestCase):
...
@@ -250,7 +251,7 @@ class SSLClientTest(ModuleStoreTestCase):
# Create account, break internal password, and activate account
# Create account, break internal password, and activate account
with
self
.
_create_ssl_request
(
'/'
)
as
request
:
with
self
.
_create_ssl_request
(
'/'
)
as
request
:
external_auth
.
views
.
ssl_login
(
request
)
external_auth
_
views
.
ssl_login
(
request
)
user
=
User
.
objects
.
get
(
email
=
self
.
USER_EMAIL
)
user
=
User
.
objects
.
get
(
email
=
self
.
USER_EMAIL
)
user
.
set_password
(
'not autogenerated'
)
user
.
set_password
(
'not autogenerated'
)
user
.
is_active
=
True
user
.
is_active
=
True
...
@@ -267,7 +268,7 @@ class SSLClientTest(ModuleStoreTestCase):
...
@@ -267,7 +268,7 @@ class SSLClientTest(ModuleStoreTestCase):
def
test_ssl_decorator_no_certs
(
self
):
def
test_ssl_decorator_no_certs
(
self
):
"""Make sure no external auth happens without SSL enabled"""
"""Make sure no external auth happens without SSL enabled"""
dec_mock
=
external_auth
.
views
.
ssl_login_shortcut
(
self
.
mock
)
dec_mock
=
external_auth
_
views
.
ssl_login_shortcut
(
self
.
mock
)
with
self
.
_create_normal_request
(
self
.
MOCK_URL
)
as
request
:
with
self
.
_create_normal_request
(
self
.
MOCK_URL
)
as
request
:
request
.
user
=
AnonymousUser
()
request
.
user
=
AnonymousUser
()
...
@@ -282,7 +283,7 @@ class SSLClientTest(ModuleStoreTestCase):
...
@@ -282,7 +283,7 @@ class SSLClientTest(ModuleStoreTestCase):
def
test_ssl_login_decorator
(
self
):
def
test_ssl_login_decorator
(
self
):
"""Create mock function to test ssl login decorator"""
"""Create mock function to test ssl login decorator"""
dec_mock
=
external_auth
.
views
.
ssl_login_shortcut
(
self
.
mock
)
dec_mock
=
external_auth
_
views
.
ssl_login_shortcut
(
self
.
mock
)
# Test that anonymous without cert doesn't create authmap
# Test that anonymous without cert doesn't create authmap
with
self
.
_create_normal_request
(
self
.
MOCK_URL
)
as
request
:
with
self
.
_create_normal_request
(
self
.
MOCK_URL
)
as
request
:
...
@@ -312,7 +313,7 @@ class SSLClientTest(ModuleStoreTestCase):
...
@@ -312,7 +313,7 @@ class SSLClientTest(ModuleStoreTestCase):
will bypass registration and call retfun.
will bypass registration and call retfun.
"""
"""
dec_mock
=
external_auth
.
views
.
ssl_login_shortcut
(
self
.
mock
)
dec_mock
=
external_auth
_
views
.
ssl_login_shortcut
(
self
.
mock
)
with
self
.
_create_ssl_request
(
self
.
MOCK_URL
)
as
request
:
with
self
.
_create_ssl_request
(
self
.
MOCK_URL
)
as
request
:
dec_mock
(
request
)
dec_mock
(
request
)
...
@@ -343,7 +344,7 @@ class SSLClientTest(ModuleStoreTestCase):
...
@@ -343,7 +344,7 @@ class SSLClientTest(ModuleStoreTestCase):
)
)
with
self
.
_create_ssl_request
(
'/'
)
as
request
:
with
self
.
_create_ssl_request
(
'/'
)
as
request
:
external_auth
.
views
.
ssl_login
(
request
)
external_auth
_
views
.
ssl_login
(
request
)
user
=
User
.
objects
.
get
(
email
=
self
.
USER_EMAIL
)
user
=
User
.
objects
.
get
(
email
=
self
.
USER_EMAIL
)
CourseEnrollment
.
enroll
(
user
,
course
.
id
)
CourseEnrollment
.
enroll
(
user
,
course
.
id
)
course_private_url
=
'/courses/MITx/999/Robot_Super_Course/courseware'
course_private_url
=
'/courses/MITx/999/Robot_Super_Course/courseware'
...
@@ -374,7 +375,7 @@ class SSLClientTest(ModuleStoreTestCase):
...
@@ -374,7 +375,7 @@ class SSLClientTest(ModuleStoreTestCase):
)
)
with
self
.
_create_ssl_request
(
'/'
)
as
request
:
with
self
.
_create_ssl_request
(
'/'
)
as
request
:
external_auth
.
views
.
ssl_login
(
request
)
external_auth
_
views
.
ssl_login
(
request
)
user
=
User
.
objects
.
get
(
email
=
self
.
USER_EMAIL
)
user
=
User
.
objects
.
get
(
email
=
self
.
USER_EMAIL
)
CourseEnrollment
.
enroll
(
user
,
course
.
id
)
CourseEnrollment
.
enroll
(
user
,
course
.
id
)
...
...
common
/djangoapps/external_auth/views.py
→
openedx/core
/djangoapps/external_auth/views.py
View file @
fd49f88e
"""
External Auth Views
"""
import
functools
import
functools
import
json
import
json
import
logging
import
logging
...
@@ -9,8 +12,8 @@ import unicodedata
...
@@ -9,8 +12,8 @@ import unicodedata
import
urllib
import
urllib
from
textwrap
import
dedent
from
textwrap
import
dedent
from
external_auth.models
import
ExternalAuthMap
from
openedx.core.djangoapps.
external_auth.models
import
ExternalAuthMap
from
external_auth.djangostore
import
DjangoOpenIDStore
from
openedx.core.djangoapps.
external_auth.djangostore
import
DjangoOpenIDStore
from
django.conf
import
settings
from
django.conf
import
settings
from
django.contrib.auth
import
REDIRECT_FIELD_NAME
,
authenticate
,
login
from
django.contrib.auth
import
REDIRECT_FIELD_NAME
,
authenticate
,
login
...
@@ -31,11 +34,7 @@ from django.shortcuts import redirect
...
@@ -31,11 +34,7 @@ from django.shortcuts import redirect
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
edxmako.shortcuts
import
render_to_response
,
render_to_string
from
edxmako.shortcuts
import
render_to_response
,
render_to_string
try
:
from
django.views.decorators.csrf
import
csrf_exempt
,
ensure_csrf_cookie
from
django.views.decorators.csrf
import
csrf_exempt
except
ImportError
:
from
django.contrib.csrf.middleware
import
csrf_exempt
from
django.views.decorators.csrf
import
ensure_csrf_cookie
import
django_openid_auth.views
as
openid_views
import
django_openid_auth.views
as
openid_views
from
django_openid_auth
import
auth
as
openid_auth
from
django_openid_auth
import
auth
as
openid_auth
...
@@ -62,7 +61,7 @@ OPENID_DOMAIN_PREFIX = settings.OPENID_DOMAIN_PREFIX
...
@@ -62,7 +61,7 @@ OPENID_DOMAIN_PREFIX = settings.OPENID_DOMAIN_PREFIX
@csrf_exempt
@csrf_exempt
def
default_render_failure
(
request
,
def
default_render_failure
(
request
,
# pylint: disable=unused-argument
message
,
message
,
status
=
403
,
status
=
403
,
template_name
=
'extauth_failure.html'
,
template_name
=
'extauth_failure.html'
,
...
@@ -90,7 +89,7 @@ def generate_password(length=12, chars=string.letters + string.digits):
...
@@ -90,7 +89,7 @@ def generate_password(length=12, chars=string.letters + string.digits):
@csrf_exempt
@csrf_exempt
def
openid_login_complete
(
request
,
def
openid_login_complete
(
request
,
redirect_field_name
=
REDIRECT_FIELD_NAME
,
redirect_field_name
=
REDIRECT_FIELD_NAME
,
# pylint: disable=unused-argument
render_failure
=
None
):
render_failure
=
None
):
"""Complete the openid login process"""
"""Complete the openid login process"""
...
@@ -104,7 +103,7 @@ def openid_login_complete(request,
...
@@ -104,7 +103,7 @@ def openid_login_complete(request,
if
openid_response
.
status
==
SUCCESS
:
if
openid_response
.
status
==
SUCCESS
:
external_id
=
openid_response
.
identity_url
external_id
=
openid_response
.
identity_url
oid_backend
=
openid_auth
.
OpenIDBackend
()
oid_backend
=
openid_auth
.
OpenIDBackend
()
details
=
oid_backend
.
_extract_user_details
(
openid_response
)
details
=
oid_backend
.
_extract_user_details
(
openid_response
)
# pylint: disable=protected-access
log
.
debug
(
'openid success, details=
%
s'
,
details
)
log
.
debug
(
'openid success, details=
%
s'
,
details
)
...
@@ -134,6 +133,7 @@ def _external_login_or_signup(request,
...
@@ -134,6 +133,7 @@ def _external_login_or_signup(request,
fullname
,
fullname
,
retfun
=
None
):
retfun
=
None
):
"""Generic external auth login or signup"""
"""Generic external auth login or signup"""
# pylint: disable=too-many-statements
# see if we have a map from this external_id to an edX username
# see if we have a map from this external_id to an edX username
try
:
try
:
eamap
=
ExternalAuthMap
.
objects
.
get
(
external_id
=
external_id
,
eamap
=
ExternalAuthMap
.
objects
.
get
(
external_id
=
external_id
,
...
@@ -300,7 +300,8 @@ def _signup(request, eamap, retfun=None):
...
@@ -300,7 +300,8 @@ def _signup(request, eamap, retfun=None):
# but this only affects username, not fullname
# but this only affects username, not fullname
username
=
re
.
sub
(
r'\s'
,
''
,
_flatten_to_ascii
(
eamap
.
external_name
),
flags
=
re
.
UNICODE
)
username
=
re
.
sub
(
r'\s'
,
''
,
_flatten_to_ascii
(
eamap
.
external_name
),
flags
=
re
.
UNICODE
)
context
=
{
'has_extauth_info'
:
True
,
context
=
{
'has_extauth_info'
:
True
,
'show_signup_immediately'
:
True
,
'show_signup_immediately'
:
True
,
'extauth_domain'
:
eamap
.
external_domain
,
'extauth_domain'
:
eamap
.
external_domain
,
'extauth_id'
:
eamap
.
external_id
,
'extauth_id'
:
eamap
.
external_id
,
...
@@ -343,17 +344,17 @@ def _ssl_dn_extract_info(dn_string):
...
@@ -343,17 +344,17 @@ def _ssl_dn_extract_info(dn_string):
full name from the SSL DN string. Return (user,email,fullname) if
full name from the SSL DN string. Return (user,email,fullname) if
successful, and None otherwise.
successful, and None otherwise.
"""
"""
s
s
=
re
.
search
(
'/emailAddress=(.*)@([^/]+)'
,
dn_string
)
s
earch_string
=
re
.
search
(
'/emailAddress=(.*)@([^/]+)'
,
dn_string
)
if
s
s
:
if
s
earch_string
:
user
=
s
s
.
group
(
1
)
user
=
s
earch_string
.
group
(
1
)
email
=
"
%
s@
%
s"
%
(
user
,
s
s
.
group
(
2
))
email
=
"
%
s@
%
s"
%
(
user
,
s
earch_string
.
group
(
2
))
else
:
else
:
r
eturn
None
r
aise
ValueError
s
s
=
re
.
search
(
'/CN=([^/]+)/'
,
dn_string
)
s
earch_string
=
re
.
search
(
'/CN=([^/]+)/'
,
dn_string
)
if
s
s
:
if
s
earch_string
:
fullname
=
s
s
.
group
(
1
)
fullname
=
s
earch_string
.
group
(
1
)
else
:
else
:
r
eturn
None
r
aise
ValueError
return
(
user
,
email
,
fullname
)
return
(
user
,
email
,
fullname
)
...
@@ -370,14 +371,14 @@ def ssl_get_cert_from_request(request):
...
@@ -370,14 +371,14 @@ def ssl_get_cert_from_request(request):
if
not
cert
:
if
not
cert
:
try
:
try
:
# try the direct apache2 SSL key
# try the direct apache2 SSL key
cert
=
request
.
_req
.
subprocess_env
.
get
(
certkey
,
''
)
cert
=
request
.
_req
.
subprocess_env
.
get
(
certkey
,
''
)
# pylint: disable=protected-access
except
Exception
:
except
Exception
:
# pylint: disable=broad-except
return
''
return
''
return
cert
return
cert
def
ssl_login_shortcut
(
f
n
):
def
ssl_login_shortcut
(
f
unc
):
"""
"""
Python function decorator for login procedures, to allow direct login
Python function decorator for login procedures, to allow direct login
based on existing ExternalAuth record and MIT ssl certificate.
based on existing ExternalAuth record and MIT ssl certificate.
...
@@ -390,19 +391,19 @@ def ssl_login_shortcut(fn):
...
@@ -390,19 +391,19 @@ def ssl_login_shortcut(fn):
"""
"""
if
not
settings
.
FEATURES
[
'AUTH_USE_CERTIFICATES'
]:
if
not
settings
.
FEATURES
[
'AUTH_USE_CERTIFICATES'
]:
return
f
n
(
*
args
,
**
kwargs
)
return
f
unc
(
*
args
,
**
kwargs
)
request
=
args
[
0
]
request
=
args
[
0
]
if
request
.
user
and
request
.
user
.
is_authenticated
():
# don't re-authenticate
if
request
.
user
and
request
.
user
.
is_authenticated
():
# don't re-authenticate
return
f
n
(
*
args
,
**
kwargs
)
return
f
unc
(
*
args
,
**
kwargs
)
cert
=
ssl_get_cert_from_request
(
request
)
cert
=
ssl_get_cert_from_request
(
request
)
if
not
cert
:
# no certificate information - show normal login window
if
not
cert
:
# no certificate information - show normal login window
return
f
n
(
*
args
,
**
kwargs
)
return
f
unc
(
*
args
,
**
kwargs
)
def
retfun
():
def
retfun
():
"""Wrap function again for call by _external_login_or_signup"""
"""Wrap function again for call by _external_login_or_signup"""
return
f
n
(
*
args
,
**
kwargs
)
return
f
unc
(
*
args
,
**
kwargs
)
(
_user
,
email
,
fullname
)
=
_ssl_dn_extract_info
(
cert
)
(
_user
,
email
,
fullname
)
=
_ssl_dn_extract_info
(
cert
)
return
_external_login_or_signup
(
return
_external_login_or_signup
(
...
@@ -634,6 +635,9 @@ def get_xrds_url(resource, request):
...
@@ -634,6 +635,9 @@ def get_xrds_url(resource, request):
def
add_openid_simple_registration
(
request
,
response
,
data
):
def
add_openid_simple_registration
(
request
,
response
,
data
):
"""
Add simple registration fields to the response if requested.
"""
sreg_data
=
{}
sreg_data
=
{}
sreg_request
=
sreg
.
SRegRequest
.
fromOpenIDRequest
(
request
)
sreg_request
=
sreg
.
SRegRequest
.
fromOpenIDRequest
(
request
)
sreg_fields
=
sreg_request
.
allRequestedFields
()
sreg_fields
=
sreg_request
.
allRequestedFields
()
...
@@ -655,6 +659,9 @@ def add_openid_simple_registration(request, response, data):
...
@@ -655,6 +659,9 @@ def add_openid_simple_registration(request, response, data):
def
add_openid_attribute_exchange
(
request
,
response
,
data
):
def
add_openid_attribute_exchange
(
request
,
response
,
data
):
"""
Add attribute exchange fields to the response if requested.
"""
try
:
try
:
ax_request
=
ax
.
FetchRequest
.
fromOpenIDRequest
(
request
)
ax_request
=
ax
.
FetchRequest
.
fromOpenIDRequest
(
request
)
except
ax
.
AXError
:
except
ax
.
AXError
:
...
@@ -691,8 +698,8 @@ def provider_respond(server, request, response, data):
...
@@ -691,8 +698,8 @@ def provider_respond(server, request, response, data):
http_response
.
status_code
=
webresponse
.
code
http_response
.
status_code
=
webresponse
.
code
# add OpenID headers to response
# add OpenID headers to response
for
k
,
v
in
webresponse
.
headers
.
iteritems
():
for
k
ey
,
val
in
webresponse
.
headers
.
iteritems
():
http_response
[
k
]
=
v
http_response
[
k
ey
]
=
val
return
http_response
return
http_response
...
@@ -744,7 +751,7 @@ def provider_login(request):
...
@@ -744,7 +751,7 @@ def provider_login(request):
"""
"""
OpenID login endpoint
OpenID login endpoint
"""
"""
# pylint: disable=too-many-statements
# make and validate endpoint
# make and validate endpoint
endpoint
=
get_xrds_url
(
'login'
,
request
)
endpoint
=
get_xrds_url
(
'login'
,
request
)
if
not
endpoint
:
if
not
endpoint
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment