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
7f2c956e
Commit
7f2c956e
authored
Nov 06, 2015
by
Fred Smith
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #560 from edx-solutions/rc/2015-11-05
Rc/2015 11 05
parents
15265445
2b0976f5
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
156 additions
and
313 deletions
+156
-313
common/djangoapps/student/views.py
+9
-22
common/djangoapps/third_party_auth/migrations/0005_auto__del_field_samlproviderconfig_autoprovision_account__del_field_oa.py
+130
-0
common/djangoapps/third_party_auth/models.py
+0
-9
common/djangoapps/third_party_auth/pipeline.py
+4
-52
common/djangoapps/third_party_auth/settings.py
+2
-1
common/djangoapps/third_party_auth/strategy.py
+0
-45
common/djangoapps/third_party_auth/tests/specs/test_testshib.py
+5
-55
common/djangoapps/third_party_auth/tests/test_pipeline.py
+0
-37
common/djangoapps/third_party_auth/tests/test_strategy.py
+0
-74
lms/envs/aws.py
+0
-8
lms/envs/test.py
+0
-3
requirements/edx/custom.txt
+4
-5
requirements/edx/github.txt
+2
-2
No files found.
common/djangoapps/student/views.py
View file @
7f2c956e
...
@@ -1357,22 +1357,11 @@ def change_setting(request):
...
@@ -1357,22 +1357,11 @@ def change_setting(request):
class
AccountValidationError
(
Exception
):
class
AccountValidationError
(
Exception
):
""" Exception thrown if some account validation error happened """
def
__init__
(
self
,
message
,
field
):
def
__init__
(
self
,
message
,
field
):
super
(
AccountValidationError
,
self
)
.
__init__
(
message
)
super
(
AccountValidationError
,
self
)
.
__init__
(
message
)
self
.
field
=
field
self
.
field
=
field
class
AccountUserNameValidationError
(
AccountValidationError
):
""" Exception thrown if attempted to create account with username already taken """
pass
class
AccountEmailAlreadyExistsValidationError
(
AccountValidationError
):
""" Exception thrown if attempted to create account with email already used by other account """
pass
@receiver
(
post_save
,
sender
=
User
)
@receiver
(
post_save
,
sender
=
User
)
def
user_signup_handler
(
sender
,
**
kwargs
):
# pylint: disable=unused-argument
def
user_signup_handler
(
sender
,
**
kwargs
):
# pylint: disable=unused-argument
"""
"""
...
@@ -1414,12 +1403,12 @@ def _do_create_account(form):
...
@@ -1414,12 +1403,12 @@ def _do_create_account(form):
except
IntegrityError
:
except
IntegrityError
:
# Figure out the cause of the integrity error
# Figure out the cause of the integrity error
if
len
(
User
.
objects
.
filter
(
username
=
user
.
username
))
>
0
:
if
len
(
User
.
objects
.
filter
(
username
=
user
.
username
))
>
0
:
raise
Account
UserName
ValidationError
(
raise
AccountValidationError
(
_
(
"An account with the Public Username '{username}' already exists."
)
.
format
(
username
=
user
.
username
),
_
(
"An account with the Public Username '{username}' already exists."
)
.
format
(
username
=
user
.
username
),
field
=
"username"
field
=
"username"
)
)
elif
len
(
User
.
objects
.
filter
(
email
=
user
.
email
))
>
0
:
elif
len
(
User
.
objects
.
filter
(
email
=
user
.
email
))
>
0
:
raise
Account
EmailAlreadyExists
ValidationError
(
raise
AccountValidationError
(
_
(
"An account with the Email '{email}' already exists."
)
.
format
(
email
=
user
.
email
),
_
(
"An account with the Email '{email}' already exists."
)
.
format
(
email
=
user
.
email
),
field
=
"email"
field
=
"email"
)
)
...
@@ -1454,7 +1443,7 @@ def _do_create_account(form):
...
@@ -1454,7 +1443,7 @@ def _do_create_account(form):
# pylint: disable=too-many-statements
# pylint: disable=too-many-statements
def
create_account_with_params
(
request
,
params
,
skip_email
=
False
):
def
create_account_with_params
(
request
,
params
):
"""
"""
Given a request and a dict of parameters (which may or may not have come
Given a request and a dict of parameters (which may or may not have come
from the request), create an account for the requesting user, including
from the request), create an account for the requesting user, including
...
@@ -1548,8 +1537,7 @@ def create_account_with_params(request, params, skip_email=False):
...
@@ -1548,8 +1537,7 @@ def create_account_with_params(request, params, skip_email=False):
(
user
,
profile
,
registration
)
=
_do_create_account
(
form
)
(
user
,
profile
,
registration
)
=
_do_create_account
(
form
)
# next, link the account with social auth, if provided via the API.
# next, link the account with social auth, if provided via the API.
# (If the user is using the normal register page or account is automatically provisioned,
# (If the user is using the normal register page, the social auth pipeline does the linking, not this code)
# the social auth pipeline does the linking, not this code)
if
should_link_with_social_auth
:
if
should_link_with_social_auth
:
backend_name
=
params
[
'provider'
]
backend_name
=
params
[
'provider'
]
request
.
social_strategy
=
social_utils
.
load_strategy
(
request
)
request
.
social_strategy
=
social_utils
.
load_strategy
(
request
)
...
@@ -1633,12 +1621,11 @@ def create_account_with_params(request, params, skip_email=False):
...
@@ -1633,12 +1621,11 @@ def create_account_with_params(request, params, skip_email=False):
# the other for *new* systems. we need to be careful about
# the other for *new* systems. we need to be careful about
# changing settings on a running system to make sure no users are
# changing settings on a running system to make sure no users are
# left in an inconsistent state (or doing a migration if they are).
# left in an inconsistent state (or doing a migration if they are).
send_email
=
not
(
send_email
=
(
skip_email
or
not
settings
.
FEATURES
.
get
(
'SKIP_EMAIL_VALIDATION'
,
None
)
and
settings
.
FEATURES
.
get
(
'SKIP_EMAIL_VALIDATION'
,
False
)
or
not
settings
.
FEATURES
.
get
(
'AUTOMATIC_AUTH_FOR_TESTING'
)
and
settings
.
FEATURES
.
get
(
'AUTOMATIC_AUTH_FOR_TESTING'
,
False
)
or
not
(
do_external_auth
and
settings
.
FEATURES
.
get
(
'BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'
))
and
(
do_external_auth
and
settings
.
FEATURES
.
get
(
'BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'
))
or
not
(
(
third_party_provider
and
third_party_provider
.
skip_email_verification
and
third_party_provider
and
third_party_provider
.
skip_email_verification
and
user
.
email
==
running_pipeline
[
'kwargs'
]
.
get
(
'details'
,
{})
.
get
(
'email'
)
user
.
email
==
running_pipeline
[
'kwargs'
]
.
get
(
'details'
,
{})
.
get
(
'email'
)
)
)
...
...
common/djangoapps/third_party_auth/migrations/0005_auto__del_field_samlproviderconfig_autoprovision_account__del_field_oa.py
0 → 100644
View file @
7f2c956e
# -*- coding: utf-8 -*-
from
south.utils
import
datetime_utils
as
datetime
from
south.db
import
db
from
south.v2
import
SchemaMigration
from
django.db
import
models
class
Migration
(
SchemaMigration
):
def
forwards
(
self
,
orm
):
# Deleting field 'SAMLProviderConfig.autoprovision_account'
db
.
delete_column
(
'third_party_auth_samlproviderconfig'
,
'autoprovision_account'
)
# Deleting field 'OAuth2ProviderConfig.autoprovision_account'
db
.
delete_column
(
'third_party_auth_oauth2providerconfig'
,
'autoprovision_account'
)
def
backwards
(
self
,
orm
):
# Adding field 'SAMLProviderConfig.autoprovision_account'
db
.
add_column
(
'third_party_auth_samlproviderconfig'
,
'autoprovision_account'
,
self
.
gf
(
'django.db.models.fields.BooleanField'
)(
default
=
False
),
keep_default
=
False
)
# Adding field 'OAuth2ProviderConfig.autoprovision_account'
db
.
add_column
(
'third_party_auth_oauth2providerconfig'
,
'autoprovision_account'
,
self
.
gf
(
'django.db.models.fields.BooleanField'
)(
default
=
False
),
keep_default
=
False
)
models
=
{
'auth.group'
:
{
'Meta'
:
{
'object_name'
:
'Group'
},
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'80'
}),
'permissions'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Permission']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
})
},
'auth.permission'
:
{
'Meta'
:
{
'ordering'
:
"('content_type__app_label', 'content_type__model', 'codename')"
,
'unique_together'
:
"(('content_type', 'codename'),)"
,
'object_name'
:
'Permission'
},
'codename'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'content_type'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['contenttypes.ContentType']"
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
})
},
'auth.user'
:
{
'Meta'
:
{
'object_name'
:
'User'
},
'date_joined'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'email'
:
(
'django.db.models.fields.EmailField'
,
[],
{
'max_length'
:
'75'
,
'blank'
:
'True'
}),
'first_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'blank'
:
'True'
}),
'groups'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Group']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'is_active'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'True'
}),
'is_staff'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'is_superuser'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'last_login'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'last_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'30'
,
'blank'
:
'True'
}),
'password'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
}),
'user_permissions'
:
(
'django.db.models.fields.related.ManyToManyField'
,
[],
{
'to'
:
"orm['auth.Permission']"
,
'symmetrical'
:
'False'
,
'blank'
:
'True'
}),
'username'
:
(
'django.db.models.fields.CharField'
,
[],
{
'unique'
:
'True'
,
'max_length'
:
'30'
})
},
'contenttypes.contenttype'
:
{
'Meta'
:
{
'ordering'
:
"('name',)"
,
'unique_together'
:
"(('app_label', 'model'),)"
,
'object_name'
:
'ContentType'
,
'db_table'
:
"'django_content_type'"
},
'app_label'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'model'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'100'
})
},
'third_party_auth.oauth2providerconfig'
:
{
'Meta'
:
{
'object_name'
:
'OAuth2ProviderConfig'
},
'backend_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
,
'db_index'
:
'True'
}),
'change_date'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'blank'
:
'True'
}),
'changed_by'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['auth.User']"
,
'null'
:
'True'
,
'on_delete'
:
'models.PROTECT'
}),
'enabled'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'icon_class'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'fa-sign-in'"
,
'max_length'
:
'50'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'key'
:
(
'django.db.models.fields.TextField'
,
[],
{
'blank'
:
'True'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
}),
'other_settings'
:
(
'django.db.models.fields.TextField'
,
[],
{
'blank'
:
'True'
}),
'secondary'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'secret'
:
(
'django.db.models.fields.TextField'
,
[],
{
'blank'
:
'True'
}),
'skip_email_verification'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'skip_registration_form'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
})
},
'third_party_auth.samlconfiguration'
:
{
'Meta'
:
{
'object_name'
:
'SAMLConfiguration'
},
'change_date'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'blank'
:
'True'
}),
'changed_by'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['auth.User']"
,
'null'
:
'True'
,
'on_delete'
:
'models.PROTECT'
}),
'enabled'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'entity_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'http://saml.example.com'"
,
'max_length'
:
'255'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'org_info_str'
:
(
'django.db.models.fields.TextField'
,
[],
{
'default'
:
'
\'
{"en-US": {"url": "http://www.example.com", "displayname": "Example Inc.", "name": "example"}}
\'
'
}),
'other_config_str'
:
(
'django.db.models.fields.TextField'
,
[],
{
'default'
:
'
\'
{
\\
n"SECURITY_CONFIG": {"metadataCacheDuration": 604800, "signMetadata": false}
\\
n}
\'
'
}),
'private_key'
:
(
'django.db.models.fields.TextField'
,
[],
{}),
'public_key'
:
(
'django.db.models.fields.TextField'
,
[],
{})
},
'third_party_auth.samlproviderconfig'
:
{
'Meta'
:
{
'object_name'
:
'SAMLProviderConfig'
},
'attr_email'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'blank'
:
'True'
}),
'attr_first_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'blank'
:
'True'
}),
'attr_full_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'blank'
:
'True'
}),
'attr_last_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'blank'
:
'True'
}),
'attr_user_permanent_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'blank'
:
'True'
}),
'attr_username'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'128'
,
'blank'
:
'True'
}),
'backend_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'tpa-saml'"
,
'max_length'
:
'50'
}),
'change_date'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'auto_now_add'
:
'True'
,
'blank'
:
'True'
}),
'changed_by'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['auth.User']"
,
'null'
:
'True'
,
'on_delete'
:
'models.PROTECT'
}),
'enabled'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'entity_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
}),
'icon_class'
:
(
'django.db.models.fields.CharField'
,
[],
{
'default'
:
"'fa-sign-in'"
,
'max_length'
:
'50'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'idp_slug'
:
(
'django.db.models.fields.SlugField'
,
[],
{
'max_length'
:
'30'
}),
'metadata_source'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
}),
'name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'50'
}),
'other_settings'
:
(
'django.db.models.fields.TextField'
,
[],
{
'blank'
:
'True'
}),
'secondary'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'skip_email_verification'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'skip_registration_form'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
})
},
'third_party_auth.samlproviderdata'
:
{
'Meta'
:
{
'ordering'
:
"('-fetched_at',)"
,
'object_name'
:
'SAMLProviderData'
},
'entity_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'expires_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'null'
:
'True'
,
'db_index'
:
'True'
}),
'fetched_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'public_key'
:
(
'django.db.models.fields.TextField'
,
[],
{}),
'sso_url'
:
(
'django.db.models.fields.URLField'
,
[],
{
'max_length'
:
'200'
})
}
}
complete_apps
=
[
'third_party_auth'
]
\ No newline at end of file
common/djangoapps/third_party_auth/models.py
View file @
7f2c956e
...
@@ -93,15 +93,6 @@ class ProviderConfig(ConfigurationModel):
...
@@ -93,15 +93,6 @@ class ProviderConfig(ConfigurationModel):
"email, and their account will be activated immediately upon registration."
"email, and their account will be activated immediately upon registration."
),
),
)
)
autoprovision_account
=
models
.
BooleanField
(
default
=
False
,
help_text
=
_
(
"If this option is selected, users will not be required to confirm their details even if "
"some required data is missing or fails validation (e.g. duplicate email). Instead, fake or generated "
"values will be used. This setting forces skipping email verification, so 'Skip email verification' "
"setting have no effect."
)
)
prefix
=
None
# used for provider_id. Set to a string value in subclass
prefix
=
None
# used for provider_id. Set to a string value in subclass
backend_name
=
None
# Set to a field or fixed value in subclass
backend_name
=
None
# Set to a field or fixed value in subclass
...
...
common/djangoapps/third_party_auth/pipeline.py
View file @
7f2c956e
...
@@ -77,7 +77,6 @@ from social.apps.django_app.default import models
...
@@ -77,7 +77,6 @@ from social.apps.django_app.default import models
from
social.exceptions
import
AuthException
from
social.exceptions
import
AuthException
from
social.pipeline
import
partial
from
social.pipeline
import
partial
from
social.pipeline.social_auth
import
associate_by_email
from
social.pipeline.social_auth
import
associate_by_email
from
social.pipeline.user
import
create_user
as
social_create_user
import
student
import
student
...
@@ -85,7 +84,6 @@ from logging import getLogger
...
@@ -85,7 +84,6 @@ from logging import getLogger
from
.
import
provider
from
.
import
provider
# These are the query string params you can pass
# These are the query string params you can pass
# to the URL that starts the authentication process.
# to the URL that starts the authentication process.
#
#
...
@@ -194,20 +192,6 @@ class NotActivatedException(AuthException):
...
@@ -194,20 +192,6 @@ class NotActivatedException(AuthException):
)
)
class
EmailAlreadyInUseException
(
AuthException
):
""" Raised when new user account is created with an email already used by another account """
def
__init__
(
self
,
backend
,
email
):
self
.
email
=
email
super
(
EmailAlreadyInUseException
,
self
)
.
__init__
(
backend
,
email
)
def
__str__
(
self
):
return
(
_
(
'Email {email_address} is already used in our system. To link your accounts, '
'sign in now using your {platform_name} password.'
)
.
format
(
email_address
=
self
.
email
,
platform_name
=
settings
.
PLATFORM_NAME
)
)
class
ProviderUserState
(
object
):
class
ProviderUserState
(
object
):
"""Object representing the provider state (attached or not) for a user.
"""Object representing the provider state (attached or not) for a user.
...
@@ -554,34 +538,18 @@ def ensure_user_information(strategy, auth_entry, backend=None, user=None, socia
...
@@ -554,34 +538,18 @@ def ensure_user_information(strategy, auth_entry, backend=None, user=None, socia
"""Redirects to the registration page."""
"""Redirects to the registration page."""
return
redirect
(
AUTH_DISPATCH_URLS
[
AUTH_ENTRY_REGISTER
])
return
redirect
(
AUTH_DISPATCH_URLS
[
AUTH_ENTRY_REGISTER
])
def
get_provider
():
def
should_force_account_creation
():
"""
""" For some third party providers, we auto-create user accounts """
Gets third-party provider for request
current_provider
=
provider
.
Registry
.
get_from_pipeline
({
'backend'
:
backend
.
name
,
'kwargs'
:
kwargs
})
"""
return
provider
.
Registry
.
get_from_pipeline
({
'backend'
:
backend
.
name
,
'kwargs'
:
kwargs
})
def
should_autoprovision_account
():
""" For some third party providers we trust the provider so much that we automatically provision the account """
current_provider
=
get_provider
()
return
current_provider
and
current_provider
.
autoprovision_account
def
autosubmit_registration_form
():
""" For some third party providers, we auto-submit registration forms """
current_provider
=
get_provider
()
return
current_provider
and
current_provider
.
skip_email_verification
return
current_provider
and
current_provider
.
skip_email_verification
if
not
user
:
if
not
user
:
if
should_autoprovision_account
():
# User has authenticated with the third party provider and provider is configured
# to automatically provision edX account, which is done via strategy.create_user in next pipeline step
return
{
'autoprovision'
:
True
}
if
auth_entry
in
[
AUTH_ENTRY_LOGIN_API
,
AUTH_ENTRY_REGISTER_API
]:
if
auth_entry
in
[
AUTH_ENTRY_LOGIN_API
,
AUTH_ENTRY_REGISTER_API
]:
return
HttpResponseBadRequest
()
return
HttpResponseBadRequest
()
elif
auth_entry
in
[
AUTH_ENTRY_LOGIN
,
AUTH_ENTRY_LOGIN_2
]:
elif
auth_entry
in
[
AUTH_ENTRY_LOGIN
,
AUTH_ENTRY_LOGIN_2
]:
# User has authenticated with the third party provider but we don't know which edX
# User has authenticated with the third party provider but we don't know which edX
# account corresponds to them yet, if any.
# account corresponds to them yet, if any.
if
autosubmit_registration_form
():
if
should_force_account_creation
():
return
dispatch_to_register
()
return
dispatch_to_register
()
return
dispatch_to_login
()
return
dispatch_to_login
()
elif
auth_entry
in
[
AUTH_ENTRY_REGISTER
,
AUTH_ENTRY_REGISTER_2
]:
elif
auth_entry
in
[
AUTH_ENTRY_REGISTER
,
AUTH_ENTRY_REGISTER_2
]:
...
@@ -625,22 +593,6 @@ def ensure_user_information(strategy, auth_entry, backend=None, user=None, socia
...
@@ -625,22 +593,6 @@ def ensure_user_information(strategy, auth_entry, backend=None, user=None, socia
@partial.partial
@partial.partial
def
create_user
(
strategy
,
details
,
user
=
None
,
*
args
,
**
kwargs
):
"""
Substitution method for stock social create_user that catches email validation error and redirects to login
"""
from
student.views
import
AccountEmailAlreadyExistsValidationError
try
:
return
social_create_user
(
strategy
,
details
,
user
,
*
args
,
**
kwargs
)
except
AccountEmailAlreadyExistsValidationError
as
exc
:
logger
.
exception
(
exc
.
message
)
# We're raising an exception that inherits from AuthException. Such exceptions are properly handled
# by social auth pipeline: their string representation (see __str__ method) is displayed to user on the page
# we're redirecting to.
raise
EmailAlreadyInUseException
(
exc
.
message
,
details
[
'email'
])
@partial.partial
def
set_logged_in_cookies
(
backend
=
None
,
user
=
None
,
strategy
=
None
,
auth_entry
=
None
,
*
args
,
**
kwargs
):
def
set_logged_in_cookies
(
backend
=
None
,
user
=
None
,
strategy
=
None
,
auth_entry
=
None
,
*
args
,
**
kwargs
):
"""This pipeline step sets the "logged in" cookie for authenticated users.
"""This pipeline step sets the "logged in" cookie for authenticated users.
...
...
common/djangoapps/third_party_auth/settings.py
View file @
7f2c956e
...
@@ -9,6 +9,7 @@ If true, it:
...
@@ -9,6 +9,7 @@ If true, it:
a) loads this module.
a) loads this module.
b) calls apply_settings(), passing in the Django settings
b) calls apply_settings(), passing in the Django settings
"""
"""
_FIELDS_STORED_IN_SESSION
=
[
'auth_entry'
,
'next'
]
_FIELDS_STORED_IN_SESSION
=
[
'auth_entry'
,
'next'
]
_MIDDLEWARE_CLASSES
=
(
_MIDDLEWARE_CLASSES
=
(
'third_party_auth.middleware.ExceptionMiddleware'
,
'third_party_auth.middleware.ExceptionMiddleware'
,
...
@@ -52,7 +53,7 @@ def apply_settings(django_settings):
...
@@ -52,7 +53,7 @@ def apply_settings(django_settings):
'social.pipeline.user.get_username'
,
'social.pipeline.user.get_username'
,
'third_party_auth.pipeline.set_pipeline_timeout'
,
'third_party_auth.pipeline.set_pipeline_timeout'
,
'third_party_auth.pipeline.ensure_user_information'
,
'third_party_auth.pipeline.ensure_user_information'
,
'
third_party_auth.pipeline
.create_user'
,
'
social.pipeline.user
.create_user'
,
'social.pipeline.social_auth.associate_user'
,
'social.pipeline.social_auth.associate_user'
,
'social.pipeline.social_auth.load_extra_data'
,
'social.pipeline.social_auth.load_extra_data'
,
'social.pipeline.user.user_details'
,
'social.pipeline.user.user_details'
,
...
...
common/djangoapps/third_party_auth/strategy.py
View file @
7f2c956e
...
@@ -2,16 +2,12 @@
...
@@ -2,16 +2,12 @@
A custom Strategy for python-social-auth that allows us to fetch configuration from
A custom Strategy for python-social-auth that allows us to fetch configuration from
ConfigurationModels rather than django.settings
ConfigurationModels rather than django.settings
"""
"""
import
logging
from
.models
import
OAuth2ProviderConfig
from
.models
import
OAuth2ProviderConfig
from
.pipeline
import
AUTH_ENTRY_CUSTOM
from
.pipeline
import
AUTH_ENTRY_CUSTOM
from
social.backends.oauth
import
BaseOAuth2
from
social.backends.oauth
import
BaseOAuth2
from
social.strategies.django_strategy
import
DjangoStrategy
from
social.strategies.django_strategy
import
DjangoStrategy
log
=
logging
.
getLogger
(
__name__
)
class
ConfigurationModelStrategy
(
DjangoStrategy
):
class
ConfigurationModelStrategy
(
DjangoStrategy
):
"""
"""
A DjangoStrategy customized to load settings from ConfigurationModels
A DjangoStrategy customized to load settings from ConfigurationModels
...
@@ -47,47 +43,6 @@ class ConfigurationModelStrategy(DjangoStrategy):
...
@@ -47,47 +43,6 @@ class ConfigurationModelStrategy(DjangoStrategy):
# It's probably a global Django setting like 'FIELDS_STORED_IN_SESSION':
# It's probably a global Django setting like 'FIELDS_STORED_IN_SESSION':
return
super
(
ConfigurationModelStrategy
,
self
)
.
setting
(
name
,
default
,
backend
)
return
super
(
ConfigurationModelStrategy
,
self
)
.
setting
(
name
,
default
,
backend
)
def
_ensure_passes_length_check
(
self
,
user_data
,
key
,
fallback
,
min_length
=
2
):
"""
Ensures that value we get from user_data is meets length requirements. IF it is shorter than required, fallback
is used
"""
assert
len
(
fallback
)
>=
min_length
value
=
user_data
.
get
(
key
)
if
value
and
len
(
value
)
>=
min_length
:
return
value
return
fallback
def
create_user
(
self
,
*
args
,
**
kwargs
):
"""
# Creates user using information provided by pipeline. This method is called in create_user pipeline step.
# Unless the workflow is changed, create_user immediately terminates if the user already found/
# So far, user is either created in ensure_user_information via registration form or account needs to be
# autoprovisioned. So, this method is only called when autoprovisioning account.
"""
from
student.views
import
create_account_with_params
from
.pipeline
import
make_random_password
user_fields
=
dict
(
kwargs
)
# needs to be >2 chars to pass validation
name
=
self
.
_ensure_passes_length_check
(
user_fields
,
'fullname'
,
self
.
setting
(
"THIRD_PARTY_AUTH_FALLBACK_FULL_NAME"
)
)
password
=
self
.
_ensure_passes_length_check
(
user_fields
,
'password'
,
make_random_password
())
user_fields
[
'name'
]
=
name
user_fields
[
'password'
]
=
password
user_fields
[
'honor_code'
]
=
True
user_fields
[
'terms_of_service'
]
=
True
if
not
user_fields
.
get
(
'email'
):
user_fields
[
'email'
]
=
"{username}@{domain}"
.
format
(
username
=
user_fields
[
'username'
],
domain
=
self
.
setting
(
"FAKE_EMAIL_DOMAIN"
)
)
# when autoprovisioning we need to skip email activation, hence skip_email is True
return
create_account_with_params
(
self
.
request
,
user_fields
,
skip_email
=
True
)
def
request_host
(
self
):
def
request_host
(
self
):
"""
"""
Host in use for this request
Host in use for this request
...
...
common/djangoapps/third_party_auth/tests/specs/test_testshib.py
View file @
7f2c956e
...
@@ -111,7 +111,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
...
@@ -111,7 +111,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
continue_response
=
self
.
client
.
get
(
TPA_TESTSHIB_COMPLETE_URL
)
continue_response
=
self
.
client
.
get
(
TPA_TESTSHIB_COMPLETE_URL
)
# And we should be redirected to the dashboard:
# And we should be redirected to the dashboard:
self
.
assertEqual
(
continue_response
.
status_code
,
302
)
self
.
assertEqual
(
continue_response
.
status_code
,
302
)
self
.
assertEqual
(
continue_response
[
'Location'
],
self
.
url_prefix
+
reverse
(
'dashboard'
)
)
self
.
assertEqual
(
continue_response
[
'Location'
],
self
.
url_prefix
+
self
.
dashboard_page_url
)
# Now check that we can login again:
# Now check that we can login again:
self
.
client
.
logout
()
self
.
client
.
logout
()
...
@@ -157,32 +157,8 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
...
@@ -157,32 +157,8 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
self
.
client
.
logout
()
self
.
client
.
logout
()
self
.
_test_return_login
()
self
.
_test_return_login
()
def
test_autoprovision_from_login
(
self
):
self
.
_configure_testshib_provider
(
autoprovision_account
=
True
)
self
.
_freeze_time
(
timestamp
=
1434326820
)
# This is the time when the saved request/response was recorded.
# check that we don't have a user we're autoprovisioning account for
self
.
_assert_user_does_not_exist
(
'myself'
)
# The user goes to the register page, and sees a button to register with TestShib:
self
.
_check_login_page
()
self
.
_test_autoprovision
(
TPA_TESTSHIB_LOGIN_URL
)
def
test_autoprovision_from_register
(
self
):
self
.
_configure_testshib_provider
(
autoprovision_account
=
True
)
self
.
_freeze_time
(
timestamp
=
1434326820
)
# This is the time when the saved request/response was recorded.
# check that we don't have a user we're autoprovisioning account for
self
.
_assert_user_does_not_exist
(
'myself'
)
# The user goes to the register page, and sees a button to register with TestShib:
self
.
_check_register_page
()
self
.
_test_autoprovision
(
TPA_TESTSHIB_REGISTER_URL
)
def
test_custom_form_does_not_link_by_email
(
self
):
def
test_custom_form_does_not_link_by_email
(
self
):
self
.
_configure_testshib_provider
(
autoprovision_account
=
False
)
self
.
_configure_testshib_provider
()
self
.
_freeze_time
(
timestamp
=
1434326820
)
# This is the time when the saved request/response was recorded.
self
.
_freeze_time
(
timestamp
=
1434326820
)
# This is the time when the saved request/response was recorded.
email
=
'myself@testshib.org'
email
=
'myself@testshib.org'
...
@@ -201,7 +177,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
...
@@ -201,7 +177,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
self
.
assertEqual
(
testshib_response
[
'Location'
],
self
.
url_prefix
+
'/auth/custom_auth_entry'
)
self
.
assertEqual
(
testshib_response
[
'Location'
],
self
.
url_prefix
+
'/auth/custom_auth_entry'
)
def
test_custom_form_links_by_email
(
self
):
def
test_custom_form_links_by_email
(
self
):
self
.
_configure_testshib_provider
(
autoprovision_account
=
False
)
self
.
_configure_testshib_provider
()
self
.
_freeze_time
(
timestamp
=
1434326820
)
# This is the time when the saved request/response was recorded.
self
.
_freeze_time
(
timestamp
=
1434326820
)
# This is the time when the saved request/response was recorded.
email
=
'myself@testshib.org'
email
=
'myself@testshib.org'
...
@@ -229,35 +205,10 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
...
@@ -229,35 +205,10 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
self
.
client
.
logout
()
self
.
client
.
logout
()
self
.
_test_return_login
()
self
.
_test_return_login
()
def
_test_autoprovision
(
self
,
entry_point
):
""" Actual autoprovision code """
# The user clicks on the TestShib button:
try_entry_response
=
self
.
client
.
get
(
entry_point
)
# The user should be redirected to TestShib:
self
.
assertEqual
(
try_entry_response
.
status_code
,
302
)
self
.
assertTrue
(
try_entry_response
[
'Location'
]
.
startswith
(
TESTSHIB_SSO_URL
))
# Now the user will authenticate with the SAML provider
self
.
_fake_testshib_login_and_return
()
# Then there's one more redirect to set logged_in cookie
continue_response
=
self
.
client
.
get
(
TPA_TESTSHIB_COMPLETE_URL
)
# We should be redirected to the dashboard screen since profile should be created and logged in
self
.
assertEqual
(
continue_response
.
status_code
,
302
)
self
.
assertEqual
(
continue_response
[
'Location'
],
self
.
url_prefix
+
self
.
dashboard_page_url
)
# assert account is created and activated
self
.
_assert_account_created
(
username
=
'myself'
,
email
=
'myself@testshib.org'
,
full_name
=
'Me Myself And I'
)
# Now check that we can login again:
self
.
client
.
logout
()
self
.
_test_return_login
()
def
_test_return_login
(
self
):
def
_test_return_login
(
self
):
""" Test logging in to an account that is already linked. """
""" Test logging in to an account that is already linked. """
# Make sure we're not logged in:
# Make sure we're not logged in:
dashboard_response
=
self
.
client
.
get
(
reverse
(
'dashboard'
)
)
dashboard_response
=
self
.
client
.
get
(
self
.
dashboard_page_url
)
self
.
assertEqual
(
dashboard_response
.
status_code
,
302
)
self
.
assertEqual
(
dashboard_response
.
status_code
,
302
)
# The user goes to the login page, and sees a button to login with TestShib:
# The user goes to the login page, and sees a button to login with TestShib:
self
.
_check_login_page
()
self
.
_check_login_page
()
...
@@ -276,7 +227,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
...
@@ -276,7 +227,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
self
.
assertEqual
(
login_response
.
status_code
,
302
)
self
.
assertEqual
(
login_response
.
status_code
,
302
)
self
.
assertEqual
(
login_response
[
'Location'
],
self
.
url_prefix
+
self
.
dashboard_page_url
)
self
.
assertEqual
(
login_response
[
'Location'
],
self
.
url_prefix
+
self
.
dashboard_page_url
)
# Now we are logged in:
# Now we are logged in:
dashboard_response
=
self
.
client
.
get
(
reverse
(
'dashboard'
)
)
dashboard_response
=
self
.
client
.
get
(
self
.
dashboard_page_url
)
self
.
assertEqual
(
dashboard_response
.
status_code
,
200
)
self
.
assertEqual
(
dashboard_response
.
status_code
,
200
)
def
_freeze_time
(
self
,
timestamp
):
def
_freeze_time
(
self
,
timestamp
):
...
@@ -311,7 +262,6 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
...
@@ -311,7 +262,6 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
kwargs
.
setdefault
(
'metadata_source'
,
TESTSHIB_METADATA_URL
)
kwargs
.
setdefault
(
'metadata_source'
,
TESTSHIB_METADATA_URL
)
kwargs
.
setdefault
(
'icon_class'
,
'fa-university'
)
kwargs
.
setdefault
(
'icon_class'
,
'fa-university'
)
kwargs
.
setdefault
(
'attr_email'
,
'urn:oid:1.3.6.1.4.1.5923.1.1.1.6'
)
# eduPersonPrincipalName
kwargs
.
setdefault
(
'attr_email'
,
'urn:oid:1.3.6.1.4.1.5923.1.1.1.6'
)
# eduPersonPrincipalName
kwargs
.
setdefault
(
'autoprovision_account'
,
False
)
self
.
configure_saml_provider
(
**
kwargs
)
self
.
configure_saml_provider
(
**
kwargs
)
if
fetch_metadata
:
if
fetch_metadata
:
...
...
common/djangoapps/third_party_auth/tests/test_pipeline.py
View file @
7f2c956e
"""Unit tests for third_party_auth/pipeline.py."""
"""Unit tests for third_party_auth/pipeline.py."""
import
random
import
random
import
mock
from
student.views
import
AccountEmailAlreadyExistsValidationError
from
third_party_auth
import
pipeline
,
provider
from
third_party_auth
import
pipeline
,
provider
from
third_party_auth.tests
import
testutil
from
third_party_auth.tests
import
testutil
import
unittest
import
unittest
...
@@ -45,38 +43,3 @@ class ProviderUserStateTestCase(testutil.TestCase):
...
@@ -45,38 +43,3 @@ class ProviderUserStateTestCase(testutil.TestCase):
google_provider
=
self
.
configure_google_provider
(
enabled
=
True
)
google_provider
=
self
.
configure_google_provider
(
enabled
=
True
)
state
=
pipeline
.
ProviderUserState
(
google_provider
,
object
(),
None
)
state
=
pipeline
.
ProviderUserState
(
google_provider
,
object
(),
None
)
self
.
assertEqual
(
google_provider
.
provider_id
+
'_unlink_form'
,
state
.
get_unlink_form_name
())
self
.
assertEqual
(
google_provider
.
provider_id
+
'_unlink_form'
,
state
.
get_unlink_form_name
())
@unittest.skipUnless
(
testutil
.
AUTH_FEATURE_ENABLED
,
'third_party_auth not enabled'
)
class
TestCreateUser
(
testutil
.
TestCase
):
"""
Tests for custom create_user step
"""
def
_raise_email_in_use_exception
(
self
,
*
unused_args
,
**
unused_kwargs
):
""" Helper to raise AccountEmailAlreadyExistsValidationError """
raise
AccountEmailAlreadyExistsValidationError
(
mock
.
Mock
(),
mock
.
Mock
())
def
test_create_user_normal_scenario
(
self
):
""" Tests happy path - user is created and results are returned intact """
retval
=
mock
.
Mock
()
with
mock
.
patch
(
"third_party_auth.pipeline.social_create_user"
)
as
patched_social_create_user
:
patched_social_create_user
.
return_value
=
retval
strategy
,
details
,
user
,
idx
=
mock
.
Mock
(),
{
'email'
:
'qwe@asd.com'
},
mock
.
Mock
(),
1
# pylint: disable=redundant-keyword-arg
result
=
pipeline
.
create_user
(
strategy
,
idx
,
details
=
details
,
user
=
user
)
self
.
assertEqual
(
result
,
retval
)
def
test_create_user_exception_scenario
(
self
):
"""
Tests sad path - expected exception is thrown, captured and transformed into AuthException subclass instance
"""
with
mock
.
patch
(
"third_party_auth.pipeline.social_create_user"
)
as
patched_social_create_user
:
patched_social_create_user
.
side_effect
=
self
.
_raise_email_in_use_exception
strategy
,
details
,
user
=
mock
.
Mock
(),
{
'email'
:
'qwe@asd.com'
},
mock
.
Mock
()
with
self
.
assertRaises
(
pipeline
.
EmailAlreadyInUseException
):
# pylint: disable=redundant-keyword-arg
pipeline
.
create_user
(
strategy
,
1
,
details
=
details
,
user
=
user
)
common/djangoapps/third_party_auth/tests/test_strategy.py
View file @
7f2c956e
...
@@ -24,80 +24,6 @@ class TestStrategy(TestCase):
...
@@ -24,80 +24,6 @@ class TestStrategy(TestCase):
args
,
unused_kwargs
=
patched_create_account
.
call_args
args
,
unused_kwargs
=
patched_create_account
.
call_args
return
args
return
args
def
test_create_user_sets_tos_and_honor_code
(
self
,
patched_create_account
):
self
.
strategy
.
create_user
(
username
=
'myself'
)
self
.
assertTrue
(
patched_create_account
.
called
)
request
,
user_data
=
self
.
_get_last_call_args
(
patched_create_account
)
self
.
assertEqual
(
request
,
self
.
request_mock
)
self
.
assertTrue
(
user_data
[
'terms_of_service'
])
self
.
assertTrue
(
user_data
[
'honor_code'
])
@ddt.data
(
(
None
,
'Fallback Name'
,
'Fallback Name'
),
(
'q'
,
'Other Name'
,
'Other Name'
),
(
'q2'
,
'Other Name'
,
'q2'
),
(
'qwe'
,
'Other Name'
,
'qwe'
),
(
'user1'
,
'Fallback Name'
,
'user1'
)
)
@ddt.unpack
def
test_create_user_sets_name
(
self
,
full_name
,
fallback_name
,
expected_name
,
patched_create_account
):
with
mock
.
patch
.
object
(
self
.
strategy
,
'setting'
,
mock
.
Mock
())
as
patched_setting
:
patched_setting
.
return_value
=
fallback_name
self
.
strategy
.
create_user
(
username
=
'myself'
,
fullname
=
full_name
)
# it is actually always called, but this assertion is relaxed to allow not actually going to settings
# if there's no point in that
if
expected_name
==
fallback_name
:
self
.
assertIn
(
mock
.
call
(
"THIRD_PARTY_AUTH_FALLBACK_FULL_NAME"
),
patched_setting
.
mock_calls
)
_
,
user_data
=
self
.
_get_last_call_args
(
patched_create_account
)
self
.
assertEqual
(
user_data
[
'name'
],
expected_name
)
def
test_sets_password_if_missing
(
self
,
patched_create_account
):
self
.
strategy
.
create_user
(
username
=
'myself'
,
fullname
=
'myself'
)
_
,
user_data
=
self
.
_get_last_call_args
(
patched_create_account
)
self
.
assertIn
(
'password'
,
user_data
)
@ddt.data
(
(
None
,
False
),
(
'q'
,
False
),
(
'12'
,
False
),
(
'456'
,
True
),
(
'$up3r_$e(ur3_p/|$$w0rd'
,
True
),
)
@ddt.unpack
def
test_passes_password_if_specified
(
self
,
password
,
should_match
,
patched_create_account
):
self
.
strategy
.
create_user
(
username
=
'myself'
,
fullname
=
'myself'
,
password
=
password
)
_
,
user_data
=
self
.
_get_last_call_args
(
patched_create_account
)
self
.
assertIn
(
'password'
,
user_data
)
if
should_match
:
self
.
assertEqual
(
user_data
[
'password'
],
password
)
@ddt.data
(
(
None
,
'fallback_domain.com'
,
'myself@fallback_domain.com'
),
(
''
,
'other_domain.com'
,
'myself@other_domain.com'
),
(
'qwe@asd.com'
,
'fallback_domain.com'
,
'qwe@asd.com'
),
(
'zxc@darpa.gov.mil.edu'
,
'fallback_domain.com'
,
'zxc@darpa.gov.mil.edu'
),
)
@ddt.unpack
def
test_sets_email_if_not_provided
(
self
,
email
,
fallback_domain
,
expected_email
,
patched_create_account
):
with
mock
.
patch
.
object
(
self
.
strategy
,
'setting'
,
mock
.
Mock
())
as
patched_setting
:
patched_setting
.
return_value
=
fallback_domain
# fullname is needed to avoid calling setting twice
self
.
strategy
.
create_user
(
username
=
'myself'
,
fullname
=
'myself'
,
email
=
email
)
# it is actually always called, but this assertion is relaxed to allow not actually going to settings
# if there's no point in that
if
email
!=
expected_email
:
self
.
assertIn
(
mock
.
call
(
"FAKE_EMAIL_DOMAIN"
),
patched_setting
.
mock_calls
)
_
,
user_data
=
self
.
_get_last_call_args
(
patched_create_account
)
self
.
assertEqual
(
user_data
[
'email'
],
expected_email
)
@ddt.data
(
@ddt.data
(
(
True
,
None
,
'host'
,
'host'
),
(
True
,
None
,
'host'
,
'host'
),
(
True
,
""
,
'other_host'
,
'other_host'
),
(
True
,
""
,
'other_host'
,
'other_host'
),
...
...
lms/envs/aws.py
View file @
7f2c956e
...
@@ -592,14 +592,6 @@ if FEATURES.get('ENABLE_THIRD_PARTY_AUTH'):
...
@@ -592,14 +592,6 @@ if FEATURES.get('ENABLE_THIRD_PARTY_AUTH'):
SOCIAL_AUTH_RESPECT_X_FORWARDED_HEADERS
=
ENV_TOKENS
.
get
(
'SOCIAL_AUTH_RESPECT_X_FORWARDED_HEADERS'
)
SOCIAL_AUTH_RESPECT_X_FORWARDED_HEADERS
=
ENV_TOKENS
.
get
(
'SOCIAL_AUTH_RESPECT_X_FORWARDED_HEADERS'
)
# FAKE EMAIL DOMAIN setting is used to generate an email for an automatically provisioned account in case
# it is not provided by IdP (which should'nt normally be the case for providers with automatic provisioning)
FAKE_EMAIL_DOMAIN
=
ENV_TOKENS
.
get
(
'FAKE_EMAIL_DOMAIN'
,
'fake-email-domain.foo'
)
# This setting is used as a user full name when automatically provisioning an account in case
# IdP provided name is empty, missing or does not pass minimal length check
THIRD_PARTY_AUTH_FALLBACK_FULL_NAME
=
ENV_TOKENS
.
get
(
'THIRD_PARTY_AUTH_FALLBACK_FULL_NAME'
,
"Unknown"
)
# The following can be used to integrate a custom login form with third_party_auth.
# The following can be used to integrate a custom login form with third_party_auth.
# It should be a dict where the key is a word passed via ?auth_entry=, and the value is a
# It should be a dict where the key is a word passed via ?auth_entry=, and the value is a
# dict with an arbitrary 'secret_key' and a 'url'.
# dict with an arbitrary 'secret_key' and a 'url'.
...
...
lms/envs/test.py
View file @
7f2c956e
...
@@ -258,9 +258,6 @@ AUTHENTICATION_BACKENDS = (
...
@@ -258,9 +258,6 @@ AUTHENTICATION_BACKENDS = (
'third_party_auth.saml.SAMLAuthBackend'
,
'third_party_auth.saml.SAMLAuthBackend'
,
)
+
AUTHENTICATION_BACKENDS
)
+
AUTHENTICATION_BACKENDS
FAKE_EMAIL_DOMAIN
=
'fake-email-domain.foo'
THIRD_PARTY_AUTH_FALLBACK_FULL_NAME
=
"Unknown"
THIRD_PARTY_AUTH_CUSTOM_AUTH_FORMS
=
{
THIRD_PARTY_AUTH_CUSTOM_AUTH_FORMS
=
{
'custom1'
:
{
'custom1'
:
{
'secret_key'
:
'opensesame'
,
'secret_key'
:
'opensesame'
,
...
...
requirements/edx/custom.txt
View file @
7f2c956e
# Custom requirements to be customized by individual OpenEdX instances
# Custom requirements to be customized by individual OpenEdX instances
# When updating a hash of an XBlock that users xblock-utils, please update its version hash in github.txt
# When updating a hash of an XBlock that uses xblock-utils, please update its version hash in github.txt.
-e git+https://github.com/edx/xblock-utils.git@3b58c757f06943072b170654d676e95b9adb37b0#egg=xblock-utils
-e git+https://github.com/edx-solutions/xblock-mentoring.git@bd0b3f413ae7e8274985555adfd7de7af3eca84c#egg=xblock-mentoring
-e git+https://github.com/edx-solutions/xblock-mentoring.git@bd0b3f413ae7e8274985555adfd7de7af3eca84c#egg=xblock-mentoring
-e git+https://github.com/edx-solutions/xblock-image-explorer.git@21b9bcc4f2c7917463ab18a596161ac6c58c9c4a#egg=xblock-image-explorer
-e git+https://github.com/edx-solutions/xblock-image-explorer.git@21b9bcc4f2c7917463ab18a596161ac6c58c9c4a#egg=xblock-image-explorer
-e git+https://github.com/edx-solutions/xblock-drag-and-drop.git@92ee2055a16899090a073e1df81e35d5293ad767#egg=xblock-drag-and-drop
-e git+https://github.com/edx-solutions/xblock-drag-and-drop.git@92ee2055a16899090a073e1df81e35d5293ad767#egg=xblock-drag-and-drop
...
@@ -9,9 +8,9 @@
...
@@ -9,9 +8,9 @@
-e git+https://github.com/edx-solutions/xblock-ooyala.git@42f769d422850df81bcbd2dbcc344f86b6a17d8e#egg=xblock-ooyala
-e git+https://github.com/edx-solutions/xblock-ooyala.git@42f769d422850df81bcbd2dbcc344f86b6a17d8e#egg=xblock-ooyala
-e git+https://github.com/edx-solutions/xblock-group-project.git@6b3393a1a5eb76224ecd3311e870ab8adf4badbf#egg=xblock-group-project
-e git+https://github.com/edx-solutions/xblock-group-project.git@6b3393a1a5eb76224ecd3311e870ab8adf4badbf#egg=xblock-group-project
-e git+https://github.com/edx-solutions/xblock-adventure.git@effa22006bb6528bc6d3788787466eb4e74e1161#egg=xblock-adventure
-e git+https://github.com/edx-solutions/xblock-adventure.git@effa22006bb6528bc6d3788787466eb4e74e1161#egg=xblock-adventure
-e git+https://github.com/
mckinseyacademy/xblock-poll.git@ca0e6eb4ef10c128d573c3cec015dcfee7984730
#egg=xblock-poll
-e git+https://github.com/
open-craft/xblock-poll.git@ed7f32a570fb29a18cce57b14f322667a5f33cd5
#egg=xblock-poll
-e git+https://github.com/edx/edx-notifications.git@275b8354593048ecae3e06642985b702b81140cc#egg=edx-notifications
-e git+https://github.com/edx/edx-notifications.git@275b8354593048ecae3e06642985b702b81140cc#egg=edx-notifications
-e git+https://github.com/open-craft/problem-builder.git@
c6e606027155d92ca78e96e6bc23ea86dcc588fc
#egg=problem-builder
-e git+https://github.com/open-craft/problem-builder.git@
ff271b2dcf8098cc3bfed424244c76ea2c53cc96
#egg=problem-builder
-e git+https://github.com/open-craft/xblock-group-project-v2.git@
533a3d70b8ff58af0c4f5e22abc674c60881cea3
#egg=xblock-group-project-v2
-e git+https://github.com/open-craft/xblock-group-project-v2.git@
da8ab1e0e110cb3d2525157958a88f101fd1abdb
#egg=xblock-group-project-v2
-e git+https://github.com/OfficeDev/xblock-officemix.git@86238f5968a08db005717dbddc346808f1ed3716#egg=xblock-officemix
-e git+https://github.com/OfficeDev/xblock-officemix.git@86238f5968a08db005717dbddc346808f1ed3716#egg=xblock-officemix
-e git+https://github.com/edx-solutions/xblock.git@80d11e883cb0f4b554e1e566294cb7de383cffed#egg=xblock
-e git+https://github.com/edx-solutions/xblock.git@80d11e883cb0f4b554e1e566294cb7de383cffed#egg=xblock
requirements/edx/github.txt
View file @
7f2c956e
...
@@ -50,8 +50,8 @@ git+https://github.com/edx/ease.git@release-2015-07-14#egg=ease==0.1.3
...
@@ -50,8 +50,8 @@ git+https://github.com/edx/ease.git@release-2015-07-14#egg=ease==0.1.3
-e git+https://github.com/edx/edx-search.git@release-2015-07-03#egg=edx-search
-e git+https://github.com/edx/edx-search.git@release-2015-07-03#egg=edx-search
-e git+https://github.com/edx/edx-milestones.git@release-2015-06-17#egg=edx-milestones
-e git+https://github.com/edx/edx-milestones.git@release-2015-06-17#egg=edx-milestones
git+https://github.com/edx/edx-lint.git@ed8c8d2a0267d4d42f43642d193e25f8bd575d9b#egg=edx_lint==0.2.3
git+https://github.com/edx/edx-lint.git@ed8c8d2a0267d4d42f43642d193e25f8bd575d9b#egg=edx_lint==0.2.3
# Note for the next rebase:
custom.txt or one of XBlocks installed there might require a newer version of xblock-utils - please check versions
# Note for the next rebase:
one of XBlocks in custom.txt might require a newer version of xblock-utils - please check versions.
-e git+https://github.com/edx/xblock-utils.git@
588f7fd3ee88847c57cf09d10e81caa6b267ec51
#egg=xblock-utils
-e git+https://github.com/edx/xblock-utils.git@
08e5a5a9fc8ab46b627435427fd7e04c20809009
#egg=xblock-utils
-e git+https://github.com/edx-solutions/xblock-google-drive.git@138e6fa0bf3a2013e904a085b9fed77dab7f3f21#egg=xblock-google-drive
-e git+https://github.com/edx-solutions/xblock-google-drive.git@138e6fa0bf3a2013e904a085b9fed77dab7f3f21#egg=xblock-google-drive
-e git+https://github.com/edx/edx-reverification-block.git@a286e89c73e1b788e35ac5b08a54b71a9fa63cfd#egg=edx-reverification-block
-e git+https://github.com/edx/edx-reverification-block.git@a286e89c73e1b788e35ac5b08a54b71a9fa63cfd#egg=edx-reverification-block
git+https://github.com/edx/ecommerce-api-client.git@1.0.0#egg=ecommerce-api-client==1.0.0
git+https://github.com/edx/ecommerce-api-client.git@1.0.0#egg=ecommerce-api-client==1.0.0
...
...
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