diff --git a/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js index fe77a4b26f..320296b5b3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/interceptor.js @@ -1,12 +1,19 @@ angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']) // This http interceptor listens for authentication failures -.factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', function ($injector, queue, notifications) { +.factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', '$rootScope', '$log', function ($injector, queue, notifications, $rootScope, $log) { return function (promise) { // Intercept failed requests return promise.then(null, function (originalResponse) { + //A 401 means that the user is not logged in if (originalResponse.status === 401) { + + $log.log("Broadcasting notAuthenticated event"); + + //emit a global event that the user is no longer logged in + $rootScope.$broadcast("notAuthenticated"); + // The request bounced because it was not authorized - add a new request to the retry queue promise = queue.pushRetryFn('unauthorized-server', function retryRequest() { // We must use $injector to get the $http service to prevent circular dependency diff --git a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js index 54a5ae1999..9ea869a913 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js @@ -36,6 +36,10 @@ angular.module('umbraco.services') // Register a handler for when an item is added to the retry queue securityRetryQueue.onItemAddedCallbacks.push(function (retryItem) { if (securityRetryQueue.hasMore()) { + + //clear the user + currentUser = null; + openLoginDialog(); } }); @@ -49,7 +53,7 @@ angular.module('umbraco.services') .then(function(data) { //note, this can return null if they are not authenticated - if (!data) { + if (!data) { throw "Not authenticated"; } else { @@ -65,16 +69,28 @@ angular.module('umbraco.services') return authResource.performLogin(login, password) .then(function (data) { + //when it's successful, return the user data currentUser = data; - return { user: data, authenticated: true }; + + var result = { user: data, authenticated: true }; + + //broadcast a global event + $rootScope.$broadcast("authenticated", result); + + return result; }); }, logout: function () { return authResource.performLogout() .then(function (data) { + currentUser = null; + + //broadcast a global event + $rootScope.$broadcast("notAuthenticated"); + openLoginDialog(); return null; }); diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 603948984b..6b482eba9b 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -53,8 +53,16 @@ app.config(function ($routeProvider) { }); -app.run(['userService', function (userService) { +app.run(['userService', '$log', '$rootScope', function (userService, $log, $rootScope) { + // Get the current user when the application starts // (in case they are still logged in from a previous session) - userService.isAuthenticated(); + + userService.isAuthenticated() + .then(function (data) { + + //broadcast a global event, will inform listening controllers to load in the user specific data + $rootScope.$broadcast("authenticated", data); + + }); }]); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js index e42a2aa479..a4dd1f7507 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js @@ -15,7 +15,8 @@ $scope.today = weekday[d.getDay()]; $scope.errorMsg = ""; - $scope.loginSubmit = function (login, password) { + $scope.loginSubmit = function (login, password) { + //if the login and password are not empty we need to automatically // validate them - this is because if there are validation errors on the server // then the user has to change both username & password to resubmit which isn't ideal, @@ -32,20 +33,19 @@ userService.authenticate(login, password) .then(function (data) { - //We need to load in the legacy tree js. - legacyJsLoader.loadLegacyTreeJs($scope).then( - function(result) { - var iframe = $("#right"); - if(iframe){ - var url = decodeURIComponent($routeParams.url); - if(!url){ - url ="dashboard.aspx"; - } - iframe.attr("src", url); - } + + var iframe = $("#right"); + if (iframe) { + var url = decodeURIComponent($routeParams.url); + if (!url) { + url = "dashboard.aspx"; + } + iframe.attr("src", url); + } - $scope.submit(true); - }); + $scope.submit(true); + + }, function (reason) { $scope.errorMsg = reason.errorMsg; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js index a0b244c8f2..e683c831d1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js @@ -12,7 +12,7 @@ angular.module("umbraco") $scope.gotoHistory = function (link) { $location.path(link); - $scope.$apply() + $scope.$apply(); $scope.hide(); }; }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js index 476c9663c0..f1fa3e0549 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/main.controller.js @@ -10,6 +10,7 @@ */ function MainController($scope, $routeParams, $rootScope, $timeout, $http, $log, notificationsService, userService, navigationService, legacyJsLoader) { + var legacyTreeJsLoaded = false; //detect if the current device is touch-enabled $scope.touchDevice = ("ontouchstart" in window || window.touch || window.navigator.msMaxTouchPoints===5 || window.DocumentTouch && document instanceof DocumentTouch); @@ -53,53 +54,77 @@ function MainController($scope, $routeParams, $rootScope, $timeout, $http, $log, $rootScope.$emit("closeDialogs", event); }; - //fetch the authorized status - userService.isAuthenticated() - .then(function (data) { - - //We need to load in the legacy tree js. + //when a user logs out or timesout + $scope.$on("notAuthenticated", function() { + + //this means that the user has logged out + $log.log("MainController handling notAuthenticated"); + + $scope.authenticated = null; + $scope.user = null; + + }); + + //when a user is authorized setup the data + $scope.$on("authenticated", function (evt, data) { + + //this means that the user has logged in + $log.log("MainController handling authenticated"); + + //We need to load in the legacy tree js but only once no matter what user has logged in + if (!legacyTreeJsLoaded) { legacyJsLoader.loadLegacyTreeJs($scope).then( function (result) { + legacyTreeJsLoaded = true; + //TODO: We could wait for this to load before running the UI ? }); + } + + $scope.authenticated = data.authenticated; + $scope.user = data.user; + + }); + + ////fetch the authorized status + //userService.isAuthenticated() + // .then(function (data) { - $scope.authenticated = data.authenticated; - $scope.user = data.user; + // ////We need to load in the legacy tree js but only once no matter what user has logged in + // //if (!legacyTreeJsLoaded) { + // // legacyJsLoader.loadLegacyTreeJs($scope).then( + // // function (result) { + // // legacyTreeJsLoaded = true; + + // // //TODO: We could wait for this to load before running the UI ? + // // }); + // //} + + // //$scope.authenticated = data.authenticated; + // //$scope.user = data.user; + + // //var url = "http://www.gravatar.com/avatar/" + $scope.user.emailHash + ".json?404=404"; + // //$http.jsonp(url).then(function(response){ + // // $log.log("found: " + response); + // //}, function(data){ + // // $log.log(data); + // //}); - -/* - var url = "http://www.gravatar.com/avatar/" + $scope.user.emailHash + ".json?404=404"; - $http.jsonp(url).then(function(response){ - $log.log("found: " + response); - }, function(data){ - $log.log(data); - }); -*/ - - /* - if($scope.user.avatar){ - $http.get($scope.user.avatar).then(function(){ - //alert($scope.user.avatar); - $scope.avatar = $scope.user.avatar; - }); - }*/ + // //if($scope.user.avatar){ + // // $http.get($scope.user.avatar).then(function(){ + // // //alert($scope.user.avatar); + // // $scope.avatar = $scope.user.avatar; + // // }); + // //} - }, function (reason) { - notificationsService.error("An error occurred checking authentication."); - $scope.authenticated = false; - $scope.user = null; - }); + // }, function (reason) { + // notificationsService.error("An error occurred checking authentication."); + // $scope.authenticated = false; + // $scope.user = null; + // }); } //register it -angular.module('umbraco').controller("Umbraco.MainController", MainController); - -/* -angular.module("umbraco").run(function(eventsService){ - eventsService.subscribe("Umbraco.Dialogs.ContentPickerController.Select", function(a, b){ - a.node.name = "wat"; - }); -}); -*/ \ No newline at end of file +angular.module('umbraco').controller("Umbraco.MainController", MainController); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js index bc88a561bb..dbe7cea8e9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/navigation.controller.js @@ -30,11 +30,19 @@ function NavigationController($scope,$rootScope, $location, $log, $routeParams, $scope.selectedId = navigationService.currentId; $scope.sections = navigationService.sections; + + $scope.$on("notAuthenticated", function() { + $log.log("NavigationController handling notAuthenticated"); + }); - sectionResource.getSections() - .then(function(result) { - $scope.sections = result; - }); + $scope.$on("authenticated", function (evt, data) { + $log.log("NavigationController handling authenticated"); + + sectionResource.getSections() + .then(function(result) { + $scope.sections = result; + }); + }); //This reacts to clicks passed to the body element which emits a global call to close all dialogs $rootScope.$on("closeDialogs", function (event) {