mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +00:00 
			
		
		
		
	GUAC-919: Rename LoginRESTService to TokenRESTService and provide logout semantics. Move Angular auth stuff to own module. Actually logout user.
This commit is contained in:
		| @@ -26,7 +26,7 @@ import com.google.inject.Scopes; | ||||
| import com.google.inject.servlet.ServletModule; | ||||
| import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; | ||||
| import org.codehaus.jackson.jaxrs.JacksonJsonProvider; | ||||
| import org.glyptodon.guacamole.net.basic.rest.auth.LoginRESTService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.auth.TokenRESTService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.clipboard.ClipboardRESTService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionRESTService; | ||||
| import org.glyptodon.guacamole.net.basic.rest.connectiongroup.ConnectionGroupRESTService; | ||||
| @@ -51,7 +51,7 @@ public class RESTServletModule extends ServletModule { | ||||
|         bind(PermissionRESTService.class); | ||||
|         bind(ProtocolRESTService.class); | ||||
|         bind(UserRESTService.class); | ||||
|         bind(LoginRESTService.class); | ||||
|         bind(TokenRESTService.class); | ||||
|          | ||||
|         // Set up the servlet and JSON mappings | ||||
|         bind(GuiceContainer.class); | ||||
|   | ||||
| @@ -131,6 +131,7 @@ public class BasicTokenSessionMap implements TokenSessionMap { | ||||
|                 if (age >= sessionTimeout) { | ||||
|                     logger.debug("Session \"{}\" has timed out.", entry.getKey()); | ||||
|                     entries.remove(); | ||||
|                     session.invalidate(); | ||||
|                 } | ||||
|  | ||||
|                 // Otherwise, no other sessions can possibly be old enough | ||||
| @@ -162,9 +163,14 @@ public class BasicTokenSessionMap implements TokenSessionMap { | ||||
|         sessionMap.put(authToken, session); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public GuacamoleSession remove(String authToken) { | ||||
|         return sessionMap.remove(authToken); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void shutdown() { | ||||
|         executor.shutdownNow(); | ||||
|     } | ||||
|      | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -24,9 +24,11 @@ package org.glyptodon.guacamole.net.basic.rest.auth; | ||||
| 
 | ||||
| import com.google.inject.Inject; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.ws.rs.DELETE; | ||||
| import javax.ws.rs.FormParam; | ||||
| import javax.ws.rs.POST; | ||||
| import javax.ws.rs.Path; | ||||
| import javax.ws.rs.PathParam; | ||||
| import javax.ws.rs.Produces; | ||||
| import javax.ws.rs.core.Context; | ||||
| import javax.ws.rs.core.MediaType; | ||||
| @@ -42,16 +44,13 @@ import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| 
 | ||||
| /** | ||||
|  * A service for authenticating to the Guacamole REST API. Given valid | ||||
|  * credentials, the service will return an auth token. Invalid credentials will | ||||
|  * result in a permission error. | ||||
|  * A service for managing auth tokens via the Guacamole REST API. | ||||
|  *  | ||||
|  * @author James Muehlner | ||||
|  */ | ||||
| 
 | ||||
| @Path("/login") | ||||
| @Path("/token") | ||||
| @Produces(MediaType.APPLICATION_JSON) | ||||
| public class LoginRESTService { | ||||
| public class TokenRESTService { | ||||
|      | ||||
|     /** | ||||
|      * The authentication provider used to authenticate this user. | ||||
| @@ -74,7 +73,7 @@ public class LoginRESTService { | ||||
|     /** | ||||
|      * Logger for this class. | ||||
|      */ | ||||
|     private static final Logger logger = LoggerFactory.getLogger(LoginRESTService.class); | ||||
|     private static final Logger logger = LoggerFactory.getLogger(TokenRESTService.class); | ||||
|      | ||||
|     /** | ||||
|      * Authenticates a user, generates an auth token, associates that auth token | ||||
| @@ -88,7 +87,7 @@ public class LoginRESTService { | ||||
|      */ | ||||
|     @POST | ||||
|     @AuthProviderRESTExposure | ||||
|     public APIAuthToken login(@FormParam("username") String username, | ||||
|     public APIAuthToken createToken(@FormParam("username") String username, | ||||
|             @FormParam("password") String password,  | ||||
|             @Context HttpServletRequest request) throws GuacamoleException { | ||||
|          | ||||
| @@ -120,5 +119,24 @@ public class LoginRESTService { | ||||
|         return new APIAuthToken(authToken, username); | ||||
| 
 | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     /** | ||||
|      * Invalidates a specific auth token, effectively logging out the associated | ||||
|      * user. | ||||
|      *  | ||||
|      * @param authToken The token being invalidated. | ||||
|      */ | ||||
|     @DELETE | ||||
|     @Path("/{token}") | ||||
|     @AuthProviderRESTExposure | ||||
|     public void invalidateToken(@PathParam("token") String authToken) { | ||||
|          | ||||
|         GuacamoleSession session = tokenSessionMap.remove(authToken); | ||||
|         if (session == null) | ||||
|             throw new HTTPException(Status.NOT_FOUND, "No such token."); | ||||
| 
 | ||||
|         session.invalidate(); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @@ -51,6 +51,15 @@ public interface TokenSessionMap { | ||||
|      */ | ||||
|     public GuacamoleSession get(String authToken); | ||||
|  | ||||
|     /** | ||||
|      * Removes the GuacamoleSession associated with the given auth token. | ||||
|      * | ||||
|      * @param authToken The token to remove. | ||||
|      * @return The GuacamoleSession for the given auth token, if the auth token | ||||
|      *         represents a currently logged in user, null otherwise. | ||||
|      */ | ||||
|     public GuacamoleSession remove(String authToken); | ||||
|      | ||||
|     /** | ||||
|      * Shuts down this session map, disallowing future sessions and reclaiming | ||||
|      * any resources. | ||||
|   | ||||
| @@ -21,33 +21,6 @@ | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * A service for authenticating a user against the REST API. | ||||
|  * The module for authentication and management of tokens. | ||||
|  */ | ||||
| angular.module('index').factory('authenticationService', ['$http',  | ||||
|         function authenticationService($http) { | ||||
|     var service = {}; | ||||
|      | ||||
|     /** | ||||
|      * Makes a request to authenticate a user using the login REST API endpoint,  | ||||
|      * returning a promise that can be used for processing the results of the call. | ||||
|      *  | ||||
|      * @param {string} username The username to log in with. | ||||
|      * @param {string} password The password to log in with. | ||||
|      * @returns {promise} A promise for the HTTP call. | ||||
|      */ | ||||
|     service.login = function login(username, password) { | ||||
|         return $http({ | ||||
|             method: 'POST', | ||||
|             url: 'api/login', | ||||
|             headers: { | ||||
|                 'Content-Type': 'application/x-www-form-urlencoded' | ||||
|             }, | ||||
|             data: $.param({ | ||||
|                 username: username, | ||||
|                 password: password | ||||
|             }) | ||||
|         }); | ||||
|     }; | ||||
|      | ||||
|     return service; | ||||
| }]); | ||||
| angular.module('auth', ['util']); | ||||
| @@ -0,0 +1,90 @@ | ||||
| /* | ||||
|  * Copyright (C) 2014 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * A service for authenticating a user against the REST API. | ||||
|  */ | ||||
| angular.module('auth').factory('authenticationService', ['$http', '$injector', | ||||
|         function authenticationService($http, $injector) { | ||||
|  | ||||
|     var localStorageUtility = $injector.get("localStorageUtility"); | ||||
|     var service = {}; | ||||
|      | ||||
|     /** | ||||
|      * Makes a request to authenticate a user using the token REST API endpoint,  | ||||
|      * returning a promise that can be used for processing the results of the call. | ||||
|      *  | ||||
|      * @param {String} username The username to log in with. | ||||
|      * @param {String} password The password to log in with. | ||||
|      * @returns {Promise} A promise for the HTTP call. | ||||
|      */ | ||||
|     service.login = function login(username, password) { | ||||
|         return $http({ | ||||
|             method: 'POST', | ||||
|             url: 'api/token', | ||||
|             headers: { | ||||
|                 'Content-Type': 'application/x-www-form-urlencoded' | ||||
|             }, | ||||
|             data: $.param({ | ||||
|                 username: username, | ||||
|                 password: password | ||||
|             }) | ||||
|         }).success(function success(data, status, headers, config) { | ||||
|             localStorageUtility.set('authToken', data.authToken); | ||||
|             localStorageUtility.set('userID', data.userID); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Makes a request to logout a user using the login REST API endpoint,  | ||||
|      * returning a promise that can be used for processing the results of the call. | ||||
|      *  | ||||
|      * @returns {Promise} A promise for the HTTP call. | ||||
|      */ | ||||
|     service.logout = function logout() { | ||||
|         return $http({ | ||||
|             method: 'DELETE', | ||||
|             url: 'api/token/' + encodeURIComponent(service.getCurrentToken()) | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Returns the user ID of the current user. | ||||
|      * | ||||
|      * @returns {String} The user ID of the current user. | ||||
|      */ | ||||
|     service.getCurrentUserID = function getCurrentUserID() { | ||||
|         return localStorageUtility.get('userID'); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Returns the auth token associated with the current user. If the current | ||||
|      * user is not logged in, this token may not be valid. | ||||
|      * | ||||
|      * @returns {String} The auth token associated with the current user. | ||||
|      */ | ||||
|     service.getCurrentToken = function getCurrentToken() { | ||||
|         return localStorageUtility.get('authToken'); | ||||
|     }; | ||||
|      | ||||
|     return service; | ||||
| }]); | ||||
| @@ -49,7 +49,7 @@ | ||||
|  | ||||
|     <div class="logout-panel"> | ||||
|         <a class="manage button" ng-show="currentUserHasUpdate" href="#/manage">{{'home.manage' | translate}}</a> | ||||
|         <a class="logout button" href="#/login">{{'home.logout' | translate}}</a> | ||||
|         <a class="logout button" ng-click="logout()">{{'home.logout' | translate}}</a> | ||||
|     </div> | ||||
|  | ||||
|     <!-- The recent connections for this user --> | ||||
|   | ||||
| @@ -29,7 +29,7 @@ angular.module('index').controller('indexController', ['$scope', '$injector', | ||||
|     // Get the dependencies commonJS style | ||||
|     var permissionDAO           = $injector.get("permissionDAO"), | ||||
|         permissionCheckService  = $injector.get("permissionCheckService"), | ||||
|         localStorageUtility     = $injector.get("localStorageUtility"), | ||||
|         authenticationService   = $injector.get("authenticationService"), | ||||
|         $q                      = $injector.get("$q"), | ||||
|         $document               = $injector.get("$document"), | ||||
|         $window                 = $injector.get("$window"), | ||||
| @@ -64,7 +64,7 @@ angular.module('index').controller('indexController', ['$scope', '$injector', | ||||
|     var permissionsLoaded= $q.defer(); | ||||
|     $scope.basicPermissionsLoaded = permissionsLoaded.promise; | ||||
|      | ||||
|     $scope.currentUserID = localStorageUtility.get('userID'); | ||||
|     $scope.currentUserID = authenticationService.getCurrentUserID(); | ||||
|      | ||||
|     // If the user is unknown, force a login | ||||
|     if(!$scope.currentUserID) | ||||
| @@ -86,6 +86,13 @@ angular.module('index').controller('indexController', ['$scope', '$injector', | ||||
|             permissionsLoaded.resolve(); | ||||
|         }); | ||||
|     }; | ||||
|  | ||||
|     // Provide simple mechanism for logging out the current user | ||||
|     $scope.logout = function logout() { | ||||
|         authenticationService.logout().success(function logoutSuccess() { | ||||
|             $location.path('/login'); | ||||
|         }); | ||||
|     }; | ||||
|      | ||||
|     // Try to load them now | ||||
|     $scope.loadBasicPermissions(); | ||||
|   | ||||
| @@ -23,4 +23,4 @@ | ||||
| /** | ||||
|  * The module for the root of the application. | ||||
|  */ | ||||
| angular.module('index', ['ngRoute', 'pascalprecht.translate', 'home', 'manage', 'login', 'client']); | ||||
| angular.module('index', ['ngRoute', 'pascalprecht.translate', 'auth', 'home', 'manage', 'login', 'client']); | ||||
|   | ||||
| @@ -24,22 +24,14 @@ angular.module('login').controller('loginController', ['$scope', '$injector', | ||||
|         function loginController($scope, $injector) { | ||||
|              | ||||
|     // Get the dependencies commonJS style | ||||
|     var authenticationService   = $injector.get("authenticationService"); | ||||
|     var localStorageUtility     = $injector.get("localStorageUtility"); | ||||
|     var $location               = $injector.get("$location"); | ||||
|     var authenticationService = $injector.get("authenticationService"); | ||||
|     var $location             = $injector.get("$location"); | ||||
|              | ||||
|     // Clear the auth token and userID to log out the user | ||||
|     localStorageUtility.clear("authToken"); | ||||
|     localStorageUtility.clear("userID"); | ||||
|          | ||||
|     $scope.loginError = false; | ||||
|      | ||||
|     $scope.login = function login() { | ||||
|         authenticationService.login($scope.username, $scope.password) | ||||
|             .success(function success(data, status, headers, config) { | ||||
|                 localStorageUtility.set('authToken', data.authToken); | ||||
|                 localStorageUtility.set('userID', data.userID); | ||||
|                  | ||||
|                 // Set up the basic permissions for the user | ||||
|                 $scope.loadBasicPermissions(); | ||||
|                 $location.path('/'); | ||||
| @@ -47,4 +39,5 @@ angular.module('login').controller('loginController', ['$scope', '$injector', | ||||
|                 $scope.loginError = true; | ||||
|             }); | ||||
|     }; | ||||
|  | ||||
| }]); | ||||
|   | ||||
| @@ -44,7 +44,7 @@ THE SOFTWARE. | ||||
|  | ||||
| <div class="logout-panel"> | ||||
|     <a class="back button" href="#/">{{'manage.back' | translate}}</a> | ||||
|     <a class="logout button" href="#/login">{{'home.logout' | translate}}</a> | ||||
|     <a class="logout button" ng-click="logout()">{{'home.logout' | translate}}</a> | ||||
| </div> | ||||
|  | ||||
| <h2>{{'manage.administration' | translate}}</h2> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user