diff --git a/src/Umbraco.Web.UI.Client/src/common/services/appstate.service.js b/src/Umbraco.Web.UI.Client/src/common/services/appstate.service.js index d1d867977a..07e4242e98 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/appstate.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/appstate.service.js @@ -42,7 +42,8 @@ function appState(eventsService) { touchDevice: null, showTray: null, stickyNavigation: null, - navMode: null + navMode: null, + isReady: null }; var sectionState = { diff --git a/src/Umbraco.Web.UI.Client/src/init.js b/src/Umbraco.Web.UI.Client/src/init.js index bc71239135..57df26b532 100644 --- a/src/Umbraco.Web.UI.Client/src/init.js +++ b/src/Umbraco.Web.UI.Client/src/init.js @@ -11,31 +11,19 @@ app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', xhr.setRequestHeader("X-XSRF-TOKEN", $cookies["XSRF-TOKEN"]); } }); - - var firstRun = true; /** Listens for authentication and checks if our required assets are loaded, if/once they are we'll broadcast a ready event */ eventsService.on("app.authenticated", function(evt, data) { assetsService._loadInitAssets().then(function() { + appState.setGlobalState("isReady", true); //send the ready event eventsService.emit("app.ready", data); }); }); - /** when we have a successful first route that is not the login page - *meaning the user is authenticated* - we'll get the current user from the user service and ensure it broadcasts it's events. If the route - is successful from after a login then this will not actually do anything since the authenticated event would - have alraedy fired, but if the user is loading the angularjs app for the first time and they are already authenticated - then this is when the authenticated event will be fired. - */ + /** execute code on each successful route */ $rootScope.$on('$routeChangeSuccess', function(event, current, previous) { - - if (firstRun && !$location.url().toLowerCase().startsWith("/login")) { - userService.getCurrentUser({ broadcastEvent: true }).then(function (user) { - firstRun = false; - }); - } - + if(current.params.section){ $rootScope.locationTitle = current.params.section + " - " + $location.$$host; } diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 855bbad12c..e709600809 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -1,5 +1,5 @@ app.config(function ($routeProvider) { - + /** This checks if the user is authenticated for a route and what the isRequired is set to. Depending on whether isRequired = true, it first check if the user is authenticated and will resolve successfully otherwise the route will fail and the $routeChangeError event will execute, in that handler we will redirect to the rejected @@ -8,7 +8,7 @@ app.config(function ($routeProvider) { return { /** Checks that the user is authenticated, then ensures that are requires assets are loaded */ - isAuthenticatedAndReady: function ($q, userService, $route, assetsService) { + isAuthenticatedAndReady: function ($q, userService, $route, assetsService, appState) { var deferred = $q.defer(); //don't need to check if we've redirected to login and we've already checked auth @@ -21,14 +21,33 @@ app.config(function ($routeProvider) { .then(function () { assetsService._loadInitAssets().then(function() { - //is auth, check if we allow or reject - if (isRequired) { - //this will resolve successfully so the route will continue - deferred.resolve(true); + + //This could be the first time has loaded after the user has logged in, in this case + // we need to broadcast the authenticated event - this will be handled by the startup (init) + // handler to set/broadcast the ready state + if (appState.getGlobalState("isReady") !== true) { + userService.getCurrentUser({ broadcastEvent: true }).then(function(user) { + //is auth, check if we allow or reject + if (isRequired) { + //this will resolve successfully so the route will continue + deferred.resolve(true); + } + else { + deferred.reject({ path: "/" }); + } + }); } else { - deferred.reject({ path: "/" }); + //is auth, check if we allow or reject + if (isRequired) { + //this will resolve successfully so the route will continue + deferred.resolve(true); + } + else { + deferred.reject({ path: "/" }); + } } + }); }, function () { diff --git a/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs b/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs index f656ebd2cc..9ea42f8a39 100644 --- a/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/SetAngularAntiForgeryTokensAttribute.cs @@ -1,4 +1,5 @@ -using System.Net.Http; +using System.Linq; +using System.Net.Http; using System.Net.Http.Headers; using System.Web.Helpers; using System.Web.Http.Filters; @@ -15,6 +16,13 @@ namespace Umbraco.Web.WebApi.Filters { if (context.Response == null) return; + //don't need to set the cookie if they already exist + if (context.Request.Headers.GetCookies(AngularAntiForgeryHelper.AngularCookieName).Any() + && context.Request.Headers.GetCookies(AngularAntiForgeryHelper.CsrfValidationCookieName).Any()) + { + return; + } + string cookieToken, headerToken; AngularAntiForgeryHelper.GetTokens(out cookieToken, out headerToken);