Repository: zeppelin Updated Branches: refs/heads/master 2a4d3699a -> 97dfb8986
[ZEPPELIN-2147] zeppelin should redirect to login page after browser session expires ### What is this PR for? Zeppelin should redirect to login page after browser session expires ### What type of PR is it? [Bug Fix] ### What is the Jira issue? * [https://issues.apache.org/jira/browse/ZEPPELIN-2147](https://issues.apache.org/jira/browse/ZEPPELIN-2147) ### How should this be tested? - Open any Zeppelin's notebook on a browser - Restart zeppelin server - now as soon as next web-socket message or API request is sent to server that returns either "ticket is invalid" or 405. This should get redirected to login page. - On successful login it should take user back to the page from where he was coming from. ### Screenshots (if appropriate)  ### Questions: * Does the licenses files need update? N/A * Is there breaking changes for older versions? N/A * Does this needs documentation? N/A Author: Prabhjyot Singh <prabhjyotsi...@gmail.com> Closes #2058 from prabhjyotsingh/ZEPPELIN-2147 and squashes the following commits: 27bc361 [Prabhjyot Singh] user $timeout with $location 9189089 [Prabhjyot Singh] in case of session lost or logout, show login window Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/97dfb898 Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/97dfb898 Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/97dfb898 Branch: refs/heads/master Commit: 97dfb898666ea186d9bb5fbe85dae4c1aa15bf25 Parents: 2a4d369 Author: Prabhjyot Singh <prabhjyotsi...@gmail.com> Authored: Fri Feb 24 13:01:10 2017 +0530 Committer: Prabhjyot Singh <prabhjyotsi...@gmail.com> Committed: Mon Feb 27 12:10:40 2017 +0530 ---------------------------------------------------------------------- .../apache/zeppelin/socket/NotebookServer.java | 4 +-- zeppelin-web/src/app/app.js | 20 ++++++++++++- .../src/components/login/login.controller.js | 30 ++++++++++++++++++-- .../websocketEvents/websocketEvents.factory.js | 2 ++ .../zeppelin/notebook/socket/Message.java | 1 + 5 files changed, 52 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zeppelin/blob/97dfb898/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java index 73e0d5b..d9cbca8 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java @@ -200,9 +200,9 @@ public class NotebookServer extends WebSocketServlet messagereceived.ticket, ticket); } else { if (!messagereceived.op.equals(OP.PING)) { - conn.send(serializeMessage(new Message(OP.ERROR_INFO).put("info", + conn.send(serializeMessage(new Message(OP.SESSION_LOGOUT).put("info", "Your ticket is invalid possibly due to server restart. " - + "Please refresh the page and login again."))); + + "Please login again."))); } } return; http://git-wip-us.apache.org/repos/asf/zeppelin/blob/97dfb898/zeppelin-web/src/app/app.js ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/app.js b/zeppelin-web/src/app/app.js index f68b3da..40b19c1 100644 --- a/zeppelin-web/src/app/app.js +++ b/zeppelin-web/src/app/app.js @@ -96,7 +96,7 @@ var zeppelinWebApp = angular.module('zeppelinWebApp', [ .when('/helium', { templateUrl: 'app/helium/helium.html', controller: 'HeliumCtrl' - }) + }) .when('/configuration', { templateUrl: 'app/configuration/configuration.html', controller: 'ConfigurationCtrl' @@ -116,6 +116,24 @@ var zeppelinWebApp = angular.module('zeppelinWebApp', [ timeout: 6000 }); }) + + //handel logout on API failure + .config(function ($httpProvider, $provide) { + $provide.factory('httpInterceptor', function ($q, $rootScope) { + return { + 'responseError': function (rejection) { + if (rejection.status === 405) { + var data = {}; + data.info = ''; + $rootScope.$broadcast('session_logout', data); + } + $rootScope.$broadcast('httpResponseError', rejection); + return $q.reject(rejection); + } + }; + }); + $httpProvider.interceptors.push('httpInterceptor'); + }) .constant('TRASH_FOLDER_ID', '~Trash'); function auth() { http://git-wip-us.apache.org/repos/asf/zeppelin/blob/97dfb898/zeppelin-web/src/components/login/login.controller.js ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/components/login/login.controller.js b/zeppelin-web/src/components/login/login.controller.js index 8b761a4..370466e 100644 --- a/zeppelin-web/src/components/login/login.controller.js +++ b/zeppelin-web/src/components/login/login.controller.js @@ -14,7 +14,7 @@ angular.module('zeppelinWebApp').controller('LoginCtrl', LoginCtrl); -function LoginCtrl($scope, $rootScope, $http, $httpParamSerializer, baseUrlSrv) { +function LoginCtrl($scope, $rootScope, $http, $httpParamSerializer, baseUrlSrv, $location, $timeout) { 'ngInject'; $scope.SigningIn = false; @@ -37,6 +37,17 @@ function LoginCtrl($scope, $rootScope, $http, $httpParamSerializer, baseUrlSrv) angular.element('#loginModal').modal('toggle'); $rootScope.$broadcast('loginSuccess', true); $rootScope.userName = $scope.loginParams.userName; + $scope.SigningIn = false; + + //redirect to the page from where the user originally was + if ($location.search() && $location.search()['ref']) { + $timeout(function() { + var redirectLocation = $location.search()['ref']; + $location.$$search = {}; + $location.path(redirectLocation); + }, 100); + + } }, function errorCallback(errorResponse) { $scope.loginParams.errorText = 'The username and password that you entered don\'t match.'; $scope.SigningIn = false; @@ -51,10 +62,25 @@ function LoginCtrl($scope, $rootScope, $http, $httpParamSerializer, baseUrlSrv) }; }; + //handle session logout message received from WebSocket + $rootScope.$on('session_logout', function(event, data) { + if ($rootScope.userName !== '') { + $rootScope.userName = ''; + $rootScope.ticket = undefined; + + setTimeout(function() { + $scope.loginParams = {}; + $scope.loginParams.errorText = data.info; + angular.element('.nav-login-btn').click(); + }, 1000); + var locationPath = $location.path(); + $location.path('/').search('ref', locationPath); + } + }); + /* ** $scope.$on functions below */ - $scope.$on('initLoginValues', function() { initValues(); }); http://git-wip-us.apache.org/repos/asf/zeppelin/blob/97dfb898/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js b/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js index 821884b..9c6e585 100644 --- a/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js +++ b/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js @@ -150,6 +150,8 @@ function websocketEvents($rootScope, $websocket, $location, baseUrlSrv) { } }] }); + } else if (op === 'SESSION_LOGOUT') { + $rootScope.$broadcast('session_logout', data); } else if (op === 'CONFIGURATIONS_INFO') { $rootScope.$broadcast('configurationsInfo', data); } else if (op === 'INTERPRETER_SETTINGS') { http://git-wip-us.apache.org/repos/asf/zeppelin/blob/97dfb898/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java index d40afc2..3784f5e 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java @@ -167,6 +167,7 @@ public class Message { GET_INTERPRETER_SETTINGS, // [c-s] get interpreter settings INTERPRETER_SETTINGS, // [s-c] interpreter settings ERROR_INFO, // [s-c] error information to be sent + SESSION_LOGOUT, // [s-c] error information to be sent WATCHER, // [s-c] Change websocket to watcher mode. PARAGRAPH_ADDED, // [s-c] paragraph is added PARAGRAPH_REMOVED, // [s-c] paragraph deleted