Ticket #269: Major cleanup of permissions service.

This commit is contained in:
Michael Jumper
2013-03-01 03:39:49 -08:00
parent a42167ecc3
commit dbafe68cd4
5 changed files with 459 additions and 922 deletions

View File

@@ -38,7 +38,7 @@ package net.sourceforge.guacamole.net.auth.mysql;
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.HashSet; import java.util.List;
import java.util.Set; import java.util.Set;
import net.sourceforge.guacamole.GuacamoleException; import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.auth.Connection; import net.sourceforge.guacamole.net.auth.Connection;
@@ -102,19 +102,34 @@ public class ConnectionDirectory implements Directory<String, Connection>{
@Transactional @Transactional
@Override @Override
public Connection get(String identifier) throws GuacamoleException { public Connection get(String identifier) throws GuacamoleException {
permissionCheckService.verifyConnectionReadAccess(this.user_id, identifier);
return connectionService.retrieveConnection(identifier); // Get connection
MySQLConnection connection =
connectionService.retrieveConnection(identifier);
// Verify access is granted
permissionCheckService.verifyConnectionAccess(
this.user_id,
connection.getConnectionID(),
MySQLConstants.CONNECTION_READ);
// Return connection
return connection;
} }
@Transactional @Transactional
@Override @Override
public Set<String> getIdentifiers() throws GuacamoleException { public Set<String> getIdentifiers() throws GuacamoleException {
Set<String> connectionNameSet = new HashSet<String>();
Set<MySQLConnection> connections = permissionCheckService.getReadableConnections(this.user_id); // List of all connection IDs for which this user has read access
for(MySQLConnection mySQLConnection : connections) { List<Integer> connectionIDs =
connectionNameSet.add(mySQLConnection.getIdentifier()); permissionCheckService.retrieveConnectionIDs(this.user_id,
} MySQLConstants.CONNECTION_READ);
return connectionNameSet;
// Query all associated connections
return connectionService.translateNames(connectionIDs).keySet();
} }
@Transactional @Transactional
@@ -122,7 +137,8 @@ public class ConnectionDirectory implements Directory<String, Connection>{
public void add(Connection object) throws GuacamoleException { public void add(Connection object) throws GuacamoleException {
// Verify permission to create // Verify permission to create
permissionCheckService.verifyCreateConnectionPermission(this.user_id); permissionCheckService.verifySystemAccess(this.user_id,
MySQLConstants.SYSTEM_CONNECTION_CREATE);
// Create connection // Create connection
MySQLConnection connection = connectionService.createConnection( MySQLConnection connection = connectionService.createConnection(
@@ -192,10 +208,14 @@ public class ConnectionDirectory implements Directory<String, Connection>{
if (!(object instanceof MySQLConnection)) if (!(object instanceof MySQLConnection))
throw new GuacamoleException("Connection not from database."); throw new GuacamoleException("Connection not from database.");
// Verify permission to update
permissionCheckService.verifyConnectionUpdateAccess(this.user_id, object.getIdentifier());
MySQLConnection mySQLConnection = (MySQLConnection) object; MySQLConnection mySQLConnection = (MySQLConnection) object;
// Verify permission to update
permissionCheckService.verifyConnectionAccess(this.user_id,
mySQLConnection.getConnectionID(),
MySQLConstants.CONNECTION_UPDATE);
// Perform update
connectionService.updateConnection(mySQLConnection); connectionService.updateConnection(mySQLConnection);
// Delete old connection parameters // Delete old connection parameters
@@ -213,13 +233,15 @@ public class ConnectionDirectory implements Directory<String, Connection>{
@Override @Override
public void remove(String identifier) throws GuacamoleException { public void remove(String identifier) throws GuacamoleException {
// Verify permission to delete
permissionCheckService.verifyConnectionDeleteAccess(this.user_id, identifier);
// Get connection // Get connection
MySQLConnection mySQLConnection = MySQLConnection mySQLConnection =
connectionService.retrieveConnection(identifier); connectionService.retrieveConnection(identifier);
// Verify permission to delete
permissionCheckService.verifyConnectionAccess(this.user_id,
mySQLConnection.getConnectionID(),
MySQLConstants.CONNECTION_DELETE);
// Delete the connection itself // Delete the connection itself
connectionService.deleteConnection(mySQLConnection.getConnectionID()); connectionService.deleteConnection(mySQLConnection.getConnectionID());

View File

@@ -41,8 +41,6 @@ import com.google.common.base.Preconditions;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -143,23 +141,32 @@ public class UserDirectory implements Directory<String, net.sourceforge.guacamol
@Override @Override
public net.sourceforge.guacamole.net.auth.User get(String identifier) public net.sourceforge.guacamole.net.auth.User get(String identifier)
throws GuacamoleException { throws GuacamoleException {
permissionCheckService.verifyUserReadAccess(this.user_id, identifier);
// Get user
MySQLUser user = userService.retrieveUser(identifier);
// Verify access is granted
permissionCheckService.verifyUserAccess(this.user_id,
user.getUserID(),
MySQLConstants.USER_READ);
// Return user
return userService.retrieveUser(identifier); return userService.retrieveUser(identifier);
} }
@Transactional @Transactional
@Override @Override
public Set<String> getIdentifiers() throws GuacamoleException { public Set<String> getIdentifiers() throws GuacamoleException {
// Get set of all readable users // List of all user IDs for which this user has read access
Set<MySQLUser> users = permissionCheckService.getReadableUsers(this.user_id); List<Integer> userIDs =
permissionCheckService.retrieveConnectionIDs(this.user_id,
MySQLConstants.USER_READ);
// Build set of usernames of readable users // Query all associated users
Set<String> userNameSet = new HashSet<String>(); return userService.translateUsernames(userIDs).keySet();
for (MySQLUser mySQLUser : users)
userNameSet.add(mySQLUser.getUsername());
return userNameSet;
} }
@Override @Override
@@ -168,7 +175,8 @@ public class UserDirectory implements Directory<String, net.sourceforge.guacamol
throws GuacamoleException { throws GuacamoleException {
// Verify current user has permission to create users // Verify current user has permission to create users
permissionCheckService.verifyCreateUserPermission(this.user_id); permissionCheckService.verifySystemAccess(this.user_id,
MySQLConstants.SYSTEM_USER_CREATE);
Preconditions.checkNotNull(object); Preconditions.checkNotNull(object);
// Create new user // Create new user
@@ -285,51 +293,43 @@ public class UserDirectory implements Directory<String, net.sourceforge.guacamol
Collection<UserPermission> permissions) Collection<UserPermission> permissions)
throws GuacamoleException { throws GuacamoleException {
// If no permissions given, stop now
if(permissions.isEmpty()) if(permissions.isEmpty())
return; return;
// Get set of administerable users // Get list of administerable user IDs
Set<Integer> administerableUsers = List<Integer> administerableUserIDs =
permissionCheckService.getAdministerableUserIDs(this.user_id); permissionCheckService.retrieveUserIDs(this.user_id,
MySQLConstants.USER_ADMINISTER);
// Get list of usernames for all given user permissions. // Get set of usernames corresponding to administerable users
List<String> usernames = new ArrayList<String>(); Map<String, Integer> administerableUsers =
for (UserPermission permission : permissions) userService.translateUsernames(administerableUserIDs);
usernames.add(permission.getObjectIdentifier());
// Find all the users by username
List<MySQLUser> users = userService.retrieveUsersByUsername(usernames);
// Build map of found users, indexed by username
Map<String, MySQLUser> userMap = new HashMap<String, MySQLUser>();
for (MySQLUser user : users)
userMap.put(user.getUsername(), user);
// Insert all given permissions
for (UserPermission permission : permissions) { for (UserPermission permission : permissions) {
// Get user // Get original ID
MySQLUser affectedUser = Integer affected_id =
userMap.get(permission.getObjectIdentifier()); administerableUsers.get(permission.getObjectIdentifier());
if (affectedUser == null)
throw new GuacamoleException(
"User '" + permission.getObjectIdentifier()
+ "' not found.");
// Verify that the user actually has permission to administrate // Verify that the user actually has permission to administrate
// every one of these users // every one of these users
if (!administerableUsers.contains(affectedUser.getUserID())) if (affected_id == null)
throw new GuacamoleSecurityException( throw new GuacamoleSecurityException(
"User #" + this.user_id "User #" + this.user_id
+ " does not have permission to administrate user " + " does not have permission to administrate user "
+ affectedUser.getUsername()); + permission.getObjectIdentifier());
// Create new permission // Create new permission
UserPermissionKey newPermission = new UserPermissionKey(); UserPermissionKey newPermission = new UserPermissionKey();
newPermission.setAffected_user_id(affectedUser.getUserID());
newPermission.setPermission(permission.getType().name());
newPermission.setUser_id(user_id); newPermission.setUser_id(user_id);
newPermission.setPermission(MySQLConstants.getUserConstant(permission.getType()));
newPermission.setAffected_user_id(affected_id);
userPermissionDAO.insert(newPermission); userPermissionDAO.insert(newPermission);
} }
} }
/** /**
@@ -345,54 +345,44 @@ public class UserDirectory implements Directory<String, net.sourceforge.guacamol
Collection<UserPermission> permissions) Collection<UserPermission> permissions)
throws GuacamoleException { throws GuacamoleException {
// If no permissions given, stop now
if(permissions.isEmpty()) if(permissions.isEmpty())
return; return;
// Get set of administerable users // Get list of administerable user IDs
Set<Integer> administerableUsers = List<Integer> administerableUserIDs =
permissionCheckService.getAdministerableUserIDs(this.user_id); permissionCheckService.retrieveUserIDs(this.user_id,
MySQLConstants.USER_ADMINISTER);
// Get list of usernames for all given user permissions. // Get set of usernames corresponding to administerable users
List<String> usernames = new ArrayList<String>(); Map<String, Integer> administerableUsers =
for (UserPermission permission : permissions) userService.translateUsernames(administerableUserIDs);
usernames.add(permission.getObjectIdentifier());
// Find all the users by username // Delete requested permissions
List<MySQLUser> users = userService.retrieveUsersByUsername(usernames);
List<Integer> userIDs = new ArrayList<Integer>();
// Build map of found users, indexed by username
Map<String, MySQLUser> userMap = new HashMap<String, MySQLUser>();
for (MySQLUser user : users) {
userMap.put(user.getUsername(), user);
userIDs.add(user.getUserID());
}
// Verify we have permission to delete each user permission.
for (UserPermission permission : permissions) { for (UserPermission permission : permissions) {
// Get user // Get original ID
MySQLUser affectedUser = userMap.get(permission.getObjectIdentifier()); Integer affected_id =
if (affectedUser == null) administerableUsers.get(permission.getObjectIdentifier());
throw new GuacamoleException(
"User '" + permission.getObjectIdentifier()
+ "' not found.");
// Verify that the user actually has permission to administrate // Verify that the user actually has permission to administrate
// every one of these users // every one of these users
if (!administerableUsers.contains(affectedUser.getUserID())) if (affected_id == null)
throw new GuacamoleSecurityException( throw new GuacamoleSecurityException(
"User #" + this.user_id "User #" + this.user_id
+ " does not have permission to administrate user " + " does not have permission to administrate user "
+ affectedUser.getUsername()); + permission.getObjectIdentifier());
// Delete requested permission
UserPermissionExample userPermissionExample = new UserPermissionExample();
userPermissionExample.createCriteria()
.andUser_idEqualTo(user_id)
.andPermissionEqualTo(MySQLConstants.getUserConstant(permission.getType()))
.andAffected_user_idEqualTo(affected_id);
userPermissionDAO.deleteByExample(userPermissionExample);
} }
if(!userIDs.isEmpty()) {
UserPermissionExample userPermissionExample = new UserPermissionExample();
userPermissionExample.createCriteria().andUser_idEqualTo(user_id)
.andAffected_user_idIn(userIDs);
userPermissionDAO.deleteByExample(userPermissionExample);
}
} }
/** /**
@@ -409,51 +399,42 @@ public class UserDirectory implements Directory<String, net.sourceforge.guacamol
Collection<ConnectionPermission> permissions) Collection<ConnectionPermission> permissions)
throws GuacamoleException { throws GuacamoleException {
// If no permissions given, stop now
if(permissions.isEmpty()) if(permissions.isEmpty())
return; return;
// Get adminsterable connection identifiers // Get list of administerable connection IDs
Set<Integer> administerableConnections = List<Integer> administerableConnectionIDs =
permissionCheckService.getAdministerableConnectionIDs(this.user_id); permissionCheckService.retrieveUserIDs(this.user_id,
MySQLConstants.CONNECTION_ADMINISTER);
// Build list of affected connection names from the permissions given // Get set of names corresponding to administerable connections
List<String> connectionNames = new ArrayList<String>(); Map<String, Integer> administerableConnections =
for (ConnectionPermission permission : permissions) userService.translateUsernames(administerableConnectionIDs);
connectionNames.add(permission.getObjectIdentifier());
// Find all the connections by connection name // Insert all given permissions
List<MySQLConnection> connections = connectionService.retrieveConnectionsByName(connectionNames);
// Build map of found connections, indexed by name
Map<String, MySQLConnection> connectionMap = new HashMap<String, MySQLConnection>();
for (MySQLConnection connection : connections)
connectionMap.put(connection.getIdentifier(), connection);
// Finally, insert the new permissions
for (ConnectionPermission permission : permissions) { for (ConnectionPermission permission : permissions) {
// Get permission // Get original ID
MySQLConnection connection = connectionMap.get(permission.getObjectIdentifier()); Integer connection_id =
if (connection == null) administerableConnections.get(permission.getObjectIdentifier());
throw new GuacamoleException(
"Connection '" + permission.getObjectIdentifier()
+ "' not found.");
// Throw exception if permission to administer this connection // Throw exception if permission to administer this connection
// is not granted // is not granted
if (!administerableConnections.contains(connection.getConnectionID())) if (connection_id == null)
throw new GuacamoleSecurityException( throw new GuacamoleSecurityException(
"User #" + this.user_id "User #" + this.user_id
+ " does not have permission to administrate connection " + " does not have permission to administrate connection "
+ connection.getIdentifier()); + permission.getObjectIdentifier());
// Insert previously-non-existent connection permission // Create new permission
ConnectionPermissionKey newPermission = new ConnectionPermissionKey(); ConnectionPermissionKey newPermission = new ConnectionPermissionKey();
newPermission.setConnection_id(connection.getConnectionID());
newPermission.setPermission(permission.getType().name());
newPermission.setUser_id(user_id); newPermission.setUser_id(user_id);
newPermission.setPermission(MySQLConstants.getConnectionConstant(permission.getType()));
newPermission.setConnection_id(connection_id);
connectionPermissionDAO.insert(newPermission); connectionPermissionDAO.insert(newPermission);
} }
} }
@@ -470,54 +451,43 @@ public class UserDirectory implements Directory<String, net.sourceforge.guacamol
Collection<ConnectionPermission> permissions) Collection<ConnectionPermission> permissions)
throws GuacamoleException { throws GuacamoleException {
// If no permissions given, stop now
if(permissions.isEmpty()) if(permissions.isEmpty())
return; return;
// Get set of administerable users // Get list of administerable connection IDs
Set<Integer> administerableConnections = List<Integer> administerableConnectionIDs =
permissionCheckService.getAdministerableConnectionIDs(this.user_id); permissionCheckService.retrieveUserIDs(this.user_id,
MySQLConstants.CONNECTION_ADMINISTER);
// Get list of identifiers for all given user permissions. // Get set of names corresponding to administerable connections
List<String> identifiers = new ArrayList<String>(); Map<String, Integer> administerableConnections =
for (ConnectionPermission permission : permissions) userService.translateUsernames(administerableConnectionIDs);
identifiers.add(permission.getObjectIdentifier());
// Find all the connections by identifiers // Delete requested permissions
List<MySQLConnection> connections = connectionService.retrieveConnectionsByName(identifiers);
List<Integer> connectionIDs = new ArrayList<Integer>();
// Build map of found connections, indexed by identifier
Map<String, MySQLConnection> connectionMap = new HashMap<String, MySQLConnection>();
for (MySQLConnection connection : connections) {
connectionMap.put(connection.getIdentifier(), connection);
connectionIDs.add(connection.getConnectionID());
}
// Verify we have permission to delete each connection permission.
for (ConnectionPermission permission : permissions) { for (ConnectionPermission permission : permissions) {
// Get user // Get original ID
MySQLConnection connection = connectionMap.get(permission.getObjectIdentifier()); Integer connection_id =
if (connection == null) administerableConnections.get(permission.getObjectIdentifier());
throw new GuacamoleException(
"User '" + permission.getObjectIdentifier()
+ "' not found.");
// Verify that the user actually has permission to administrate // Verify that the user actually has permission to administrate
// every one of these connections // every one of these connections
if (!administerableConnections.contains(connection.getConnectionID())) if (connection_id == null)
throw new GuacamoleSecurityException( throw new GuacamoleSecurityException(
"User #" + this.user_id "User #" + this.user_id
+ " does not have permission to administrate connection " + " does not have permission to administrate connection "
+ connection.getIdentifier()); + permission.getObjectIdentifier());
ConnectionPermissionExample connectionPermissionExample = new ConnectionPermissionExample();
connectionPermissionExample.createCriteria()
.andUser_idEqualTo(user_id)
.andPermissionEqualTo(MySQLConstants.getConnectionConstant(permission.getType()))
.andConnection_idEqualTo(connection_id);
connectionPermissionDAO.deleteByExample(connectionPermissionExample);
} }
if(!connectionIDs.isEmpty()) {
ConnectionPermissionExample connectionPermissionExample = new ConnectionPermissionExample();
connectionPermissionExample.createCriteria().andUser_idEqualTo(user_id)
.andConnection_idIn(connectionIDs);
connectionPermissionDAO.deleteByExample(connectionPermissionExample);
}
} }
/** /**
@@ -538,7 +508,7 @@ public class UserDirectory implements Directory<String, net.sourceforge.guacamol
List<String> systemPermissionTypes = new ArrayList<String>(); List<String> systemPermissionTypes = new ArrayList<String>();
for (SystemPermission permission : permissions) { for (SystemPermission permission : permissions) {
switch (permission.getType()) { switch (permission.getType()) { // TODO: Move this into MySQLConstants
// Create connection permission // Create connection permission
case CREATE_CONNECTION: case CREATE_CONNECTION:
@@ -627,12 +597,14 @@ public class UserDirectory implements Directory<String, net.sourceforge.guacamol
if (!(object instanceof MySQLUser)) if (!(object instanceof MySQLUser))
throw new GuacamoleException("User not from database."); throw new GuacamoleException("User not from database.");
MySQLUser mySQLUser = (MySQLUser) object;
// Validate permission to update this user is granted // Validate permission to update this user is granted
permissionCheckService.verifyUserUpdateAccess(this.user_id, permissionCheckService.verifyUserAccess(this.user_id,
object.getUsername()); mySQLUser.getUserID(),
MySQLConstants.USER_UPDATE);
// Update the user in the database // Update the user in the database
MySQLUser mySQLUser = (MySQLUser) object;
userService.updateUser(mySQLUser); userService.updateUser(mySQLUser);
// Update permissions in database // Update permissions in database
@@ -649,17 +621,16 @@ public class UserDirectory implements Directory<String, net.sourceforge.guacamol
@Transactional @Transactional
public void remove(String identifier) throws GuacamoleException { public void remove(String identifier) throws GuacamoleException {
// FIXME: Querying permissions here will query the user to determine // Get user pending deletion
// its ID, and that same user will be queried AGAIN later when MySQLUser user = userService.retrieveUser(identifier);
// deleted, again - to determine its ID. Perhaps we want cascading
// deletes in the schema?
// Validate current user has permission to remove the specified user // Validate current user has permission to remove the specified user
permissionCheckService.verifyUserDeleteAccess(this.user_id, permissionCheckService.verifyUserAccess(this.user_id,
identifier); user.getUserID(),
MySQLConstants.USER_DELETE);
// Delete specified user // Delete specified user
userService.deleteUser(identifier); userService.deleteUser(user.getUserID());
} }

View File

@@ -41,7 +41,9 @@ import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import net.sourceforge.guacamole.GuacamoleException; import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.GuacamoleSocket; import net.sourceforge.guacamole.net.GuacamoleSocket;
import net.sourceforge.guacamole.net.InetGuacamoleSocket; import net.sourceforge.guacamole.net.InetGuacamoleSocket;
@@ -163,56 +165,63 @@ public class ConnectionService {
} }
/** /**
* Retrieves the connections having the given IDs from the database. * Retrieves a translation map of connection names to their corresponding
* IDs.
* *
* @param ids The IDs of the connections to retrieve. * @param ids The IDs of the connections to retrieve the names of.
* @return A list of existing MySQLConnection objects. * @return A map containing the names of all connections and their
* corresponding IDs.
*/ */
public List<MySQLConnection> retrieveConnectionsByID(List<Integer> ids) { public Map<String, Integer> translateNames(List<Integer> ids) {
// If no IDs given, just return empty list // If no IDs given, just return empty map
if (ids.isEmpty()) if (ids.isEmpty())
return Collections.EMPTY_LIST; return Collections.EMPTY_MAP;
// Query connections by ID // Map of all names onto their corresponding IDs.
Map<String, Integer> names = new HashMap<String, Integer>();
// Get all connections having the given IDs
ConnectionExample example = new ConnectionExample(); ConnectionExample example = new ConnectionExample();
example.createCriteria().andConnection_idIn(ids); example.createCriteria().andConnection_idIn(ids);
List<Connection> connections = connectionDAO.selectByExample(example); List<Connection> connections = connectionDAO.selectByExample(example);
// Convert to MySQLConnection list // Produce set of names
List<MySQLConnection> mySQLConnections = new ArrayList<MySQLConnection>(connections.size());
for (Connection connection : connections) for (Connection connection : connections)
mySQLConnections.add(toMySQLConnection(connection)); names.put(connection.getConnection_name(),
connection.getConnection_id());
// Return found connections return names;
return mySQLConnections;
} }
/** /**
* Retrieves the connections having the given names from the database. * Retrieves a map of all connection names for the given IDs.
* *
* @param names The names of the connections to retrieve. * @param ids The IDs of the connections to retrieve the names of.
* @return A list of existing MySQLConnection objects. * @return A map containing the names of all connections and their
* corresponding IDs.
*/ */
public List<MySQLConnection> retrieveConnectionsByName(List<String> names) { public Map<Integer, String> retrieveNames(List<Integer> ids) {
// If no names given, just return empty list // If no IDs given, just return empty map
if (names.isEmpty()) if (ids.isEmpty())
return Collections.EMPTY_LIST; return Collections.EMPTY_MAP;
// Query connections by ID // Map of all names onto their corresponding IDs.
Map<Integer, String> names = new HashMap<Integer, String>();
// Get all connections having the given IDs
ConnectionExample example = new ConnectionExample(); ConnectionExample example = new ConnectionExample();
example.createCriteria().andConnection_nameIn(names); example.createCriteria().andConnection_idIn(ids);
List<Connection> connections = connectionDAO.selectByExample(example); List<Connection> connections = connectionDAO.selectByExample(example);
// Convert to MySQLConnection list // Produce set of names
List<MySQLConnection> mySQLConnections = new ArrayList<MySQLConnection>(connections.size());
for (Connection connection : connections) for (Connection connection : connections)
mySQLConnections.add(toMySQLConnection(connection)); names.put(connection.getConnection_id(),
connection.getConnection_name());
// Return found connections return names;
return mySQLConnections;
} }
@@ -352,21 +361,6 @@ public class ConnectionService {
} }
/**
* Deletes the connection having the given name from the database.
* @param name The name of the connection to delete.
*/
public void deleteConnection(String name) {
// Get specified connection
MySQLConnection mySQLConnection = retrieveConnection(name);
int connection_id = mySQLConnection.getConnectionID();
// Delete the connection in the database
deleteConnection(connection_id);
}
/** /**
* Deletes the connection having the given ID from the database. * Deletes the connection having the given ID from the database.
* @param id The ID of the connection to delete. * @param id The ID of the connection to delete.

View File

@@ -35,19 +35,14 @@
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
package net.sourceforge.guacamole.net.auth.mysql.service; package net.sourceforge.guacamole.net.auth.mysql.service;
import com.google.common.collect.Lists;
import com.google.inject.Inject; import com.google.inject.Inject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import net.sourceforge.guacamole.GuacamoleSecurityException; import net.sourceforge.guacamole.GuacamoleSecurityException;
import net.sourceforge.guacamole.net.auth.mysql.MySQLConnection;
import net.sourceforge.guacamole.net.auth.mysql.MySQLConstants; import net.sourceforge.guacamole.net.auth.mysql.MySQLConstants;
import net.sourceforge.guacamole.net.auth.mysql.MySQLUser;
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper;
import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper;
import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper; import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper;
@@ -80,744 +75,299 @@ public class PermissionCheckService {
@Inject @Inject
private ConnectionService connectionService; private ConnectionService connectionService;
/**
* DAO for accessing permissions related to users.
*/
@Inject @Inject
private UserPermissionMapper userPermissionDAO; private UserPermissionMapper userPermissionDAO;
/**
* DAO for accessing permissions related to connections.
*/
@Inject @Inject
private ConnectionPermissionMapper connectionPermissionDAO; private ConnectionPermissionMapper connectionPermissionDAO;
/**
* DAO for accessing permissions related to the system as a whole.
*/
@Inject @Inject
private SystemPermissionMapper systemPermissionDAO; private SystemPermissionMapper systemPermissionDAO;
/** /**
* Verifies that the user has read access to the given user. If not, throws a GuacamoleSecurityException. * Verifies that the user has the specified access to the given other
* @param userID * user. If permission is denied, a GuacamoleSecurityException is thrown.
* @param affectedUserID *
* @throws GuacamoleSecurityException * @param userID The ID of the user to check.
* @param affectedUserID The user that would be affected by the operation
* if permission is granted.
* @param permissionType The type of permission to check for.
* @throws GuacamoleSecurityException If the specified permission is not
* granted.
*/ */
public void verifyUserReadAccess(int userID, int affectedUserID) throws GuacamoleSecurityException { public void verifyUserAccess(int userID, int affectedUserID,
if(!checkUserReadAccess(userID, affectedUserID)) String permissionType) throws GuacamoleSecurityException {
throw new GuacamoleSecurityException("User " + userID + " does not have read access to user " + affectedUserID);
// If permission does not exist, throw exception
if(!checkUserAccess(userID, affectedUserID, permissionType))
throw new GuacamoleSecurityException("Permission denied.");
} }
/** /**
* Verifies that the user has update access to the given user. If not, throws a GuacamoleSecurityException. * Verifies that the user has the specified access to the given connection.
* @param userID * If permission is denied, a GuacamoleSecurityException is thrown.
* @param affectedUserID *
* @throws GuacamoleSecurityException * @param userID The ID of the user to check.
* @param affectedConnectionID The connection that would be affected by the
* operation if permission is granted.
* @param permissionType The type of permission to check for.
* @throws GuacamoleSecurityException If the specified permission is not
* granted.
*/ */
public void verifyUserUpdateAccess(int userID, int affectedUserID) throws GuacamoleSecurityException { public void verifyConnectionAccess(int userID, int affectedConnectionID, String permissionType) throws GuacamoleSecurityException {
if(!checkUserUpdateAccess(userID, affectedUserID))
throw new GuacamoleSecurityException("User " + userID + " does not have update access to user " + affectedUserID); // If permission does not exist, throw exception
if(!checkConnectionAccess(userID, affectedConnectionID, permissionType))
throw new GuacamoleSecurityException("Permission denied.");
}
/**
* Verifies that the user has the specified access to the system. If
* permission is denied, a GuacamoleSecurityException is thrown.
*
* @param userID The ID of the user to check.
* @param systemPermissionType The type of permission to check for.
* @throws GuacamoleSecurityException If the specified permission is not
* granted.
*/
public void verifySystemAccess(int userID, String systemPermissionType)
throws GuacamoleSecurityException {
// If permission does not exist, throw exception
if(!checkSystemAccess(userID, systemPermissionType))
throw new GuacamoleSecurityException("Permission denied.");
} }
/** /**
* Verifies that the user has delete access to the given user. If not, throws a GuacamoleSecurityException. * Checks whether a user has the specified type of access to the affected
* @param userID * user.
* @param affectedUserID *
* @throws GuacamoleSecurityException * @param userID The ID of the user to check.
* @param affectedUserID The user that would be affected by the operation
* if permission is granted.
* @param permissionType The type of permission to check for.
* @return true if the specified permission is granted, false otherwise.
*/ */
public void verifyUserDeleteAccess(int userID, int affectedUserID) throws GuacamoleSecurityException { public boolean checkUserAccess(int userID, Integer affectedUserID, String permissionType) {
if(!checkUserDeleteAccess(userID, affectedUserID))
throw new GuacamoleSecurityException("User " + userID + " does not have delete access to user " + affectedUserID);
}
/** // Check existence of requested permission
* Verifies that the user has administer access to the given user. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedUserID
* @throws GuacamoleSecurityException
*/
public void verifyUserAdministerAccess(int userID, int affectedUserID) throws GuacamoleSecurityException {
if(!checkUserAdministerAccess(userID, affectedUserID))
throw new GuacamoleSecurityException("User " + userID + " does not have administer access to user " + affectedUserID);
}
/**
* Verifies that the user has read access to the given user. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedUsername
* @throws GuacamoleSecurityException
*/
public void verifyUserReadAccess(int userID, String affectedUsername) throws GuacamoleSecurityException {
if(!checkUserReadAccess(userID, affectedUsername))
throw new GuacamoleSecurityException("User " + userID + " does not have read access to user '" + affectedUsername + "'");
}
/**
* Verifies that the user has update access to the given user. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedUsername
* @throws GuacamoleSecurityException
*/
public void verifyUserUpdateAccess(int userID, String affectedUsername) throws GuacamoleSecurityException {
if(!checkUserUpdateAccess(userID, affectedUsername))
throw new GuacamoleSecurityException("User " + userID + " does not have update access to user '" + affectedUsername + "'");
}
/**
* Verifies that the user has delete access to the given user. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedUsername
* @throws GuacamoleSecurityException
*/
public void verifyUserDeleteAccess(int userID, String affectedUsername) throws GuacamoleSecurityException {
if(!checkUserDeleteAccess(userID, affectedUsername))
throw new GuacamoleSecurityException("User " + userID + " does not have delete access to user '" + affectedUsername + "'");
}
/**
* Verifies that the user has administer access to the given user. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedUsername
* @throws GuacamoleSecurityException
*/
public void verifyUserAdministerAccess(int userID, String affectedUsername) throws GuacamoleSecurityException {
if(!checkUserAdministerAccess(userID, affectedUsername))
throw new GuacamoleSecurityException("User " + userID + " does not have administer access to user '" + affectedUsername + "'");
}
/**
* Checks if the user has read access to the given user.
* @param userID
* @param affectedUserID
* @return true if the user has access to this user.
*/
public boolean checkUserReadAccess(int userID, int affectedUserID) {
return checkUserAccess(userID, affectedUserID, MySQLConstants.USER_READ);
}
/**
* Checks if the user has update access to the given user.
* @param userID
* @param affectedUserID
* @return true if the user has access to this user.
*/
public boolean checkUserUpdateAccess(int userID, int affectedUserID) {
return checkUserAccess(userID, affectedUserID, MySQLConstants.USER_UPDATE);
}
/**
* Checks if the user has delete access to the given user.
* @param userID
* @param affectedUserID
* @return true if the user has access to this user.
*/
public boolean checkUserDeleteAccess(int userID, int affectedUserID) {
return checkUserAccess(userID, affectedUserID, MySQLConstants.USER_DELETE);
}
/**
* Checks if the user has administer access to the given user.
* @param userID
* @param affectedUserID
* @return true if the user has access to this user.
*/
public boolean checkUserAdministerAccess(int userID, int affectedUserID) {
return checkUserAccess(userID, affectedUserID, MySQLConstants.USER_ADMINISTER);
}
/**
* Checks if the user has read access to the given user.
* @param userID
* @param affectedUsername
* @return true if the user has access to this user.
*/
public boolean checkUserReadAccess(int userID, String affectedUsername) {
return checkUserAccess(userID, affectedUsername, MySQLConstants.USER_READ);
}
/**
* Checks if the user has update access to the given user.
* @param userID
* @param affectedUsername
* @return true if the user has access to this user.
*/
public boolean checkUserUpdateAccess(int userID, String affectedUsername) {
return checkUserAccess(userID, affectedUsername, MySQLConstants.USER_UPDATE);
}
/**
* Checks if the user has delete access to the given user.
* @param userID
* @param affectedUsername
* @return true if the user has access to this user.
*/
public boolean checkUserDeleteAccess(int userID, String affectedUsername) {
return checkUserAccess(userID, affectedUsername, MySQLConstants.USER_DELETE);
}
/**
* Checks if the user has administer access to the given user.
* @param userID
* @param affectedUsername
* @return true if the user has access to this user.
*/
public boolean checkUserAdministerAccess(int userID, String affectedUsername) {
return checkUserAccess(userID, affectedUsername, MySQLConstants.USER_ADMINISTER);
}
/**
* Check if the user has the selected type of access to the affected user.
* @param userID
* @param affectedUsername
* @param permissionType
* @return
*/
private boolean checkUserAccess(int userID, String affectedUsername, String permissionType) {
MySQLUser affectedUser = userService.retrieveUser(affectedUsername);
if(affectedUser != null)
return checkUserAccess(userID, affectedUser.getUserID(), permissionType);
return false;
}
/**
* Check if the user has the selected type of access to the affected user.
* @param userID
* @param affectedUserID
* @param permissionType
* @return
*/
private boolean checkUserAccess(int userID, Integer affectedUserID, String permissionType) {
UserPermissionExample example = new UserPermissionExample(); UserPermissionExample example = new UserPermissionExample();
example.createCriteria().andUser_idEqualTo(userID).andAffected_user_idEqualTo(affectedUserID).andPermissionEqualTo(permissionType); example.createCriteria().andUser_idEqualTo(userID).andAffected_user_idEqualTo(affectedUserID).andPermissionEqualTo(permissionType);
int count = userPermissionDAO.countByExample(example); return userPermissionDAO.countByExample(example) > 0;
return count > 0;
} }
/** /**
* Find the list of all user IDs a user has permission to administer. * Checks whether a user has the specified type of access to the affected
* @param userID * connection.
* @return the list of all user IDs this user has administer access to *
* @param userID The ID of the user to check.
* @param affectedConnectionID The connection that would be affected by the
* operation if permission is granted.
* @param permissionType The type of permission to check for.
* @return true if the specified permission is granted, false otherwise.
*/ */
public Set<Integer> getAdministerableUserIDs(int userID) { public boolean checkConnectionAccess(int userID, Integer affectedConnectionID, String permissionType) {
return getUserIDs(userID, MySQLConstants.USER_ADMINISTER);
// Check existence of requested permission
ConnectionPermissionExample example = new ConnectionPermissionExample();
example.createCriteria().andUser_idEqualTo(userID).andConnection_idEqualTo(affectedConnectionID).andPermissionEqualTo(permissionType);
return connectionPermissionDAO.countByExample(example) > 0;
} }
/** /**
* Find the list of all user IDs a user has permission to delete. * Checks whether a user has the specified type of access to the system.
* @param userID *
* @return the list of all user IDs this user has delete access to * @param userID The ID of the user to check.
* @param systemPermissionType The type of permission to check for.
* @return true if the specified permission is granted, false otherwise.
*/ */
public Set<Integer> getDeletableUserIDs(int userID) { private boolean checkSystemAccess(int userID, String systemPermissionType) {
return getUserIDs(userID, MySQLConstants.USER_DELETE);
}
/** // Check existence of requested permission
* Find the list of all user IDs a user has permission to write. SystemPermissionExample example = new SystemPermissionExample();
* @param userID example.createCriteria().andUser_idEqualTo(userID).andPermissionEqualTo(systemPermissionType);
* @return the list of all user IDs this user has write access to return systemPermissionDAO.countByExample(example) > 0;
*/
public Set<Integer> getUpdateableUserIDs(int userID) {
return getUserIDs(userID, MySQLConstants.USER_UPDATE);
}
/**
* Find the list of all user IDs a user has permission to read.
* @param userID
* @return the list of all user IDs this user has read access to
*/
public Set<Integer> getReadableUserIDs(int userID) {
return getUserIDs(userID, MySQLConstants.USER_READ);
}
/**
* Find the list of all users a user has permission to administer.
* @param userID
* @return the list of all users this user has administer access to
*/
public Set<MySQLUser> getAdministerableUsers(int userID) {
return getUsers(userID, MySQLConstants.USER_ADMINISTER);
}
/**
* Find the list of all users a user has permission to delete.
* @param userID
* @return the list of all users this user has delete access to
*/
public Set<MySQLUser> getDeletableUsers(int userID) {
return getUsers(userID, MySQLConstants.USER_DELETE);
}
/**
* Find the list of all users a user has permission to write.
* @param userID
* @return the list of all users this user has write access to
*/
public Set<MySQLUser> getUpdateableUsers(int userID) {
return getUsers(userID, MySQLConstants.USER_UPDATE);
}
/**
* Find the list of all users a user has permission to read.
* @param userID
* @return the list of all users this user read has access to
*/
public Set<MySQLUser> getReadableUsers(int userID) {
return getUsers(userID, MySQLConstants.USER_READ);
}
/**
* Find the list of all users a user has permission to.
* The access type is defined by permissionType.
* @param userID
* @param permissionType
* @return the list of all users this user has access to
*/
@Deprecated /* FIXME: Totally useless (we only ever need usernames, and querying ALL USER DATA will take ages) */
private Set<MySQLUser> getUsers(int userID, String permissionType) {
// Get all IDs of all users that the given user can perform the given
// operation on
Set<Integer> affectedUserIDs = getUserIDs(userID, permissionType);
// If no affected users at all, return empty set
if (affectedUserIDs.isEmpty())
return Collections.EMPTY_SET;
// Query corresponding user data for each retrieved ID
return new HashSet<MySQLUser>(userService.retrieveUsersByID(
Lists.newArrayList(affectedUserIDs)));
} }
/** /**
* Find the list of the IDs of all users a user has permission to. * Find the list of the IDs of all users a user has permission to.
* The access type is defined by permissionType. * The access type is defined by permissionType.
* @param userID *
* @param permissionType * @param userID The ID of the user to check.
* @return the list of all user IDs this user has access to * @param permissionType The type of permission to check for.
* @return A list of all user IDs this user has the specified access to.
*/ */
private Set<Integer> getUserIDs(int userID, String permissionType) { public List<Integer> retrieveUserIDs(int userID, String permissionType) {
Set<Integer> userIDs = new HashSet<Integer>();
// Query all user permissions for the given user and permission type
UserPermissionExample example = new UserPermissionExample(); UserPermissionExample example = new UserPermissionExample();
example.createCriteria().andUser_idEqualTo(userID).andPermissionEqualTo(permissionType); example.createCriteria().andUser_idEqualTo(userID).andPermissionEqualTo(permissionType);
List<UserPermissionKey> userPermissions = userPermissionDAO.selectByExample(example); example.setDistinct(true);
List<UserPermissionKey> userPermissions =
userPermissionDAO.selectByExample(example);
// Convert result into list of IDs
List<Integer> userIDs = new ArrayList<Integer>(userPermissions.size());
for(UserPermissionKey permission : userPermissions) for(UserPermissionKey permission : userPermissions)
userIDs.add(permission.getAffected_user_id()); userIDs.add(permission.getAffected_user_id());
return userIDs; return userIDs;
}
/**
* Verifies that the user has read access to the given connection. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedConnectionID
* @throws GuacamoleSecurityException
*/
public void verifyConnectionReadAccess(int userID, int affectedConnectionID) throws GuacamoleSecurityException {
if(!checkConnectionReadAccess(userID, affectedConnectionID))
throw new GuacamoleSecurityException("User " + userID + " does not have read access to connection " + affectedConnectionID);
}
/**
* Verifies that the user has update access to the given connection. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedConnectionID
* @throws GuacamoleSecurityException
*/
public void verifyConnectionUpdateAccess(int userID, int affectedConnectionID) throws GuacamoleSecurityException {
if(!checkConnectionUpdateAccess(userID, affectedConnectionID))
throw new GuacamoleSecurityException("User " + userID + " does not have update access to connection " + affectedConnectionID);
}
/**
* Verifies that the user has delete access to the given connection. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedConnectionID
* @throws GuacamoleSecurityException
*/
public void verifyConnectionDeleteAccess(int userID, int affectedConnectionID) throws GuacamoleSecurityException {
if(!checkConnectionDeleteAccess(userID, affectedConnectionID))
throw new GuacamoleSecurityException("User " + userID + " does not have delete access to connection " + affectedConnectionID);
}
/**
* Verifies that the user has administer access to the given connection. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedConnectionID
* @throws GuacamoleSecurityException
*/
public void verifyConnectionAdministerAccess(int userID, int affectedConnectionID) throws GuacamoleSecurityException {
if(!checkConnectionAdministerAccess(userID, affectedConnectionID))
throw new GuacamoleSecurityException("User " + userID + " does not have administer access to connection " + affectedConnectionID);
}
/**
* Verifies that the user has read access to the given connection. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedConnectionName
* @throws GuacamoleSecurityException
*/
public void verifyConnectionReadAccess(int userID, String affectedConnectionName) throws GuacamoleSecurityException {
if(!checkConnectionReadAccess(userID, affectedConnectionName))
throw new GuacamoleSecurityException("User " + userID + " does not have read access to connection '" + affectedConnectionName + "'");
}
/**
* Verifies that the user has update access to the given connection. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedConnectionName
* @throws GuacamoleSecurityException
*/
public void verifyConnectionUpdateAccess(int userID, String affectedConnectionName) throws GuacamoleSecurityException {
if(!checkConnectionUpdateAccess(userID, affectedConnectionName))
throw new GuacamoleSecurityException("User " + userID + " does not have update access to connection '" + affectedConnectionName + "'");
}
/**
* Verifies that the user has delete access to the given connection. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedConnectionName
* @throws GuacamoleSecurityException
*/
public void verifyConnectionDeleteAccess(int userID, String affectedConnectionName) throws GuacamoleSecurityException {
if(!checkConnectionDeleteAccess(userID, affectedConnectionName))
throw new GuacamoleSecurityException("User " + userID + " does not have delete access to connection '" + affectedConnectionName + "'");
}
/**
* Verifies that the user has administer access to the given connection. If not, throws a GuacamoleSecurityException.
* @param userID
* @param affectedConnectionName
* @throws GuacamoleSecurityException
*/
public void verifyConnectionAdministerAccess(int userID, String affectedConnectionName) throws GuacamoleSecurityException {
if(!checkConnectionAdministerAccess(userID, affectedConnectionName))
throw new GuacamoleSecurityException("User " + userID + " does not have administer access to connection '" + affectedConnectionName + "'");
}
/**
* Checks if the user has read access to the given connection.
* @param userID
* @param affectedConnectionID
* @return true if the user has access to this connection.
*/
public boolean checkConnectionReadAccess(int userID, int affectedConnectionID) {
return checkConnectionAccess(userID, affectedConnectionID, MySQLConstants.CONNECTION_READ);
}
/**
* Checks if the user has update access to the given connection.
* @param userID
* @param affectedConnectionID
* @return true if the user has access to this connection.
*/
public boolean checkConnectionUpdateAccess(int userID, int affectedConnectionID) {
return checkConnectionAccess(userID, affectedConnectionID, MySQLConstants.CONNECTION_UPDATE);
}
/**
* Checks if the user has delete access to the given connection.
* @param userID
* @param affectedConnectionID
* @return true if the user has access to this connection.
*/
public boolean checkConnectionDeleteAccess(int userID, int affectedConnectionID) {
return checkConnectionAccess(userID, affectedConnectionID, MySQLConstants.CONNECTION_DELETE);
}
/**
* Checks if the user has administer access to the given connection.
* @param userID
* @param affectedConnectionID
* @return true if the user has access to this connection.
*/
public boolean checkConnectionAdministerAccess(int userID, int affectedConnectionID) {
return checkConnectionAccess(userID, affectedConnectionID, MySQLConstants.CONNECTION_ADMINISTER);
}
/**
* Checks if the user has read access to the given connection.
* @param userID
* @param affectedConnectionName
* @return true if the user has access to this connection.
*/
public boolean checkConnectionReadAccess(int userID, String affectedConnectionName) {
return checkConnectionAccess(userID, affectedConnectionName, MySQLConstants.CONNECTION_READ);
}
/**
* Checks if the user has update access to the given connection.
* @param userID
* @param affectedConnectionName
* @return true if the user has access to this connection.
*/
public boolean checkConnectionUpdateAccess(int userID, String affectedConnectionName) {
return checkConnectionAccess(userID, affectedConnectionName, MySQLConstants.CONNECTION_UPDATE);
}
/**
* Checks if the user has delete access to the given connection.
* @param userID
* @param affectedConnectionID
* @return true if the user has access to this connection.
*/
public boolean checkConnectionDeleteAccess(int userID, String affectedConnectionname) {
return checkConnectionAccess(userID, affectedConnectionname, MySQLConstants.CONNECTION_DELETE);
}
/**
* Checks if the user has administer access to the given connection.
* @param userID
* @param affectedConnectionName
* @return true if the user has access to this connection.
*/
public boolean checkConnectionAdministerAccess(int userID, String affectedConnectionName) {
return checkConnectionAccess(userID, affectedConnectionName, MySQLConstants.CONNECTION_ADMINISTER);
}
/**
* Check if the user has the selected type of access to the affected connection.
* @param connectionID
* @param affectedConnectionname
* @param permissionType
* @return
*/
private boolean checkConnectionAccess(int userID, String affectedConnectionName, String permissionType) {
MySQLConnection connection = connectionService.retrieveConnection(affectedConnectionName);
if(connection != null)
return checkConnectionAccess(userID, connection.getConnectionID(), permissionType);
return false;
}
/**
* Check if the user has the selected type of access to the affected connection.
* @param connectionID
* @param affectedConnectionID
* @param permissionType
* @return
*/
private boolean checkConnectionAccess(int userID, Integer affectedConnectionID, String permissionType) {
ConnectionPermissionExample example = new ConnectionPermissionExample();
example.createCriteria().andUser_idEqualTo(userID).andConnection_idEqualTo(affectedConnectionID).andPermissionEqualTo(permissionType);
int count = connectionPermissionDAO.countByExample(example);
return count > 0;
}
/**
* Find the list of all connection IDs a user has permission to administer.
* @param userID
* @return the list of all connection IDs this user has administer access to
*/
public Set<Integer> getAdministerableConnectionIDs(int userID) {
return getConnectionIDs(userID, MySQLConstants.CONNECTION_ADMINISTER);
}
/**
* Find the list of all connection IDs a user has permission to delete.
* @param userID
* @return the list of all connection IDs this user has delete access to
*/
public Set<Integer> getDeletableConnectionIDs(int userID) {
return getConnectionIDs(userID, MySQLConstants.CONNECTION_DELETE);
}
/**
* Find the list of all connection IDs a user has permission to write.
* @param userID
* @return the list of all connection IDs this user has write access to
*/
public Set<Integer> getUpdateableConnectionIDs(int userID) {
return getConnectionIDs(userID, MySQLConstants.CONNECTION_UPDATE);
}
/**
* Find the list of all connection IDs a user has permission to read.
* @param userID
* @return the list of all connection IDs this user has ready access to
*/
public Set<Integer> getReadableConnectionIDs(int userID) {
return getConnectionIDs(userID, MySQLConstants.CONNECTION_READ);
}
/**
* Find the list of all connections a user has permission to administer.
* @param userID
* @return the list of all connections this user has administer access to
*/
public Set<MySQLConnection> getAdministerableConnections(int userID) {
return getConnections(userID, MySQLConstants.CONNECTION_ADMINISTER);
}
/**
* Find the list of all connections a user has permission to delete.
* @param userID
* @return the list of all connections this user has delete access to
*/
public Set<MySQLConnection> getDeletableConnections(int userID) {
return getConnections(userID, MySQLConstants.CONNECTION_DELETE);
}
/**
* Find the list of all connections a user has permission to write.
* @param userID
* @return the list of all connections this user has write access to
*/
public Set<MySQLConnection> getUpdateableConnections(int userID) {
return getConnections(userID, MySQLConstants.CONNECTION_UPDATE);
}
/**
* Find the list of all connections a user has permission to read.
* @param userID
* @return the list of all connections this user has read access to
*/
public Set<MySQLConnection> getReadableConnections(int userID) {
return getConnections(userID, MySQLConstants.CONNECTION_READ);
}
/**
* Find the list of all connections a user has permission to.
* The access type is defined by permissionType.
* @param connectionID
* @param permissionType
* @return the list of all connections this user has access to
*/
@Deprecated /* FIXME: Totally useless (we only ever need identifiers, and querying ALL CONNECTION DATA will take ages) */
private Set<MySQLConnection> getConnections(int userID, String permissionType) {
Set<Integer> affectedConnectionIDs = getConnectionIDs(userID, permissionType);
return new HashSet<MySQLConnection>(
connectionService.retrieveConnectionsByID(Lists.newArrayList(affectedConnectionIDs)));
} }
/** /**
* Find the list of the IDs of all connections a user has permission to. * Find the list of the IDs of all connections a user has permission to.
* The access type is defined by permissionType. * The access type is defined by permissionType.
* @param connectionID *
* @param permissionType * @param userID The ID of the user to check.
* @return the list of all connection IDs this user has access to * @param permissionType The type of permission to check for.
* @return A list of all connection IDs this user has the specified access
* to.
*/ */
private Set<Integer> getConnectionIDs(int userID, String permissionType) { public List<Integer> retrieveConnectionIDs(int userID,
Set<Integer> connectionIDs = new HashSet<Integer>(); String permissionType) {
// Query all connection permissions for the given user and permission type
ConnectionPermissionExample example = new ConnectionPermissionExample(); ConnectionPermissionExample example = new ConnectionPermissionExample();
example.createCriteria().andUser_idEqualTo(userID).andPermissionEqualTo(permissionType); example.createCriteria().andUser_idEqualTo(userID).andPermissionEqualTo(permissionType);
List<ConnectionPermissionKey> connectionPermissions = connectionPermissionDAO.selectByExample(example); example.setDistinct(true);
List<ConnectionPermissionKey> connectionPermissions =
connectionPermissionDAO.selectByExample(example);
// Convert result into list of IDs
List<Integer> connectionIDs = new ArrayList<Integer>(connectionPermissions.size());
for(ConnectionPermissionKey permission : connectionPermissions) for(ConnectionPermissionKey permission : connectionPermissions)
connectionIDs.add(permission.getConnection_id()); connectionIDs.add(permission.getConnection_id());
return connectionIDs; return connectionIDs;
}
public void verifyCreateUserPermission(int userID) throws GuacamoleSecurityException {
if(!checkCreateUserPermission(userID))
throw new GuacamoleSecurityException("User " + userID + " does not have permission to create users.");
}
public void verifyCreateConnectionPermission(int userID) throws GuacamoleSecurityException {
if(!checkCreateConnectionPermission(userID))
throw new GuacamoleSecurityException("User " + userID + " does not have permission to create connections.");
} }
/** /**
* Check if the user has the permission to create users. * Retrieves all user permissions granted to the user having the given ID.
* @param userID *
* @return * @param userID The ID of the user to retrieve permissions of.
* @return A set of all user permissions granted to the user having the
* given ID.
*/ */
public boolean checkCreateUserPermission(int userID) { public Set<UserPermission> retrieveUserPermissions(int userID) {
return checkSystemPermission(userID, MySQLConstants.SYSTEM_USER_CREATE);
}
/** // Set of all permissions
* Check if the user has the permission to create connections. Set<UserPermission> permissions = new HashSet<UserPermission>();
* @param userID
* @return
*/
public boolean checkCreateConnectionPermission(int userID) {
return checkSystemPermission(userID, MySQLConstants.SYSTEM_CONNECTION_CREATE);
}
/** // Query all user permissions
* Check if the user has the selected system permission.
* @param userID
* @param systemPermissionType
* @return
*/
private boolean checkSystemPermission(int userID, String systemPermissionType) {
SystemPermissionExample example = new SystemPermissionExample();
example.createCriteria().andUser_idEqualTo(userID).andPermissionEqualTo(systemPermissionType);
int count = systemPermissionDAO.countByExample(example);
return count > 0;
}
/**
* Get all permissions a given user has.
* @param userID
* @return all permissions a user has.
*/
public Set<Permission> getAllPermissions(int userID) {
Set<Permission> allPermissions = new HashSet<Permission>();
// First, user permissions
UserPermissionExample userPermissionExample = new UserPermissionExample(); UserPermissionExample userPermissionExample = new UserPermissionExample();
userPermissionExample.createCriteria().andUser_idEqualTo(userID); userPermissionExample.createCriteria().andUser_idEqualTo(userID);
List<UserPermissionKey> userPermissions = List<UserPermissionKey> userPermissions =
userPermissionDAO.selectByExample(userPermissionExample); userPermissionDAO.selectByExample(userPermissionExample);
// If user permissions present, add permissions // Get list of affected user IDs
if (!userPermissions.isEmpty()) { List<Integer> affectedUserIDs = new ArrayList<Integer>();
for(UserPermissionKey userPermission : userPermissions)
affectedUserIDs.add(userPermission.getAffected_user_id());
// Get list of affected user IDs // Get corresponding usernames
List<Integer> affectedUserIDs = new ArrayList<Integer>(); Map<Integer, String> affectedUsers =
for(UserPermissionKey userPermission : userPermissions) userService.retrieveUsernames(affectedUserIDs);
affectedUserIDs.add(userPermission.getAffected_user_id());
// Query all affected users, store in map indexed by user ID // Add user permissions
List<MySQLUser> users = userService.retrieveUsersByID(affectedUserIDs); for(UserPermissionKey userPermission : userPermissions) {
Map<Integer, MySQLUser> userMap = new HashMap<Integer, MySQLUser>();
for (MySQLUser user : users)
userMap.put(user.getUserID(), user);
// Add user permissions // Construct permission from data
for(UserPermissionKey userPermission : userPermissions) { UserPermission permission = new UserPermission(
MySQLUser affectedUser = userMap.get(userPermission.getAffected_user_id()); UserPermission.Type.valueOf(userPermission.getPermission()),
UserPermission newPermission = new UserPermission( affectedUsers.get(userPermission.getUser_id())
UserPermission.Type.valueOf(userPermission.getPermission()), );
affectedUser.getUsername()
); // Add to set
allPermissions.add(newPermission); permissions.add(permission);
}
} }
// Secondly, connection permissions return permissions;
}
/**
* Retrieves all connection permissions granted to the user having the
* given ID.
*
* @param userID The ID of the user to retrieve permissions of.
* @return A set of all user permissions granted to the user having the
* given ID.
*/
public Set<ConnectionPermission> retrieveConnectionPermissions(int userID) {
// Set of all permissions
Set<ConnectionPermission> permissions = new HashSet<ConnectionPermission>();
// Query all connection permissions
ConnectionPermissionExample connectionPermissionExample = new ConnectionPermissionExample(); ConnectionPermissionExample connectionPermissionExample = new ConnectionPermissionExample();
connectionPermissionExample.createCriteria().andUser_idEqualTo(userID); connectionPermissionExample.createCriteria().andUser_idEqualTo(userID);
List<ConnectionPermissionKey> connectionPermissions = List<ConnectionPermissionKey> connectionPermissions =
connectionPermissionDAO.selectByExample(connectionPermissionExample); connectionPermissionDAO.selectByExample(connectionPermissionExample);
// If connection permissions present, add permissions // Get list of affected connection IDs
if (!connectionPermissions.isEmpty()) { List<Integer> connectionIDs = new ArrayList<Integer>();
for(ConnectionPermissionKey connectionPermission : connectionPermissions)
connectionIDs.add(connectionPermission.getConnection_id());
// Get list of affected connection IDs // Get corresponding names
List<Integer> affectedConnectionIDs = new ArrayList<Integer>(); Map<Integer, String> affectedUsers =
for(ConnectionPermissionKey connectionPermission : connectionPermissions) connectionService.retrieveNames(connectionIDs);
affectedConnectionIDs.add(connectionPermission.getConnection_id());
// Query connections, store in map indexed by connection ID // Add connection permissions
List<MySQLConnection> connections = for(ConnectionPermissionKey connectionPermission : connectionPermissions) {
connectionService.retrieveConnectionsByID(affectedConnectionIDs);
Map<Integer, MySQLConnection> connectionMap = new HashMap<Integer, MySQLConnection>();
for(MySQLConnection connection : connections)
connectionMap.put(connection.getConnectionID(), connection);
// Add connection permissions // Construct permission from data
for(ConnectionPermissionKey connectionPermission : connectionPermissions) { ConnectionPermission permission = new ConnectionPermission(
MySQLConnection affectedConnection = ConnectionPermission.Type.valueOf(connectionPermission.getPermission()),
connectionMap.get(connectionPermission.getConnection_id()); affectedUsers.get(connectionPermission.getUser_id())
ConnectionPermission newPermission = new ConnectionPermission( );
ConnectionPermission.Type.valueOf(connectionPermission.getPermission()),
affectedConnection.getIdentifier() // Add to set
); permissions.add(permission);
allPermissions.add(newPermission);
}
} }
return permissions;
}
/**
* Retrieves all permissions granted to the user having the given ID.
*
* @param userID The ID of the user to retrieve permissions of.
* @return A set of all permissions granted to the user having the given
* ID.
*/
public Set<Permission> retrieveAllPermissions(int userID) {
// Set which will contain all permissions
Set<Permission> allPermissions = new HashSet<Permission>();
// Add user permissions
allPermissions.addAll(retrieveUserPermissions(userID));
// Add connection permissions
allPermissions.addAll(retrieveConnectionPermissions(userID));
// TODO: Move to retrieveSystemPermissions()
// And finally, system permissions // And finally, system permissions
SystemPermissionExample systemPermissionExample = new SystemPermissionExample(); SystemPermissionExample systemPermissionExample = new SystemPermissionExample();
systemPermissionExample.createCriteria().andUser_idEqualTo(userID); systemPermissionExample.createCriteria().andUser_idEqualTo(userID);
@@ -841,4 +391,5 @@ public class PermissionCheckService {
return allPermissions; return allPermissions;
} }
} }

View File

@@ -39,9 +39,10 @@ package net.sourceforge.guacamole.net.auth.mysql.service;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import net.sourceforge.guacamole.GuacamoleException; import net.sourceforge.guacamole.GuacamoleException;
import net.sourceforge.guacamole.net.auth.Credentials; import net.sourceforge.guacamole.net.auth.Credentials;
import net.sourceforge.guacamole.net.auth.User; import net.sourceforge.guacamole.net.auth.User;
@@ -143,7 +144,7 @@ public class UserService {
user.getUser_id(), user.getUser_id(),
user.getUsername(), user.getUsername(),
null, null,
permissionCheckService.getAllPermissions(user.getUser_id()) permissionCheckService.retrieveAllPermissions(user.getUser_id())
); );
// Return new user // Return new user
@@ -171,60 +172,6 @@ public class UserService {
} }
/**
* Retrieves the users having the given IDs from the database.
*
* @param ids The IDs of the users to retrieve.
* @return A list of existing MySQLUser objects.
*/
public List<MySQLUser> retrieveUsersByID(List<Integer> ids) {
// If no IDs given, just return empty list
if (ids.isEmpty())
return Collections.EMPTY_LIST;
// Query users by ID
UserExample example = new UserExample();
example.createCriteria().andUser_idIn(ids);
List<UserWithBLOBs> users = userDAO.selectByExampleWithBLOBs(example);
// Convert to MySQLUser list
List<MySQLUser> mySQLUsers = new ArrayList<MySQLUser>(users.size());
for (UserWithBLOBs user : users)
mySQLUsers.add(toMySQLUser(user));
// Return found users
return mySQLUsers;
}
/**
* Retrieves the users having the given usernames from the database.
*
* @param names The usernames of the users to retrieve.
* @return A list of existing MySQLUser objects.
*/
public List<MySQLUser> retrieveUsersByUsername(List<String> names) {
// If no names given, just return empty list
if (names.isEmpty())
return Collections.EMPTY_LIST;
// Query users by ID
UserExample example = new UserExample();
example.createCriteria().andUsernameIn(names);
List<UserWithBLOBs> users = userDAO.selectByExampleWithBLOBs(example);
// Convert to MySQLUser list
List<MySQLUser> mySQLUsers = new ArrayList<MySQLUser>(users.size());
for (UserWithBLOBs user : users)
mySQLUsers.add(toMySQLUser(user));
// Return found users
return mySQLUsers;
}
/** /**
* Retrieves the user having the given username from the database. * Retrieves the user having the given username from the database.
* *
@@ -286,6 +233,66 @@ public class UserService {
} }
/**
* Retrieves a translation map of usernames to their corresponding IDs.
*
* @param ids The IDs of the users to retrieve the usernames of.
* @return A map containing the names of all users and their corresponding
* IDs.
*/
public Map<String, Integer> translateUsernames(List<Integer> ids) {
// If no IDs given, just return empty map
if (ids.isEmpty())
return Collections.EMPTY_MAP;
// Map of all names onto their corresponding IDs
Map<String, Integer> names = new HashMap<String, Integer>();
// Get all users having the given IDs
UserExample example = new UserExample();
example.createCriteria().andUser_idIn(ids);
List<net.sourceforge.guacamole.net.auth.mysql.model.User> users =
userDAO.selectByExample(example);
// Produce set of names
for (net.sourceforge.guacamole.net.auth.mysql.model.User user : users)
names.put(user.getUsername(), user.getUser_id());
return names;
}
/**
* Retrieves a map of all usernames for the given IDs.
*
* @param ids The IDs of the users to retrieve the usernames of.
* @return A map containing the names of all users and their corresponding
* IDs.
*/
public Map<Integer, String> retrieveUsernames(List<Integer> ids) {
// If no IDs given, just return empty map
if (ids.isEmpty())
return Collections.EMPTY_MAP;
// Map of all names onto their corresponding IDs
Map<Integer, String> names = new HashMap<Integer, String>();
// Get all users having the given IDs
UserExample example = new UserExample();
example.createCriteria().andUser_idIn(ids);
List<net.sourceforge.guacamole.net.auth.mysql.model.User> users =
userDAO.selectByExample(example);
// Produce set of names
for (net.sourceforge.guacamole.net.auth.mysql.model.User user : users)
names.put(user.getUser_id(), user.getUsername());
return names;
}
/** /**
* Creates a new user having the given username and password. * Creates a new user having the given username and password.
* *
@@ -315,21 +322,13 @@ public class UserService {
} }
/** /**
* Deletes the user having the given username from the database. * Deletes the user having the given ID from the database.
* @param username The username of the user to delete. * @param user_id The ID of the user to delete.
*/ */
public void deleteUser(String username) { public void deleteUser(int user_id) {
// Get specified user
MySQLUser mySQLUser = retrieveUser(username);
int user_id = mySQLUser.getUserID();
// Delete the user in the database
userDAO.deleteByPrimaryKey(user_id); userDAO.deleteByPrimaryKey(user_id);
} }
/** /**
* Updates the user in the database corresponding to the given MySQLUser. * Updates the user in the database corresponding to the given MySQLUser.
* *