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
7437bcfe
Commit
7437bcfe
authored
Jun 21, 2015
by
Braden MacDonald
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New provider config options, New Institution Login Menu - PR 8603
parent
5bf0b179
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
397 additions
and
54 deletions
+397
-54
common/djangoapps/student/views.py
+14
-9
common/djangoapps/third_party_auth/migrations/0003_add_config_options.py
+0
-0
common/djangoapps/third_party_auth/models.py
+27
-3
common/djangoapps/third_party_auth/pipeline.py
+7
-0
common/djangoapps/third_party_auth/tests/specs/test_testshib.py
+8
-2
lms/djangoapps/student_account/test/test_views.py
+1
-0
lms/djangoapps/student_account/views.py
+8
-4
lms/envs/common.py
+1
-0
lms/static/js/spec/main.js
+11
-0
lms/static/js/spec/student_account/access_spec.js
+27
-0
lms/static/js/spec/student_account/institution_login_spec.js
+80
-0
lms/static/js/student_account/views/AccessView.js
+21
-5
lms/static/js/student_account/views/FormView.js
+3
-1
lms/static/js/student_account/views/InstitutionLoginView.js
+30
-0
lms/static/js/student_account/views/LoginView.js
+4
-0
lms/static/js/student_account/views/RegisterView.js
+20
-1
lms/static/sass/views/_login-register.scss
+54
-26
lms/templates/student_account/access.underscore
+4
-0
lms/templates/student_account/institution_login.underscore
+31
-0
lms/templates/student_account/institution_register.underscore
+31
-0
lms/templates/student_account/login.underscore
+7
-1
lms/templates/student_account/login_and_register.html
+1
-1
lms/templates/student_account/register.underscore
+7
-1
No files found.
common/djangoapps/student/views.py
View file @
7437bcfe
...
...
@@ -1498,6 +1498,13 @@ def create_account_with_params(request, params):
dog_stats_api
.
increment
(
"common.student.account_created"
)
# If the user is registering via 3rd party auth, track which provider they use
third_party_provider
=
None
running_pipeline
=
None
if
third_party_auth
.
is_enabled
()
and
pipeline
.
running
(
request
):
running_pipeline
=
pipeline
.
get
(
request
)
third_party_provider
=
provider
.
Registry
.
get_from_pipeline
(
running_pipeline
)
# Track the user's registration
if
settings
.
FEATURES
.
get
(
'SEGMENT_IO_LMS'
)
and
hasattr
(
settings
,
'SEGMENT_IO_LMS_KEY'
):
tracking_context
=
tracker
.
get_tracker
()
.
resolve_context
()
...
...
@@ -1506,20 +1513,13 @@ def create_account_with_params(request, params):
'username'
:
user
.
username
,
})
# If the user is registering via 3rd party auth, track which provider they use
provider_name
=
None
if
third_party_auth
.
is_enabled
()
and
pipeline
.
running
(
request
):
running_pipeline
=
pipeline
.
get
(
request
)
current_provider
=
provider
.
Registry
.
get_from_pipeline
(
running_pipeline
)
provider_name
=
current_provider
.
name
analytics
.
track
(
user
.
id
,
"edx.bi.user.account.registered"
,
{
'category'
:
'conversion'
,
'label'
:
params
.
get
(
'course_id'
),
'provider'
:
provider_nam
e
'provider'
:
third_party_provider
.
name
if
third_party_provider
else
Non
e
},
context
=
{
'Google Analytics'
:
{
...
...
@@ -1536,6 +1536,7 @@ def create_account_with_params(request, params):
# 2. Random user generation for other forms of testing.
# 3. External auth bypassing activation.
# 4. Have the platform configured to not require e-mail activation.
# 5. Registering a new user using a trusted third party provider (with skip_email_verification=True)
#
# Note that this feature is only tested as a flag set one way or
# the other for *new* systems. we need to be careful about
...
...
@@ -1544,7 +1545,11 @@ def create_account_with_params(request, params):
send_email
=
(
not
settings
.
FEATURES
.
get
(
'SKIP_EMAIL_VALIDATION'
,
None
)
and
not
settings
.
FEATURES
.
get
(
'AUTOMATIC_AUTH_FOR_TESTING'
)
and
not
(
do_external_auth
and
settings
.
FEATURES
.
get
(
'BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'
))
not
(
do_external_auth
and
settings
.
FEATURES
.
get
(
'BYPASS_ACTIVATION_EMAIL_FOR_EXTAUTH'
))
and
not
(
third_party_provider
and
third_party_provider
.
skip_email_verification
and
user
.
email
==
running_pipeline
[
'kwargs'
]
.
get
(
'details'
,
{})
.
get
(
'email'
)
)
)
if
send_email
:
context
=
{
...
...
common/djangoapps/third_party_auth/migrations/0003_add_config_options.py
0 → 100644
View file @
7437bcfe
This diff is collapsed.
Click to expand it.
common/djangoapps/third_party_auth/models.py
View file @
7437bcfe
...
...
@@ -8,7 +8,7 @@ from django.conf import settings
from
django.core.exceptions
import
ValidationError
from
django.db
import
models
from
django.utils
import
timezone
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
_lazy
as
_
import
json
import
logging
from
social.backends.base
import
BaseAuth
...
...
@@ -54,7 +54,7 @@ class AuthNotConfigured(SocialAuthBaseException):
self
.
provider_name
=
provider_name
def
__str__
(
self
):
return
_
(
'Authentication with {} is currently unavailable.'
)
.
format
(
return
_
(
'Authentication with {} is currently unavailable.'
)
.
format
(
# pylint: disable=no-member
self
.
provider_name
)
...
...
@@ -68,10 +68,34 @@ class ProviderConfig(ConfigurationModel):
help_text
=
(
'The Font Awesome (or custom) icon class to use on the login button for this provider. '
'Examples: fa-google-plus, fa-facebook, fa-linkedin, fa-sign-in, fa-university'
))
),
)
name
=
models
.
CharField
(
max_length
=
50
,
blank
=
False
,
help_text
=
"Name of this provider (shown to users)"
)
secondary
=
models
.
BooleanField
(
default
=
False
,
help_text
=
_
(
'Secondary providers are displayed less prominently, '
'in a separate list of "Institution" login providers.'
),
)
skip_registration_form
=
models
.
BooleanField
(
default
=
False
,
help_text
=
_
(
"If this option is enabled, users will not be asked to confirm their details "
"(name, email, etc.) during the registration process. Only select this option "
"for trusted providers that are known to provide accurate user information."
),
)
skip_email_verification
=
models
.
BooleanField
(
default
=
False
,
help_text
=
_
(
"If this option is selected, users will not be required to confirm their "
"email, and their account will be activated immediately upon registration."
),
)
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
# "enabled" field is inherited from ConfigurationModel
class
Meta
(
object
):
# pylint: disable=missing-docstring
...
...
common/djangoapps/third_party_auth/pipeline.py
View file @
7437bcfe
...
...
@@ -503,12 +503,19 @@ def ensure_user_information(strategy, auth_entry, backend=None, user=None, socia
"""Redirects to the registration page."""
return
redirect
(
AUTH_DISPATCH_URLS
[
AUTH_ENTRY_REGISTER
])
def
should_force_account_creation
():
""" For some third party providers, we auto-create user accounts """
current_provider
=
provider
.
Registry
.
get_from_pipeline
({
'backend'
:
backend
.
name
,
'kwargs'
:
kwargs
})
return
current_provider
and
current_provider
.
skip_email_verification
if
not
user
:
if
auth_entry
in
[
AUTH_ENTRY_LOGIN_API
,
AUTH_ENTRY_REGISTER_API
]:
return
HttpResponseBadRequest
()
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
# account corresponds to them yet, if any.
if
should_force_account_creation
():
return
dispatch_to_register
()
return
dispatch_to_login
()
elif
auth_entry
in
[
AUTH_ENTRY_REGISTER
,
AUTH_ENTRY_REGISTER_2
]:
# User has authenticated with the third party provider and now wants to finish
...
...
common/djangoapps/third_party_auth/tests/specs/test_testshib.py
View file @
7437bcfe
"""
Third_party_auth integration tests using a mock version of the TestShib provider
"""
from
django.contrib.auth.models
import
User
from
django.core.urlresolvers
import
reverse
import
httpretty
from
mock
import
patch
...
...
@@ -62,8 +63,6 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertIn
(
'Authentication with TestShib is currently unavailable.'
,
response
.
content
)
# Note: the following patch is only needed until https://github.com/edx/edx-platform/pull/8262 is merged
@patch.dict
(
"django.conf.settings.FEATURES"
,
{
"AUTOMATIC_AUTH_FOR_TESTING"
:
True
})
def
test_register
(
self
):
self
.
_configure_testshib_provider
()
self
.
_freeze_time
(
timestamp
=
1434326820
)
# This is the time when the saved request/response was recorded.
...
...
@@ -107,6 +106,7 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
# Now check that we can login again:
self
.
client
.
logout
()
self
.
_verify_user_email
(
'myself@testshib.org'
)
self
.
_test_return_login
()
def
test_login
(
self
):
...
...
@@ -222,3 +222,9 @@ class TestShibIntegrationTest(testutil.SAMLTestCase):
content_type
=
'application/x-www-form-urlencoded'
,
data
=
self
.
_read_data_file
(
'testshib_response.txt'
),
)
def
_verify_user_email
(
self
,
email
):
""" Mark the user with the given email as verified """
user
=
User
.
objects
.
get
(
email
=
email
)
user
.
is_active
=
True
user
.
save
()
lms/djangoapps/student_account/test/test_views.py
View file @
7437bcfe
...
...
@@ -359,6 +359,7 @@ class StudentAccountLoginAndRegistrationTest(ThirdPartyAuthTestMixin, UrlResetMi
json
.
dumps
({
"currentProvider"
:
current_provider
,
"providers"
:
providers
,
"secondaryProviders"
:
[],
"finishAuthUrl"
:
finish_auth_url
,
"errorMessage"
:
None
,
})
...
...
lms/djangoapps/student_account/views.py
View file @
7437bcfe
...
...
@@ -164,13 +164,14 @@ def _third_party_auth_context(request, redirect_to):
context
=
{
"currentProvider"
:
None
,
"providers"
:
[],
"secondaryProviders"
:
[],
"finishAuthUrl"
:
None
,
"errorMessage"
:
None
,
}
if
third_party_auth
.
is_enabled
():
context
[
"providers"
]
=
[
{
for
enabled
in
third_party_auth
.
provider
.
Registry
.
enabled
():
info
=
{
"id"
:
enabled
.
provider_id
,
"name"
:
enabled
.
name
,
"iconClass"
:
enabled
.
icon_class
,
...
...
@@ -185,8 +186,7 @@ def _third_party_auth_context(request, redirect_to):
redirect_url
=
redirect_to
,
),
}
for
enabled
in
third_party_auth
.
provider
.
Registry
.
enabled
()
]
context
[
"providers"
if
not
enabled
.
secondary
else
"secondaryProviders"
]
.
append
(
info
)
running_pipeline
=
pipeline
.
get
(
request
)
if
running_pipeline
is
not
None
:
...
...
@@ -194,6 +194,10 @@ def _third_party_auth_context(request, redirect_to):
context
[
"currentProvider"
]
=
current_provider
.
name
context
[
"finishAuthUrl"
]
=
pipeline
.
get_complete_url
(
current_provider
.
backend_name
)
if
current_provider
.
skip_registration_form
:
# As a reliable way of "skipping" the registration form, we just submit it automatically
context
[
"autoSubmitRegForm"
]
=
True
# Check for any error messages we may want to display:
for
msg
in
messages
.
get_messages
(
request
):
if
msg
.
extra_tags
.
split
()[
0
]
==
"social-auth"
:
...
...
lms/envs/common.py
View file @
7437bcfe
...
...
@@ -1274,6 +1274,7 @@ student_account_js = [
'js/student_account/views/RegisterView.js'
,
'js/student_account/views/PasswordResetView.js'
,
'js/student_account/views/AccessView.js'
,
'js/student_account/views/InstitutionLoginView.js'
,
'js/student_account/accessApp.js'
,
]
...
...
lms/static/js/spec/main.js
View file @
7437bcfe
...
...
@@ -84,6 +84,7 @@
'js/student_account/views/FormView'
:
'js/student_account/views/FormView'
,
'js/student_account/models/LoginModel'
:
'js/student_account/models/LoginModel'
,
'js/student_account/views/LoginView'
:
'js/student_account/views/LoginView'
,
'js/student_account/views/InstitutionLoginView'
:
'js/student_account/views/InstitutionLoginView'
,
'js/student_account/models/PasswordResetModel'
:
'js/student_account/models/PasswordResetModel'
,
'js/student_account/views/PasswordResetView'
:
'js/student_account/views/PasswordResetView'
,
'js/student_account/models/RegisterModel'
:
'js/student_account/models/RegisterModel'
,
...
...
@@ -410,6 +411,14 @@
'js/student_account/views/FormView'
]
},
'js/student_account/views/InstitutionLoginView'
:
{
exports
:
'edx.student.account.InstitutionLoginView'
,
deps
:
[
'jquery'
,
'underscore'
,
'backbone'
]
},
'js/student_account/models/PasswordResetModel'
:
{
exports
:
'edx.student.account.PasswordResetModel'
,
deps
:
[
'jquery'
,
'jquery.cookie'
,
'backbone'
]
...
...
@@ -450,6 +459,7 @@
'js/student_account/views/LoginView'
,
'js/student_account/views/PasswordResetView'
,
'js/student_account/views/RegisterView'
,
'js/student_account/views/InstitutionLoginView'
,
'js/student_account/models/LoginModel'
,
'js/student_account/models/PasswordResetModel'
,
'js/student_account/models/RegisterModel'
,
...
...
@@ -613,6 +623,7 @@
'lms/include/js/spec/student_account/access_spec.js'
,
'lms/include/js/spec/student_account/finish_auth_spec.js'
,
'lms/include/js/spec/student_account/login_spec.js'
,
'lms/include/js/spec/student_account/institution_login_spec.js'
,
'lms/include/js/spec/student_account/register_spec.js'
,
'lms/include/js/spec/student_account/password_reset_spec.js'
,
'lms/include/js/spec/student_account/enrollment_spec.js'
,
...
...
lms/static/js/spec/student_account/access_spec.js
View file @
7437bcfe
...
...
@@ -58,6 +58,7 @@ define([
thirdPartyAuth
:
{
currentProvider
:
null
,
providers
:
[],
secondaryProviders
:
[{
name
:
"provider"
}],
finishAuthUrl
:
finishAuthUrl
},
nextUrl
:
nextUrl
,
// undefined for default
...
...
@@ -97,6 +98,8 @@ define([
TemplateHelpers
.
installTemplate
(
'templates/student_account/register'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/password_reset'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/form_field'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/institution_login'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/institution_register'
);
// Stub analytics tracking
window
.
analytics
=
jasmine
.
createSpyObj
(
'analytics'
,
[
'track'
,
'page'
,
'pageview'
,
'trackLink'
]);
...
...
@@ -135,6 +138,30 @@ define([
assertForms
(
'#login-form'
,
'#register-form'
);
});
it
(
'toggles between the login and institution login view'
,
function
()
{
ajaxSpyAndInitialize
(
this
,
'login'
);
// Simulate clicking on institution login button
$
(
'#login-form .button-secondary-login[data-type="institution_login"]'
).
click
();
assertForms
(
'#institution_login-form'
,
'#login-form'
);
// Simulate selection of the login form
selectForm
(
'login'
);
assertForms
(
'#login-form'
,
'#institution_login-form'
);
});
it
(
'toggles between the register and institution register view'
,
function
()
{
ajaxSpyAndInitialize
(
this
,
'register'
);
// Simulate clicking on institution login button
$
(
'#register-form .button-secondary-login[data-type="institution_login"]'
).
click
();
assertForms
(
'#institution_login-form'
,
'#register-form'
);
// Simulate selection of the login form
selectForm
(
'register'
);
assertForms
(
'#register-form'
,
'#institution_login-form'
);
});
it
(
'displays the reset password form'
,
function
()
{
ajaxSpyAndInitialize
(
this
,
'login'
);
...
...
lms/static/js/spec/student_account/institution_login_spec.js
0 → 100644
View file @
7437bcfe
define
([
'jquery'
,
'underscore'
,
'common/js/spec_helpers/template_helpers'
,
'js/student_account/views/InstitutionLoginView'
,
],
function
(
$
,
_
,
TemplateHelpers
,
InstitutionLoginView
)
{
'use strict'
;
describe
(
'edx.student.account.InstitutionLoginView'
,
function
()
{
var
view
=
null
,
PLATFORM_NAME
=
'edX'
,
THIRD_PARTY_AUTH
=
{
currentProvider
:
null
,
providers
:
[],
secondaryProviders
:
[
{
id
:
'oa2-google-oauth2'
,
name
:
'Google'
,
iconClass
:
'fa-google-plus'
,
loginUrl
:
'/auth/login/google-oauth2/?auth_entry=account_login'
,
registerUrl
:
'/auth/login/google-oauth2/?auth_entry=account_register'
},
{
id
:
'oa2-facebook'
,
name
:
'Facebook'
,
iconClass
:
'fa-facebook'
,
loginUrl
:
'/auth/login/facebook/?auth_entry=account_login'
,
registerUrl
:
'/auth/login/facebook/?auth_entry=account_register'
}
]
};
var
createInstLoginView
=
function
(
mode
)
{
// Initialize the login view
view
=
new
InstitutionLoginView
({
mode
:
mode
,
thirdPartyAuth
:
THIRD_PARTY_AUTH
,
platformName
:
PLATFORM_NAME
});
view
.
render
();
};
beforeEach
(
function
()
{
setFixtures
(
'<div id="institution_login-form"></div>'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/institution_login'
);
TemplateHelpers
.
installTemplate
(
'templates/student_account/institution_register'
);
});
it
(
'displays a list of providers'
,
function
()
{
createInstLoginView
(
'login'
);
expect
(
$
(
'#institution_login-form'
).
html
()).
not
.
toBe
(
""
);
var
$google
=
$
(
'li a:contains("Google")'
);
expect
(
$google
).
toBeVisible
();
expect
(
$google
).
toHaveAttr
(
'href'
,
'/auth/login/google-oauth2/?auth_entry=account_login'
);
var
$facebook
=
$
(
'li a:contains("Facebook")'
);
expect
(
$facebook
).
toBeVisible
();
expect
(
$facebook
).
toHaveAttr
(
'href'
,
'/auth/login/facebook/?auth_entry=account_login'
);
});
it
(
'displays a list of providers'
,
function
()
{
createInstLoginView
(
'register'
);
expect
(
$
(
'#institution_login-form'
).
html
()).
not
.
toBe
(
""
);
var
$google
=
$
(
'li a:contains("Google")'
);
expect
(
$google
).
toBeVisible
();
expect
(
$google
).
toHaveAttr
(
'href'
,
'/auth/login/google-oauth2/?auth_entry=account_register'
);
var
$facebook
=
$
(
'li a:contains("Facebook")'
);
expect
(
$facebook
).
toBeVisible
();
expect
(
$facebook
).
toHaveAttr
(
'href'
,
'/auth/login/facebook/?auth_entry=account_register'
);
});
});
});
lms/static/js/student_account/views/AccessView.js
View file @
7437bcfe
...
...
@@ -18,7 +18,8 @@ var edx = edx || {};
subview
:
{
login
:
{},
register
:
{},
passwordHelp
:
{}
passwordHelp
:
{},
institutionLogin
:
{}
},
nextUrl
:
'/dashboard'
,
...
...
@@ -52,7 +53,8 @@ var edx = edx || {};
this
.
formDescriptions
=
{
login
:
obj
.
loginFormDesc
,
register
:
obj
.
registrationFormDesc
,
reset
:
obj
.
passwordResetFormDesc
reset
:
obj
.
passwordResetFormDesc
,
institution_login
:
null
};
this
.
platformName
=
obj
.
platformName
;
...
...
@@ -148,6 +150,16 @@ var edx = edx || {};
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
this
.
listenTo
(
this
.
subview
.
register
,
'auth-complete'
,
this
.
authComplete
);
},
institution_login
:
function
(
unused
)
{
this
.
subview
.
institutionLogin
=
new
edx
.
student
.
account
.
InstitutionLoginView
({
thirdPartyAuth
:
this
.
thirdPartyAuth
,
platformName
:
this
.
platformName
,
mode
:
this
.
activeForm
});
this
.
subview
.
institutionLogin
.
render
();
}
},
...
...
@@ -180,9 +192,11 @@ var edx = edx || {};
category
:
'user-engagement'
});
if
(
!
this
.
form
.
isLoaded
(
$form
)
)
{
// Load the form. Institution login is always refreshed since it changes based on the previous form.
if
(
!
this
.
form
.
isLoaded
(
$form
)
||
type
==
"institution_login"
)
{
this
.
loadForm
(
type
);
}
this
.
activeForm
=
type
;
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'.submission-success'
)
);
this
.
element
.
hide
(
$
(
this
.
el
).
find
(
'.form-wrapper'
)
);
...
...
@@ -190,11 +204,13 @@ var edx = edx || {};
this
.
element
.
scrollTop
(
$anchor
);
// Update url without reloading page
History
.
pushState
(
null
,
document
.
title
,
'/'
+
type
+
queryStr
);
if
(
type
!=
"institution_login"
)
{
History
.
pushState
(
null
,
document
.
title
,
'/'
+
type
+
queryStr
);
}
analytics
.
page
(
'login_and_registration'
,
type
);
// Focus on the form
document
.
getElementById
(
type
).
focus
();
$
(
"#"
+
type
).
focus
();
},
/**
...
...
lms/static/js/student_account/views/FormView.js
View file @
7437bcfe
...
...
@@ -215,7 +215,9 @@ var edx = edx || {};
submitForm
:
function
(
event
)
{
var
data
=
this
.
getFormData
();
event
.
preventDefault
();
if
(
!
_
.
isUndefined
(
event
))
{
event
.
preventDefault
();
}
this
.
toggleDisableButton
(
true
);
...
...
lms/static/js/student_account/views/InstitutionLoginView.js
0 → 100644
View file @
7437bcfe
var
edx
=
edx
||
{};
(
function
(
$
,
_
,
Backbone
)
{
'use strict'
;
edx
.
student
=
edx
.
student
||
{};
edx
.
student
.
account
=
edx
.
student
.
account
||
{};
edx
.
student
.
account
.
InstitutionLoginView
=
Backbone
.
View
.
extend
({
el
:
'#institution_login-form'
,
initialize
:
function
(
data
)
{
var
tpl
=
data
.
mode
==
"register"
?
'#institution_register-tpl'
:
'#institution_login-tpl'
;
this
.
tpl
=
$
(
tpl
).
html
();
this
.
providers
=
data
.
thirdPartyAuth
.
secondaryProviders
||
[];
this
.
platformName
=
data
.
platformName
;
},
render
:
function
()
{
$
(
this
.
el
).
html
(
_
.
template
(
this
.
tpl
,
{
// We pass the context object to the template so that
// we can perform variable interpolation using sprintf
providers
:
this
.
providers
,
platformName
:
this
.
platformName
}));
return
this
;
}
});
})(
jQuery
,
_
,
Backbone
);
lms/static/js/student_account/views/LoginView.js
View file @
7437bcfe
...
...
@@ -25,6 +25,9 @@ var edx = edx || {};
preRender
:
function
(
data
)
{
this
.
providers
=
data
.
thirdPartyAuth
.
providers
||
[];
this
.
hasSecondaryProviders
=
(
data
.
thirdPartyAuth
.
secondaryProviders
&&
data
.
thirdPartyAuth
.
secondaryProviders
.
length
);
this
.
currentProvider
=
data
.
thirdPartyAuth
.
currentProvider
||
''
;
this
.
errorMessage
=
data
.
thirdPartyAuth
.
errorMessage
||
''
;
this
.
platformName
=
data
.
platformName
;
...
...
@@ -45,6 +48,7 @@ var edx = edx || {};
currentProvider
:
this
.
currentProvider
,
errorMessage
:
this
.
errorMessage
,
providers
:
this
.
providers
,
hasSecondaryProviders
:
this
.
hasSecondaryProviders
,
platformName
:
this
.
platformName
}
}));
...
...
lms/static/js/student_account/views/RegisterView.js
View file @
7437bcfe
...
...
@@ -22,9 +22,13 @@ var edx = edx || {};
preRender
:
function
(
data
)
{
this
.
providers
=
data
.
thirdPartyAuth
.
providers
||
[];
this
.
hasSecondaryProviders
=
(
data
.
thirdPartyAuth
.
secondaryProviders
&&
data
.
thirdPartyAuth
.
secondaryProviders
.
length
);
this
.
currentProvider
=
data
.
thirdPartyAuth
.
currentProvider
||
''
;
this
.
errorMessage
=
data
.
thirdPartyAuth
.
errorMessage
||
''
;
this
.
platformName
=
data
.
platformName
;
this
.
autoSubmit
=
data
.
thirdPartyAuth
.
autoSubmitRegForm
;
this
.
listenTo
(
this
.
model
,
'sync'
,
this
.
saveSuccess
);
},
...
...
@@ -41,12 +45,19 @@ var edx = edx || {};
currentProvider
:
this
.
currentProvider
,
errorMessage
:
this
.
errorMessage
,
providers
:
this
.
providers
,
hasSecondaryProviders
:
this
.
hasSecondaryProviders
,
platformName
:
this
.
platformName
}
}));
this
.
postRender
();
if
(
this
.
autoSubmit
)
{
$
(
this
.
el
).
hide
();
$
(
'#register-honor_code'
).
prop
(
'checked'
,
true
);
this
.
submitForm
();
}
return
this
;
},
...
...
@@ -63,6 +74,7 @@ var edx = edx || {};
},
saveError
:
function
(
error
)
{
$
(
this
.
el
).
show
();
// Show in case the form was hidden for auto-submission
this
.
errors
=
_
.
flatten
(
_
.
map
(
JSON
.
parse
(
error
.
responseText
),
...
...
@@ -76,6 +88,13 @@ var edx = edx || {};
);
this
.
setErrors
();
this
.
toggleDisableButton
(
false
);
}
},
postFormSubmission
:
function
()
{
if
(
_
.
compact
(
this
.
errors
).
length
)
{
// The form did not get submitted due to validation errors.
$
(
this
.
el
).
show
();
// Show in case the form was hidden for auto-submission
}
},
});
})(
jQuery
,
_
,
gettext
);
lms/static/sass/views/_login-register.scss
View file @
7437bcfe
...
...
@@ -14,6 +14,7 @@ $sm-btn-linkedin: #0077b5;
background
:
$white
;
min-height
:
100%
;
width
:
100%
;
$third-party-button-height
:
(
$baseline
*
1
.75
);
h2
{
@extend
%t-title5
;
...
...
@@ -22,6 +23,10 @@ $sm-btn-linkedin: #0077b5;
font-family
:
$sans-serif
;
}
.instructions
{
@extend
%t-copy-base
;
}
/* Temp. fix until applied globally */
>
{
@include
box-sizing
(
border-box
);
...
...
@@ -67,10 +72,11 @@ $sm-btn-linkedin: #0077b5;
}
}
form
{
form
,
.wrapper-other-login
{
border
:
1px
solid
$gray-l4
;
border-radius
:
5px
;
padding
:
0
px
25px
20px
25px
;
border-radius
:
(
$baseline
/
4
)
;
padding
:
0
(
$baseline
*
1
.25
)
$baseline
(
$baseline
*
1
.25
)
;
}
.section-title
{
...
...
@@ -106,16 +112,20 @@ $sm-btn-linkedin: #0077b5;
}
}
.nav-btn
{
%nav-btn-base
{
@extend
%btn-secondary-blue-outline
;
width
:
100%
;
height
:
(
$baseline
*
2
);
text-transform
:
none
;
text-shadow
:
none
;
font-weight
:
600
;
letter-spacing
:
normal
;
}
.nav-btn
{
@extend
%nav-btn-base
;
@extend
%t-strong
;
}
.form-type
,
.toggle-form
{
@include
box-sizing
(
border-box
);
...
...
@@ -348,29 +358,31 @@ $sm-btn-linkedin: #0077b5;
.login-provider {
@extend %btn-secondary-grey-outline;
width: 130px;
padding: 0 0 0 ($baseline*2);
height: 34px;
text-align: left;
text-shadow: none;
text-transform: none;
@extend %t-action4;
@include padding(0, 0, 0, $baseline*2);
@include text-align(left);
position: relative;
font-size: 0.8em;
margin-right: ($baseline/4);
margin-bottom: $baseline;
border-color: $lightGrey1;
&:nth-of-type(odd) {
margin-right: 13px
;
}
width: $baseline*6.5;
height: $third-party-button-height;
text-shadow: none
;
text-transform: none;
.icon {
color: white;
@include left(0);
position: absolute;
top: -1px;
left: 0;
width: 30px;
height: 34px;
line-height: 34px;
bottom: -1px;
background: $m-blue-d3;
line-height: $third-party-button-height;
text-align: center;
color: $white;
}
&:hover,
...
...
@@ -378,16 +390,12 @@ $sm-btn-linkedin: #0077b5;
background-image: none;
.icon {
height: 32px;
line-height: 32px;
top: 0;
bottom: 0;
line-height: ($third-party-button-height - 2px);
}
}
&:last-child {
margin-bottom: $baseline;
}
&.button-oa2-google-oauth2 {
color: $sm-btn-google;
...
...
@@ -447,6 +455,19 @@ $sm-btn-linkedin: #0077b5;
}
.button-secondary-login {
@extend %nav-btn-base;
@extend %t-action4;
@extend %t-regular;
border-color: $lightGrey1;
padding: 0;
height: $third-party-button-height;
&:hover {
border-color: $m-blue-d3;
}
}
/** Error Container - from _account.scss **/
.status {
@include box-sizing(border-box);
...
...
@@ -503,6 +524,13 @@ $sm-btn-linkedin: #0077b5;
}
}
.institution-list {
.institution {
@extend %t-copy-base;
}
}
@include media( max-width 330px) {
.form-type {
width: 98%;
...
...
lms/templates/student_account/access.underscore
View file @
7437bcfe
...
...
@@ -9,3 +9,7 @@
<section id="password-reset-anchor" class="form-type">
<div id="password-reset-form" class="form-wrapper hidden" aria-hidden="true"></div>
</section>
<section id="institution_login-anchor" class="form-type">
<div id="institution_login-form" class="form-wrapper hidden" aria-hidden="true"></div>
</section>
lms/templates/student_account/institution_login.underscore
0 → 100644
View file @
7437bcfe
<div class="wrapper-other-login">
<div class="section-title lines">
<h2>
<span class="text">
<%- gettext("Sign in with Institution/Campus Credentials") %>
</span>
</h2>
</div>
<p class="instructions"><%- gettext("Choose your institution from the list below:") %></p>
<ul class="institution-list">
<% _.each( _.sortBy(providers, "name"), function( provider ) {
if ( provider.loginUrl ) { %>
<li class="institution">
<a class="institution-login-link" href="<%- provider.loginUrl %>"><%- provider.name %></a>
</li>
<% }
}); %>
</ul>
<div class="section-title lines">
<h2>
<span class="text"><%- gettext("or") %></span>
</h2>
</div>
<div class="toggle-form">
<button class="nav-btn form-toggle" data-type="login"><%- gettext("Back to sign in") %></button>
</div>
</div>
lms/templates/student_account/institution_register.underscore
0 → 100644
View file @
7437bcfe
<div class="wrapper-other-login">
<div class="section-title lines">
<h2>
<span class="text">
<%- gettext("Register with Institution/Campus Credentials") %>
</span>
</h2>
</div>
<p class="instructions"><%- gettext("Choose your institution from the list below:") %></p>
<ul class="institution-list">
<% _.each( _.sortBy(providers, "name"), function( provider ) {
if ( provider.registerUrl ) { %>
<li class="institution">
<a class="institution-login-link" href="<%- provider.registerUrl %>"><%- provider.name %></a>
</li>
<% }
}); %>
</ul>
<div class="section-title lines">
<h2>
<span class="text"><%- gettext("or") %></span>
</h2>
</div>
<div class="toggle-form">
<button class="nav-btn form-toggle" data-type="register"><%- gettext("Register through edX") %></button>
</div>
</div>
lms/templates/student_account/login.underscore
View file @
7437bcfe
...
...
@@ -39,7 +39,7 @@
<button type="submit" class="action action-primary action-update js-login login-button"><%- gettext("Sign in") %></button>
<% if ( context.providers.length > 0 && !context.currentProvider ) { %>
<% if ( context.providers.length > 0 && !context.currentProvider
|| context.hasSecondaryProviders
) { %>
<div class="login-providers">
<div class="section-title lines">
<h2>
...
...
@@ -55,6 +55,12 @@
</button>
<% }
}); %>
<% if ( context.hasSecondaryProviders ) { %>
<button type="button" class="button-secondary-login form-toggle" data-type="institution_login">
<%- gettext("Use my institution/campus credentials") %>
</button>
<% } %>
</div>
<% } %>
</form>
...
...
lms/templates/student_account/login_and_register.html
View file @
7437bcfe
...
...
@@ -15,7 +15,7 @@
</
%
block>
<
%
block
name=
"header_extras"
>
% for template_name in ["account", "access", "form_field", "login", "register", "password_reset"]:
% for template_name in ["account", "access", "form_field", "login", "register", "
institution_login", "institution_register", "
password_reset"]:
<script
type=
"text/template"
id=
"${template_name}-tpl"
>
<%
static
:
include
path
=
"student_account/${template_name}.underscore"
/>
</script>
...
...
lms/templates/student_account/register.underscore
View file @
7437bcfe
...
...
@@ -19,7 +19,7 @@
<%- _.sprintf( gettext("We just need a little more information before you start learning with %(platformName)s."), context ) %>
</p>
</div>
<% } else if ( context.providers.length > 0 ) { %>
<% } else if ( context.providers.length > 0
|| context.hasSecondaryProviders
) { %>
<div class="login-providers">
<div class="section-title lines">
<h2>
...
...
@@ -35,6 +35,12 @@
</button>
<% }
}); %>
<% if ( context.hasSecondaryProviders ) { %>
<button type="button" class="button-secondary-login form-toggle" data-type="institution_login">
<%- gettext("Use my institution/campus credentials") %>
</button>
<% } %>
</div>
<div class="section-title lines">
<h2>
...
...
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