GUACAMOLE-926: Allow JDBC extensions to accept identifiers from user for update.

This commit is contained in:
James Muehlner
2023-01-24 01:23:55 +00:00
parent 9cdbe0fb36
commit e6bd12ee4c
14 changed files with 115 additions and 27 deletions

View File

@@ -166,6 +166,14 @@ public class ActiveConnectionService
}
@Override
public void updateExternalObject(ModeledAuthenticatedUser user, ActiveConnection object) throws GuacamoleException {
// Updating active connections is not implemented
throw new GuacamoleSecurityException("Permission denied.");
}
/**
* Retrieve the permission set for the specified user that relates
* to access to active connections.

View File

@@ -116,6 +116,24 @@ public interface DirectoryObjectService<InternalType, ExternalType> {
void deleteObject(ModeledAuthenticatedUser user, String identifier)
throws GuacamoleException;
/**
* Updates the object corresponding to the given external representation,
* applying any changes that have been made. If no such object exists,
* this function has no effect.
*
* @param user
* The user updating the object.
*
* @param object
* The external object to apply updates from.
*
* @throws GuacamoleException
* If the user lacks permission to update the object, or an error
* occurs while updating the object.
*/
void updateExternalObject(ModeledAuthenticatedUser user, ExternalType object)
throws GuacamoleException;
/**
* Updates the given object, applying any changes that have been made. If
* no such object exists, this function has no effect.

View File

@@ -511,6 +511,20 @@ public abstract class ModeledDirectoryObjectService<InternalType extends Modeled
}
@Override
@Transactional
public void updateExternalObject(ModeledAuthenticatedUser user, ExternalType object)
throws GuacamoleException {
// Convert to the internal type
InternalType internalObject = getObjectInstance(
user, getModelInstance(user, object));
// Delegate to the standard internal update functionality
updateObject(user, internalObject);
}
@Override
public Set<String> getIdentifiers(ModeledAuthenticatedUser user)
throws GuacamoleException {

View File

@@ -21,6 +21,8 @@ package org.apache.guacamole.auth.jdbc.base;
import java.util.Collection;
import org.apache.guacamole.GuacamoleException;
/**
* Object representation of a Guacamole object, such as a user or connection,
* as represented in the database.
@@ -75,7 +77,7 @@ public abstract class ObjectModel {
*
* @return
* The ID of this object in the database, or null if this object was
* not retrieved from the database.
* not retrieved from or intended to update the database.
*/
public Integer getObjectID() {
return objectID;
@@ -91,6 +93,31 @@ public abstract class ObjectModel {
this.objectID = objectID;
}
/**
* Given a text identifier, attempt to convert to an integer database ID.
* If the identifier is valid, the database ID will be set to this value.
* Otherwise, a GuacamoleException will be thrown.
*
* @param identifier
* The identifier to convert to an integer and set on the database
* model, if valid.
*
* @throws GuacamoleException
* If the provided identifier is not a valid integer.
*/
public void setObjectID(String identifier) throws GuacamoleException {
// Try to convert the provided identifier to an integer ID
try {
setObjectID(Integer.parseInt(identifier));
}
catch (NumberFormatException e) {
throw new GuacamoleException(
"Database identifiers must be integers.");
}
}
/**
* Returns a map of attribute name/value pairs for all attributes associated
* with this model which do not have explicit mappings to actual model

View File

@@ -71,16 +71,15 @@ public class ConnectionDirectory extends JDBCDirectory<Connection> {
// If the provided connection is already an internal type, update
// using the internal method
if (object instanceof ModeledConnection) {
ModeledConnection connection = (ModeledConnection) object;
connectionService.updateObject(getCurrentUser(), connection);
}
if (object instanceof ModeledConnection)
connectionService.updateObject(
getCurrentUser(), (ModeledConnection) object);
// If the type is not already the expected internal type, use the
// external update method
else {
else
connectionService.updateExternalObject(getCurrentUser(), object);
}
}
@Override

View File

@@ -387,9 +387,4 @@ public class ConnectionModel extends ChildObjectModel {
}
@Override
public void setIdentifier(String identifier) {
throw new UnsupportedOperationException("Connection identifiers are derived from IDs. They cannot be set.");
}
}

View File

@@ -110,14 +110,19 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
@Override
protected ConnectionModel getModelInstance(ModeledAuthenticatedUser currentUser,
final Connection object) {
final Connection object) throws GuacamoleException {
// Create new ModeledConnection backed by blank model
ConnectionModel model = new ConnectionModel();
ModeledConnection connection = getObjectInstance(currentUser, model);
// If the provided connection has an identifier, set it on the model
if (object.getIdentifier() != null)
model.setObjectID(object.getIdentifier());
// Set model contents through ModeledConnection, copying the provided connection
connection.setParentIdentifier(object.getParentIdentifier());
connection.setIdentifier(object.getIdentifier());
connection.setName(object.getName());
connection.setConfiguration(object.getConfiguration());
connection.setAttributes(object.getAttributes());

View File

@@ -266,10 +266,4 @@ public class ConnectionGroupModel extends ChildObjectModel {
return id.toString();
}
@Override
public void setIdentifier(String identifier) {
throw new UnsupportedOperationException("Connection group identifiers are derived from IDs. They cannot be set.");
}
}

View File

@@ -92,14 +92,19 @@ public class ConnectionGroupService extends ModeledChildDirectoryObjectService<M
@Override
protected ConnectionGroupModel getModelInstance(ModeledAuthenticatedUser currentUser,
final ConnectionGroup object) {
final ConnectionGroup object) throws GuacamoleException {
// Create new ModeledConnectionGroup backed by blank model
ConnectionGroupModel model = new ConnectionGroupModel();
ModeledConnectionGroup connectionGroup = getObjectInstance(currentUser, model);
// If the provided connection has an identifier, set it on the model
if (object.getIdentifier() != null)
model.setObjectID(object.getIdentifier());
// Set model contents through ModeledConnectionGroup, copying the provided connection group
connectionGroup.setParentIdentifier(object.getParentIdentifier());
connectionGroup.setIdentifier(object.getIdentifier());
connectionGroup.setName(object.getName());
connectionGroup.setType(object.getType());
connectionGroup.setAttributes(object.getAttributes());

View File

@@ -71,10 +71,4 @@ public class SharingProfileModel extends ChildObjectModel {
}
@Override
public void setIdentifier(String identifier) {
throw new UnsupportedOperationException("Sharing profile identifiers "
+ "are derived from IDs. They cannot be set.");
}
}

View File

@@ -90,15 +90,20 @@ public class SharingProfileService
@Override
protected SharingProfileModel getModelInstance(ModeledAuthenticatedUser currentUser,
final SharingProfile object) {
final SharingProfile object) throws GuacamoleException {
// Create new ModeledSharingProfile backed by blank model
SharingProfileModel model = new SharingProfileModel();
ModeledSharingProfile sharingProfile = getObjectInstance(currentUser, model);
// If the provided connection has an identifier, set it on the model
if (object.getIdentifier() != null)
model.setObjectID(object.getIdentifier());
// Set model contents through ModeledSharingProfile, copying the
// provided sharing profile
sharingProfile.setPrimaryConnectionIdentifier(object.getPrimaryConnectionIdentifier());
sharingProfile.setIdentifier(object.getIdentifier());
sharingProfile.setName(object.getName());
sharingProfile.setParameters(object.getParameters());
sharingProfile.setAttributes(object.getAttributes());

View File

@@ -202,6 +202,10 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
UserModel model = new UserModel();
ModeledUser user = getObjectInstance(currentUser, model);
// If the provided connection has an identifier, set it on the model
if (object.getIdentifier() != null)
model.setObjectID(object.getIdentifier());
// Set model contents through ModeledUser, copying the provided user
user.setIdentifier(object.getIdentifier());
user.setPassword(object.getPassword());

View File

@@ -107,6 +107,10 @@ public class UserGroupService extends ModeledDirectoryObjectService<ModeledUserG
UserGroupModel model = new UserGroupModel();
ModeledUserGroup group = getObjectInstance(currentUser, model);
// If the provided connection has an identifier, set it on the model
if (object.getIdentifier() != null)
model.setObjectID(object.getIdentifier());
// Set model contents through ModeledUser, copying the provided group
group.setIdentifier(object.getIdentifier());
group.setAttributes(object.getAttributes());