Logging in no longer causes page refresh.
This patch updates the LastLocation service to store data from the UI-Router state, rather than the url, which allows us to navigate to a state directly using UI-Router. It also updates the SearchParamProvider to grab its data in the config phase, before the UI-Router is initialized. This permits us to forcefully remove any query parameters passed to our application in the URL - as happens during the OAuth exchange - before the router is aware of them, and thus circumvents an infinite digest loop. The end result is that StoryBoard no longer has to reload itself after a user is successfully authorized. Note: The URL class used is not supported by PhantomJS. As such, PhantomJS has been removed from our karma.conf. Change-Id: Iae113544ad35708f63c5636189f0c88990eab203
This commit is contained in:
parent
4b9dbd1d99
commit
a3abee9058
@ -29,7 +29,6 @@ module.exports = function (config) {
|
|||||||
'karma-coverage',
|
'karma-coverage',
|
||||||
'karma-jasmine',
|
'karma-jasmine',
|
||||||
'karma-html-reporter',
|
'karma-html-reporter',
|
||||||
'karma-phantomjs-launcher',
|
|
||||||
'karma-chrome-launcher',
|
'karma-chrome-launcher',
|
||||||
'karma-firefox-launcher'
|
'karma-firefox-launcher'
|
||||||
],
|
],
|
||||||
@ -52,7 +51,7 @@ module.exports = function (config) {
|
|||||||
|
|
||||||
colors: false,
|
colors: false,
|
||||||
|
|
||||||
browsers: [ 'PhantomJS', 'Firefox' ],
|
browsers: [ 'Firefox' ],
|
||||||
|
|
||||||
preprocessors: {
|
preprocessors: {
|
||||||
'./dist/js/storyboard.js': ['coverage']
|
'./dist/js/storyboard.js': ['coverage']
|
||||||
|
@ -22,8 +22,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
angular.module('sb.auth').controller('AuthAuthorizeController',
|
angular.module('sb.auth').controller('AuthAuthorizeController',
|
||||||
function ($stateParams, $state, $log, OpenId, $window, LastLocation,
|
function ($stateParams, $state, $log, OpenId) {
|
||||||
localStorageService) {
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// First, check for the edge case where the API returns an error code
|
// First, check for the edge case where the API returns an error code
|
||||||
@ -36,9 +35,6 @@ angular.module('sb.auth').controller('AuthAuthorizeController',
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the last path...
|
|
||||||
localStorageService.set('lastPath', LastLocation.get());
|
|
||||||
|
|
||||||
// We're not an error, let's fire the authorization.
|
// We're not an error, let's fire the authorization.
|
||||||
OpenId.authorize();
|
OpenId.authorize();
|
||||||
});
|
});
|
||||||
|
@ -36,21 +36,6 @@ angular.module('sb.auth').controller('AuthTokenController',
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate any previously stored redirect path
|
|
||||||
function buildNextPath() {
|
|
||||||
|
|
||||||
// First, do we have a stored last location?
|
|
||||||
var location = LastLocation.get();
|
|
||||||
|
|
||||||
// Sanity check on the location, we don't want to bounce straight
|
|
||||||
// back into auth.
|
|
||||||
if (location.indexOf('/auth') > -1) {
|
|
||||||
location = '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Looks like there's no error, so let's see if we can resolve a token.
|
// Looks like there's no error, so let's see if we can resolve a token.
|
||||||
// TODO: Finish implementing.
|
// TODO: Finish implementing.
|
||||||
OpenId.token($searchParams)
|
OpenId.token($searchParams)
|
||||||
@ -58,9 +43,7 @@ angular.module('sb.auth').controller('AuthTokenController',
|
|||||||
function (token) {
|
function (token) {
|
||||||
Session.updateSession(token)
|
Session.updateSession(token)
|
||||||
.then(function () {
|
.then(function () {
|
||||||
var nextPath = buildNextPath();
|
LastLocation.go('sb.page.about', {});
|
||||||
$window.location.href =
|
|
||||||
UrlUtil.buildApplicationUrl(nextPath);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
|
@ -18,18 +18,46 @@
|
|||||||
* Utility injector, injects the query parameters from the NON-hashbang URL as
|
* Utility injector, injects the query parameters from the NON-hashbang URL as
|
||||||
* $searchParams.
|
* $searchParams.
|
||||||
*/
|
*/
|
||||||
angular.module('sb.util').factory('$searchParams',
|
angular.module('sb.util').provider('$searchParams',
|
||||||
function ($window, UrlUtil) {
|
function ($windowProvider) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var params = {};
|
var pageParams = {};
|
||||||
var search = $window.location.search;
|
|
||||||
if (!!search) {
|
this.extractSearchParameters = function () {
|
||||||
|
var window = $windowProvider.$get();
|
||||||
|
var search = window.location.search;
|
||||||
if (search.charAt(0) === '?') {
|
if (search.charAt(0) === '?') {
|
||||||
search = search.substr(1);
|
search = search.substr(1);
|
||||||
}
|
}
|
||||||
|
var queryComponents = search.split('&');
|
||||||
|
for (var i = 0; i < queryComponents.length; i++) {
|
||||||
|
var parts = queryComponents[i].split('=');
|
||||||
|
var key = decodeURIComponent(parts[0]) || null;
|
||||||
|
var value = decodeURIComponent(parts[1]) || null;
|
||||||
|
|
||||||
return UrlUtil.deserializeParameters(search);
|
if (!!key && !!value) {
|
||||||
|
pageParams[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.$get = function () {
|
||||||
|
return angular.copy(pageParams);
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.config(function ($searchParamsProvider, $windowProvider) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// Make sure we save the search parameters so they can be used later.
|
||||||
|
$searchParamsProvider.extractSearchParameters();
|
||||||
|
|
||||||
|
// Overwrite the URL's current state.
|
||||||
|
var window = $windowProvider.$get();
|
||||||
|
var url = new URL(window.location.toString());
|
||||||
|
url.search = '';
|
||||||
|
if (window.location.toString() !== url.toString()) {
|
||||||
|
window.history.replaceState({},
|
||||||
|
window.document.title,
|
||||||
|
url.toString());
|
||||||
}
|
}
|
||||||
return params;
|
|
||||||
});
|
});
|
||||||
|
@ -17,49 +17,53 @@
|
|||||||
/**
|
/**
|
||||||
* A service that keeps track of the last page we visited.
|
* A service that keeps track of the last page we visited.
|
||||||
*/
|
*/
|
||||||
angular.module('sb.util')
|
angular.module('sb.util').factory('LastLocation',
|
||||||
.factory('LastLocation',
|
function ($rootScope, localStorageService, $state) {
|
||||||
function ($rootScope, localStorageService, $location) {
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last detected length of the history
|
* onStateChange handler. Stores the next destination state, and its
|
||||||
|
* parameters, so we can keep revisit the history after bouncing out
|
||||||
|
* for authentication.
|
||||||
|
*
|
||||||
|
* @param event The state change event.
|
||||||
|
* @param toState The destination state.
|
||||||
|
* @param toParams The parameters for that destination state.
|
||||||
*/
|
*/
|
||||||
|
function onStateChange(event, toState, toParams) {
|
||||||
// When the location changes, store the new one. Since the $location
|
if (toState.name.indexOf('sb.auth') === -1) {
|
||||||
// object changes too quickly, we instead extract the hash manually.
|
var data = {
|
||||||
function onLocationChange() {
|
'name': toState.name,
|
||||||
var path = $location.path();
|
'params': toParams
|
||||||
if (!!path && path.indexOf('/auth') === -1) {
|
};
|
||||||
localStorageService.set('lastLocation', path);
|
localStorageService.set('lastLocation',
|
||||||
|
angular.toJson(data));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
// Add the listener to the application, remove it when the scope is
|
||||||
|
// destroyed.
|
||||||
|
$rootScope.$on('$destroy',
|
||||||
|
$rootScope.$on('$stateChangeStart', onStateChange)
|
||||||
|
);
|
||||||
|
|
||||||
// The published API.
|
// The published API.
|
||||||
return {
|
return {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the recorded history path at the provided index.
|
* Navigate to the last recorded state.
|
||||||
|
*
|
||||||
|
* @param defaultStateName A fallback state.
|
||||||
|
* @param defaultStateParams Default state parameters.
|
||||||
*/
|
*/
|
||||||
get: function () {
|
go: function (defaultStateName, defaultStateParams) {
|
||||||
return localStorageService.get('lastLocation');
|
var last = localStorageService.get('lastLocation');
|
||||||
},
|
if (!last) {
|
||||||
|
$state.go(defaultStateName, defaultStateParams);
|
||||||
/**
|
} else {
|
||||||
* Initialize this service.
|
last = angular.fromJson(last);
|
||||||
*/
|
$state.go(last.name, last.params);
|
||||||
initialize: function () {
|
}
|
||||||
// Register (and disconnect) our listener.
|
|
||||||
$rootScope.$on('$destroy',
|
|
||||||
$rootScope.$on('$locationChangeStart', onLocationChange)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})
|
|
||||||
.run(function (LastLocation) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// Initialize this service.
|
|
||||||
LastLocation.initialize();
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user