Merge pull request #8140 from edx/feature/shibboleth-tpa
Feature: Shibboleth/SAML SSO
This commit is contained in:
@@ -84,11 +84,13 @@
|
||||
'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',
|
||||
'js/student_account/views/RegisterView': 'js/student_account/views/RegisterView',
|
||||
'js/student_account/views/AccessView': 'js/student_account/views/AccessView',
|
||||
'js/student_account/views/HintedLoginView': 'js/student_account/views/HintedLoginView',
|
||||
'js/student_profile/profile': 'js/student_profile/profile',
|
||||
'js/student_profile/views/learner_profile_fields': 'js/student_profile/views/learner_profile_fields',
|
||||
'js/student_profile/views/learner_profile_factory': 'js/student_profile/views/learner_profile_factory',
|
||||
@@ -410,6 +412,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']
|
||||
@@ -439,6 +449,15 @@
|
||||
'js/student_account/views/FormView'
|
||||
]
|
||||
},
|
||||
'js/student_account/views/HintedLoginView': {
|
||||
exports: 'edx.student.account.HintedLoginView',
|
||||
deps: [
|
||||
'jquery',
|
||||
'underscore',
|
||||
'backbone',
|
||||
'gettext'
|
||||
]
|
||||
},
|
||||
'js/student_account/views/AccessView': {
|
||||
exports: 'edx.student.account.AccessView',
|
||||
deps: [
|
||||
@@ -450,6 +469,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',
|
||||
@@ -612,7 +632,9 @@
|
||||
'lms/include/js/spec/student_account/account_spec.js',
|
||||
'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/hinted_login_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',
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
@@ -32,12 +32,14 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
|
||||
var AUTH_DATA = {
|
||||
'providers': [
|
||||
{
|
||||
'id': 'oa2-network1',
|
||||
'name': "Network1",
|
||||
'connected': true,
|
||||
'connect_url': 'yetanother1.com/auth/connect',
|
||||
'disconnect_url': 'yetanother1.com/auth/disconnect'
|
||||
},
|
||||
{
|
||||
'id': 'oa2-network2',
|
||||
'name': "Network2",
|
||||
'connected': true,
|
||||
'connect_url': 'yetanother2.com/auth/connect',
|
||||
|
||||
71
lms/static/js/spec/student_account/hinted_login_spec.js
Normal file
71
lms/static/js/spec/student_account/hinted_login_spec.js
Normal file
@@ -0,0 +1,71 @@
|
||||
define([
|
||||
'jquery',
|
||||
'underscore',
|
||||
'common/js/spec_helpers/template_helpers',
|
||||
'common/js/spec_helpers/ajax_helpers',
|
||||
'js/student_account/views/HintedLoginView',
|
||||
], function($, _, TemplateHelpers, AjaxHelpers, HintedLoginView) {
|
||||
'use strict';
|
||||
describe('edx.student.account.HintedLoginView', function() {
|
||||
|
||||
var view = null,
|
||||
requests = null,
|
||||
PLATFORM_NAME = 'edX',
|
||||
THIRD_PARTY_AUTH = {
|
||||
currentProvider: null,
|
||||
providers: [
|
||||
{
|
||||
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'
|
||||
}
|
||||
]
|
||||
},
|
||||
HINTED_PROVIDER = "oa2-google-oauth2";
|
||||
|
||||
var createHintedLoginView = function(test) {
|
||||
// Initialize the login view
|
||||
view = new HintedLoginView({
|
||||
thirdPartyAuth: THIRD_PARTY_AUTH,
|
||||
hintedProvider: HINTED_PROVIDER,
|
||||
platformName: PLATFORM_NAME
|
||||
});
|
||||
|
||||
// Mock the redirect call
|
||||
spyOn( view, 'redirect' ).andCallFake( function() {} );
|
||||
|
||||
view.render();
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures('<div id="hinted-login-form"></div>');
|
||||
TemplateHelpers.installTemplate('templates/student_account/hinted_login');
|
||||
});
|
||||
|
||||
it('displays a choice as two buttons', function() {
|
||||
createHintedLoginView(this);
|
||||
|
||||
expect($('.proceed-button.button-oa2-google-oauth2')).toBeVisible();
|
||||
expect($('.form-toggle')).toBeVisible();
|
||||
expect($('.proceed-button.button-oa2-facebook')).not.toBeVisible();
|
||||
});
|
||||
|
||||
it('redirects the user to the hinted provider if the user clicks the proceed button', function() {
|
||||
createHintedLoginView(this);
|
||||
|
||||
// Click the "Yes, proceed" button
|
||||
$('.proceed-button').click();
|
||||
|
||||
expect(view.redirect).toHaveBeenCalledWith( '/auth/login/google-oauth2/?auth_entry=account_login' );
|
||||
});
|
||||
});
|
||||
});
|
||||
80
lms/static/js/spec/student_account/institution_login_spec.js
Normal file
80
lms/static/js/spec/student_account/institution_login_spec.js
Normal file
@@ -0,0 +1,80 @@
|
||||
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'
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -25,12 +25,14 @@ define([
|
||||
currentProvider: null,
|
||||
providers: [
|
||||
{
|
||||
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',
|
||||
@@ -195,8 +197,8 @@ define([
|
||||
createLoginView(this);
|
||||
|
||||
// Verify that Google and Facebook registration buttons are displayed
|
||||
expect($('.button-Google')).toBeVisible();
|
||||
expect($('.button-Facebook')).toBeVisible();
|
||||
expect($('.button-oa2-google-oauth2')).toBeVisible();
|
||||
expect($('.button-oa2-facebook')).toBeVisible();
|
||||
});
|
||||
|
||||
it('displays a link to the password reset form', function() {
|
||||
|
||||
@@ -32,12 +32,14 @@ define([
|
||||
currentProvider: null,
|
||||
providers: [
|
||||
{
|
||||
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',
|
||||
@@ -284,8 +286,8 @@ define([
|
||||
createRegisterView(this);
|
||||
|
||||
// Verify that Google and Facebook registration buttons are displayed
|
||||
expect($('.button-Google')).toBeVisible();
|
||||
expect($('.button-Facebook')).toBeVisible();
|
||||
expect($('.button-oa2-google-oauth2')).toBeVisible();
|
||||
expect($('.button-oa2-facebook')).toBeVisible();
|
||||
});
|
||||
|
||||
it('validates registration form fields', function() {
|
||||
|
||||
@@ -11,6 +11,7 @@ var edx = edx || {};
|
||||
return new edx.student.account.AccessView({
|
||||
mode: container.data('initial-mode'),
|
||||
thirdPartyAuth: container.data('third-party-auth'),
|
||||
thirdPartyAuthHint: container.data('third-party-auth-hint'),
|
||||
nextUrl: container.data('next-url'),
|
||||
platformName: container.data('platform-name'),
|
||||
loginFormDesc: container.data('login-form-desc'),
|
||||
|
||||
@@ -18,7 +18,9 @@ var edx = edx || {};
|
||||
subview: {
|
||||
login: {},
|
||||
register: {},
|
||||
passwordHelp: {}
|
||||
passwordHelp: {},
|
||||
institutionLogin: {},
|
||||
hintedLogin: {}
|
||||
},
|
||||
|
||||
nextUrl: '/dashboard',
|
||||
@@ -42,6 +44,8 @@ var edx = edx || {};
|
||||
providers: []
|
||||
};
|
||||
|
||||
this.thirdPartyAuthHint = obj.thirdPartyAuthHint || null;
|
||||
|
||||
if (obj.nextUrl) {
|
||||
// Ensure that the next URL is internal for security reasons
|
||||
if ( ! window.isExternal( obj.nextUrl ) ) {
|
||||
@@ -52,7 +56,9 @@ var edx = edx || {};
|
||||
this.formDescriptions = {
|
||||
login: obj.loginFormDesc,
|
||||
register: obj.registrationFormDesc,
|
||||
reset: obj.passwordResetFormDesc
|
||||
reset: obj.passwordResetFormDesc,
|
||||
institution_login: null,
|
||||
hinted_login: null
|
||||
};
|
||||
|
||||
this.platformName = obj.platformName;
|
||||
@@ -148,6 +154,26 @@ 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();
|
||||
},
|
||||
|
||||
hinted_login: function ( unused ) {
|
||||
this.subview.hintedLogin = new edx.student.account.HintedLoginView({
|
||||
thirdPartyAuth: this.thirdPartyAuth,
|
||||
hintedProvider: this.thirdPartyAuthHint,
|
||||
platformName: this.platformName
|
||||
});
|
||||
|
||||
this.subview.hintedLogin.render();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -180,9 +206,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 +218,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();
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -215,7 +215,9 @@ var edx = edx || {};
|
||||
submitForm: function( event ) {
|
||||
var data = this.getFormData();
|
||||
|
||||
event.preventDefault();
|
||||
if (!_.isUndefined(event)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
this.toggleDisableButton(true);
|
||||
|
||||
|
||||
52
lms/static/js/student_account/views/HintedLoginView.js
Normal file
52
lms/static/js/student_account/views/HintedLoginView.js
Normal file
@@ -0,0 +1,52 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, gettext) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
edx.student.account.HintedLoginView = Backbone.View.extend({
|
||||
el: '#hinted-login-form',
|
||||
|
||||
tpl: '#hinted_login-tpl',
|
||||
|
||||
events: {
|
||||
'click .proceed-button': 'proceedWithHintedAuth'
|
||||
},
|
||||
|
||||
formType: 'hinted-login',
|
||||
|
||||
initialize: function( data ) {
|
||||
this.tpl = $(this.tpl).html();
|
||||
this.providers = data.thirdPartyAuth.providers || [];
|
||||
this.hintedProvider = _.findWhere(this.providers, {id: data.hintedProvider})
|
||||
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,
|
||||
hintedProvider: this.hintedProvider
|
||||
}));
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
proceedWithHintedAuth: function( event ) {
|
||||
this.redirect(this.hintedProvider.loginUrl);
|
||||
},
|
||||
|
||||
/**
|
||||
* Redirect to a URL. Mainly useful for mocking out in tests.
|
||||
* @param {string} url The URL to redirect to.
|
||||
*/
|
||||
redirect: function( url ) {
|
||||
window.location.href = url;
|
||||
}
|
||||
});
|
||||
})(jQuery, _, gettext);
|
||||
30
lms/static/js/student_account/views/InstitutionLoginView.js
Normal file
30
lms/static/js/student_account/views/InstitutionLoginView.js
Normal file
@@ -0,0 +1,30 @@
|
||||
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);
|
||||
@@ -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
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
screenReaderTitle: interpolate_text(
|
||||
gettext("Connect your {accountName} account"), {accountName: provider['name']}
|
||||
),
|
||||
valueAttribute: 'auth-' + provider.name.toLowerCase(),
|
||||
valueAttribute: 'auth-' + provider.id,
|
||||
helpMessage: '',
|
||||
connected: provider.connected,
|
||||
connectUrl: provider.connect_url,
|
||||
|
||||
@@ -532,30 +532,30 @@
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.button-Google:hover, &.button-Google:focus {
|
||||
&.button-oa2-google-oauth2:hover, &.button-oa2-google-oauth2:focus {
|
||||
background-color: #dd4b39;
|
||||
border: 1px solid #A5382B;
|
||||
}
|
||||
|
||||
&.button-Google:hover {
|
||||
&.button-oa2-google-oauth2:hover {
|
||||
box-shadow: 0 2px 1px 0 #8D3024;
|
||||
}
|
||||
|
||||
&.button-Facebook:hover, &.button-Facebook:focus {
|
||||
&.button-oa2-facebook:hover, &.button-oa2-facebook:focus {
|
||||
background-color: #3b5998;
|
||||
border: 1px solid #263A62;
|
||||
}
|
||||
|
||||
&.button-Facebook:hover {
|
||||
&.button-oa2-facebook:hover {
|
||||
box-shadow: 0 2px 1px 0 #30487C;
|
||||
}
|
||||
|
||||
&.button-LinkedIn:hover , &.button-LinkedIn:focus {
|
||||
&.button-oa2-linkedin-oauth2:hover , &.button-oa2-linkedin-oauth2:focus {
|
||||
background-color: #0077b5;
|
||||
border: 1px solid #06527D;
|
||||
}
|
||||
|
||||
&.button-LinkedIn:hover {
|
||||
&.button-oa2-linkedin-oauth2:hover {
|
||||
box-shadow: 0 2px 1px 0 #005D8E;
|
||||
}
|
||||
|
||||
|
||||
@@ -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: 0px 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;
|
||||
@extend %t-action4;
|
||||
|
||||
@include padding(0, 0, 0, $baseline*2);
|
||||
@include text-align(left);
|
||||
|
||||
position: relative;
|
||||
margin-right: ($baseline/4);
|
||||
margin-bottom: $baseline;
|
||||
border-color: $lightGrey1;
|
||||
width: $baseline*6.5;
|
||||
height: $third-party-button-height;
|
||||
text-shadow: none;
|
||||
text-transform: none;
|
||||
position: relative;
|
||||
font-size: 0.8em;
|
||||
border-color: $lightGrey1;
|
||||
|
||||
&:nth-of-type(odd) {
|
||||
margin-right: 13px;
|
||||
}
|
||||
|
||||
.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,17 +390,13 @@ $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-Google {
|
||||
&.button-oa2-google-oauth2 {
|
||||
color: $sm-btn-google;
|
||||
|
||||
.icon {
|
||||
@@ -407,7 +415,7 @@ $sm-btn-linkedin: #0077b5;
|
||||
}
|
||||
}
|
||||
|
||||
&.button-Facebook {
|
||||
&.button-oa2-facebook {
|
||||
color: $sm-btn-facebook;
|
||||
|
||||
.icon {
|
||||
@@ -426,7 +434,7 @@ $sm-btn-linkedin: #0077b5;
|
||||
}
|
||||
}
|
||||
|
||||
&.button-LinkedIn {
|
||||
&.button-oa2-linkedin-oauth2 {
|
||||
color: $sm-btn-linkedin;
|
||||
|
||||
.icon {
|
||||
@@ -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%;
|
||||
|
||||
Reference in New Issue
Block a user