From a03b76d9dda02849a26e90815ac312448fad39ef Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 19 Jul 2016 16:11:45 -0700 Subject: [PATCH] GUACAMOLE-5: Expose sharing profiles via a Directory on the UserContext according to granted permissions. --- .../JDBCAuthenticationProviderModule.java | 10 + .../SharingProfilePermissionService.java | 66 ++++ .../SharingProfilePermissionSet.java | 44 +++ .../sharingprofile/ModeledSharingProfile.java | 110 ++++++ .../SharingProfileDirectory.java | 85 +++++ .../sharingprofile/SharingProfileService.java | 328 ++++++++++++++++++ .../guacamole/auth/jdbc/user/UserContext.java | 16 +- 7 files changed, 655 insertions(+), 4 deletions(-) create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionService.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionSet.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/ModeledSharingProfile.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileDirectory.java create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileService.java diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java index 35b15affe..71d784a52 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCAuthenticationProviderModule.java @@ -60,8 +60,13 @@ import org.apache.guacamole.auth.jdbc.activeconnection.ActiveConnectionService; import org.apache.guacamole.auth.jdbc.activeconnection.TrackedActiveConnection; import org.apache.guacamole.auth.jdbc.connection.ConnectionParameterMapper; import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionMapper; +import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionService; +import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionSet; +import org.apache.guacamole.auth.jdbc.sharingprofile.ModeledSharingProfile; +import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileDirectory; import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileMapper; import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterMapper; +import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileService; import org.apache.guacamole.auth.jdbc.tunnel.RestrictedGuacamoleTunnelService; import org.apache.guacamole.net.auth.AuthenticationProvider; import org.mybatis.guice.MyBatisModule; @@ -141,8 +146,11 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule { bind(ModeledConnection.class); bind(ModeledConnectionGroup.class); bind(ModeledGuacamoleConfiguration.class); + bind(ModeledSharingProfile.class); bind(ModeledUser.class); bind(RootConnectionGroup.class); + bind(SharingProfileDirectory.class); + bind(SharingProfilePermissionSet.class); bind(SystemPermissionSet.class); bind(TrackedActiveConnection.class); bind(UserContext.class); @@ -159,6 +167,8 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule { bind(GuacamoleTunnelService.class).to(RestrictedGuacamoleTunnelService.class); bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class); bind(SaltService.class).to(SecureRandomSaltService.class); + bind(SharingProfilePermissionService.class); + bind(SharingProfileService.class); bind(SystemPermissionService.class); bind(UserPermissionService.class); bind(UserService.class); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionService.java new file mode 100644 index 000000000..7c12afd20 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionService.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.permission; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import org.apache.guacamole.auth.jdbc.user.AuthenticatedUser; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.auth.jdbc.user.ModeledUser; + +/** + * Service which provides convenience methods for creating, retrieving, and + * deleting sharing profile permissions. This service will automatically enforce + * the permissions of the current user. + * + * @author Michael Jumper + */ +public class SharingProfilePermissionService extends ModeledObjectPermissionService { + + /** + * Mapper for sharing profile permissions. + */ + @Inject + private SharingProfilePermissionMapper sharingProfilePermissionMapper; + + /** + * Provider for sharing profile permission sets. + */ + @Inject + private Provider sharingProfilePermissionSetProvider; + + @Override + protected ObjectPermissionMapper getPermissionMapper() { + return sharingProfilePermissionMapper; + } + + @Override + public ObjectPermissionSet getPermissionSet(AuthenticatedUser user, + ModeledUser targetUser) throws GuacamoleException { + + // Create permission set for requested user + ObjectPermissionSet permissionSet = sharingProfilePermissionSetProvider.get(); + permissionSet.init(user, targetUser); + + return permissionSet; + + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionSet.java new file mode 100644 index 000000000..77cb37e5d --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SharingProfilePermissionSet.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.permission; + +import com.google.inject.Inject; + +/** + * A database implementation of ObjectPermissionSet which uses an injected + * service to query and manipulate the sharing profile permissions associated + * with a particular user. + * + * @author Michael Jumper + */ +public class SharingProfilePermissionSet extends ObjectPermissionSet { + + /** + * Service for querying and manipulating sharing profile permissions. + */ + @Inject + private SharingProfilePermissionService sharingProfilePermissionService; + + @Override + protected ObjectPermissionService getObjectPermissionService() { + return sharingProfilePermissionService; + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/ModeledSharingProfile.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/ModeledSharingProfile.java new file mode 100644 index 000000000..318efedb4 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/ModeledSharingProfile.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.sharingprofile; + +import com.google.inject.Inject; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObject; +import org.apache.guacamole.form.Form; +import org.apache.guacamole.net.auth.SharingProfile; + +/** + * An implementation of the SharingProfile object which is backed by a database + * model. + * + * @author Michael Jumper + */ +public class ModeledSharingProfile + extends ModeledDirectoryObject + implements SharingProfile { + + /** + * All possible attributes of sharing profile objects organized as + * individual, logical forms. Currently, there are no such attributes. + */ + public static final Collection
ATTRIBUTES = Collections.emptyList(); + + /** + * The manually-set parameter map, if any. + */ + private Map parameters = null; + + /** + * Service for managing sharing profiles. + */ + @Inject + private SharingProfileService sharingProfileService; + + /** + * Creates a new, empty ModeledSharingProfile. + */ + public ModeledSharingProfile() { + } + + @Override + public String getName() { + return getModel().getName(); + } + + @Override + public void setName(String name) { + getModel().setName(name); + } + + @Override + public String getPrimaryConnectionIdentifier() { + return getModel().getPrimaryConnectionIdentifier(); + } + + @Override + public void setPrimaryConnectionIdentifier(String identifier) { + getModel().setPrimaryConnectionIdentifier(identifier); + } + + @Override + public Map getParameters() { + + // Retrieve visible parameters, if not overridden by setParameters() + if (parameters == null) + return sharingProfileService.retrieveParameters(getCurrentUser(), + getModel().getIdentifier()); + + return parameters; + + } + + @Override + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + @Override + public Map getAttributes() { + return Collections.emptyMap(); + } + + @Override + public void setAttributes(Map attributes) { + // Do nothing - no attributes + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileDirectory.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileDirectory.java new file mode 100644 index 000000000..65512748e --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileDirectory.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.sharingprofile; + +import com.google.inject.Inject; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.auth.jdbc.base.RestrictedObject; +import org.apache.guacamole.net.auth.Directory; +import org.apache.guacamole.net.auth.SharingProfile; +import org.mybatis.guice.transactional.Transactional; + +/** + * Implementation of the SharingProfile Directory which is driven by an + * underlying, arbitrary database. + * + * @author Michael Jumper + */ +public class SharingProfileDirectory extends RestrictedObject + implements Directory { + + /** + * Service for managing sharing profile objects. + */ + @Inject + private SharingProfileService sharingProfileService; + + @Override + public SharingProfile get(String identifier) throws GuacamoleException { + return sharingProfileService.retrieveObject(getCurrentUser(), identifier); + } + + @Override + @Transactional + public Collection getAll(Collection identifiers) throws GuacamoleException { + return Collections.unmodifiableCollection( + sharingProfileService.retrieveObjects(getCurrentUser(), identifiers) + ); + } + + @Override + @Transactional + public Set getIdentifiers() throws GuacamoleException { + return sharingProfileService.getIdentifiers(getCurrentUser()); + } + + @Override + @Transactional + public void add(SharingProfile object) throws GuacamoleException { + sharingProfileService.createObject(getCurrentUser(), object); + } + + @Override + @Transactional + public void update(SharingProfile object) throws GuacamoleException { + ModeledSharingProfile sharingProfile = (ModeledSharingProfile) object; + sharingProfileService.updateObject(getCurrentUser(), sharingProfile); + } + + @Override + @Transactional + public void remove(String identifier) throws GuacamoleException { + sharingProfileService.deleteObject(getCurrentUser(), identifier); + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileService.java new file mode 100644 index 000000000..11c70d23a --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileService.java @@ -0,0 +1,328 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.guacamole.auth.jdbc.sharingprofile; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.apache.guacamole.auth.jdbc.user.AuthenticatedUser; +import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper; +import org.apache.guacamole.GuacamoleClientException; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectService; +import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionMapper; +import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionMapper; +import org.apache.guacamole.net.auth.SharingProfile; +import org.apache.guacamole.net.auth.permission.ObjectPermission; +import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; +import org.apache.guacamole.net.auth.permission.SystemPermission; +import org.apache.guacamole.net.auth.permission.SystemPermissionSet; + +/** + * Service which provides convenience methods for creating, retrieving, and + * manipulating sharing profiles. + * + * @author Michael Jumper + */ +public class SharingProfileService + extends ModeledDirectoryObjectService { + + /** + * Mapper for accessing sharing profiles. + */ + @Inject + private SharingProfileMapper sharingProfileMapper; + + /** + * Mapper for manipulating sharing profile permissions. + */ + @Inject + private SharingProfilePermissionMapper sharingProfilePermissionMapper; + + /** + * Mapper for accessing sharing profile parameters. + */ + @Inject + private SharingProfileParameterMapper parameterMapper; + + /** + * Provider for creating sharing profiles. + */ + @Inject + private Provider sharingProfileProvider; + + @Override + protected ModeledDirectoryObjectMapper getObjectMapper() { + return sharingProfileMapper; + } + + @Override + protected ObjectPermissionMapper getPermissionMapper() { + return sharingProfilePermissionMapper; + } + + @Override + protected ModeledSharingProfile getObjectInstance(AuthenticatedUser currentUser, + SharingProfileModel model) { + ModeledSharingProfile sharingProfile = sharingProfileProvider.get(); + sharingProfile.init(currentUser, model); + return sharingProfile; + } + + @Override + protected SharingProfileModel getModelInstance(AuthenticatedUser currentUser, + final SharingProfile object) { + + // Create new ModeledSharingProfile backed by blank model + SharingProfileModel model = new SharingProfileModel(); + ModeledSharingProfile sharingProfile = getObjectInstance(currentUser, model); + + // Set model contents through ModeledSharingProfile, copying the + // provided sharing profile + sharingProfile.setPrimaryConnectionIdentifier(object.getPrimaryConnectionIdentifier()); + sharingProfile.setName(object.getName()); + sharingProfile.setParameters(object.getParameters()); + sharingProfile.setAttributes(object.getAttributes()); + + return model; + + } + + @Override + protected boolean hasCreatePermission(AuthenticatedUser user) + throws GuacamoleException { + + // Return whether user has explicit sharing profile creation permission + SystemPermissionSet permissionSet = user.getUser().getSystemPermissions(); + return permissionSet.hasPermission(SystemPermission.Type.CREATE_SHARING_PROFILE); + + } + + @Override + protected ObjectPermissionSet getPermissionSet(AuthenticatedUser user) + throws GuacamoleException { + + // Return permissions related to sharing profiles + return user.getUser().getSharingProfilePermissions(); + + } + + @Override + protected void beforeCreate(AuthenticatedUser user, + SharingProfileModel model) throws GuacamoleException { + + super.beforeCreate(user, model); + + // Name must not be blank + if (model.getName() == null || model.getName().trim().isEmpty()) + throw new GuacamoleClientException("Sharing profile names must not be blank."); + + // Do not attempt to create duplicate sharing profiles + SharingProfileModel existing = sharingProfileMapper.selectOneByName(model.getPrimaryConnectionIdentifier(), model.getName()); + if (existing != null) + throw new GuacamoleClientException("The sharing profile \"" + model.getName() + "\" already exists."); + + } + + @Override + protected void beforeUpdate(AuthenticatedUser user, + SharingProfileModel model) throws GuacamoleException { + + super.beforeUpdate(user, model); + + // Name must not be blank + if (model.getName() == null || model.getName().trim().isEmpty()) + throw new GuacamoleClientException("Sharing profile names must not be blank."); + + // Check whether such a sharing profile is already present + SharingProfileModel existing = sharingProfileMapper.selectOneByName(model.getPrimaryConnectionIdentifier(), model.getName()); + if (existing != null) { + + // If the specified name matches a DIFFERENT existing sharing profile, the update cannot continue + if (!existing.getObjectID().equals(model.getObjectID())) + throw new GuacamoleClientException("The sharing profile \"" + model.getName() + "\" already exists."); + + } + + } + + /** + * Given an arbitrary Guacamole sharing profile, produces a collection of + * parameter model objects containing the name/value pairs of that + * sharing profile's parameters. + * + * @param sharingProfile + * The sharing profile whose configuration should be used to produce the + * collection of parameter models. + * + * @return + * A collection of parameter models containing the name/value pairs + * of the given sharing profile's parameters. + */ + private Collection getParameterModels(ModeledSharingProfile sharingProfile) { + + Map parameters = sharingProfile.getParameters(); + + // Convert parameters to model objects + Collection parameterModels = new ArrayList(parameters.size()); + for (Map.Entry parameterEntry : parameters.entrySet()) { + + // Get parameter name and value + String name = parameterEntry.getKey(); + String value = parameterEntry.getValue(); + + // There is no need to insert empty parameters + if (value == null || value.isEmpty()) + continue; + + // Produce model object from parameter + SharingProfileParameterModel model = new SharingProfileParameterModel(); + model.setSharingProfileIdentifier(sharingProfile.getIdentifier()); + model.setName(name); + model.setValue(value); + + // Add model to list + parameterModels.add(model); + + } + + return parameterModels; + + } + + @Override + public ModeledSharingProfile createObject(AuthenticatedUser user, SharingProfile object) + throws GuacamoleException { + + // Create sharing profile + ModeledSharingProfile sharingProfile = super.createObject(user, object); + sharingProfile.setParameters(object.getParameters()); + + // Insert new parameters, if any + Collection parameterModels = getParameterModels(sharingProfile); + if (!parameterModels.isEmpty()) + parameterMapper.insert(parameterModels); + + return sharingProfile; + + } + + @Override + public void updateObject(AuthenticatedUser user, ModeledSharingProfile object) + throws GuacamoleException { + + // Update sharing profile + super.updateObject(user, object); + + // Replace existing parameters with new parameters, if any + Collection parameterModels = getParameterModels(object); + parameterMapper.delete(object.getIdentifier()); + if (!parameterModels.isEmpty()) + parameterMapper.insert(parameterModels); + + } + + /** + * Returns the set of all identifiers for all sharing profiles associated + * with the given primary connection. Only sharing profiles that the user + * has read access to will be returned. + * + * Permission to read the primary connection having the given identifier is + * NOT checked. + * + * @param user + * The user retrieving the identifiers. + * + * @param identifier + * The identifier of the primary connection. + * + * @return + * The set of all identifiers for all sharing profiles associated with + * the primary connection having the given identifier that the user has + * read access to. + * + * @throws GuacamoleException + * If an error occurs while reading identifiers. + */ + public Set getIdentifiersWithin(AuthenticatedUser user, + String identifier) + throws GuacamoleException { + + // Bypass permission checks if the user is a system admin + if (user.getUser().isAdministrator()) + return sharingProfileMapper.selectIdentifiersWithin(identifier); + + // Otherwise only return explicitly readable identifiers + else + return sharingProfileMapper.selectReadableIdentifiersWithin( + user.getUser().getModel(), identifier); + + } + + /** + * Retrieves all parameters visible to the given user and associated with + * the sharing profile having the given identifier. If the given user has no + * access to such parameters, or no such sharing profile exists, the + * returned map will be empty. + * + * @param user + * The user retrieving sharing profile parameters. + * + * @param identifier + * The identifier of the sharing profile whose parameters are being + * retrieved. + * + * @return + * A new map of all parameter name/value pairs that the given user has + * access to. + */ + public Map retrieveParameters(AuthenticatedUser user, + String identifier) { + + Map parameterMap = new HashMap(); + + // Determine whether we have permission to read parameters + boolean canRetrieveParameters; + try { + canRetrieveParameters = hasObjectPermission(user, identifier, + ObjectPermission.Type.UPDATE); + } + + // Provide empty (but mutable) map if unable to check permissions + catch (GuacamoleException e) { + return parameterMap; + } + + // Populate parameter map if we have permission to do so + if (canRetrieveParameters) { + for (SharingProfileParameterModel parameter : parameterMapper.select(identifier)) + parameterMap.put(parameter.getName(), parameter.getValue()); + } + + return parameterMap; + + } + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserContext.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserContext.java index 7cb52f07e..5ddea97ba 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserContext.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserContext.java @@ -26,13 +26,14 @@ import org.apache.guacamole.auth.jdbc.connection.ConnectionDirectory; import com.google.inject.Inject; import com.google.inject.Provider; import java.util.Collection; -import java.util.Collections; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.auth.jdbc.base.RestrictedObject; import org.apache.guacamole.auth.jdbc.activeconnection.ActiveConnectionDirectory; import org.apache.guacamole.auth.jdbc.connection.ConnectionRecordSet; import org.apache.guacamole.auth.jdbc.connection.ModeledConnection; import org.apache.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup; +import org.apache.guacamole.auth.jdbc.sharingprofile.ModeledSharingProfile; +import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileDirectory; import org.apache.guacamole.form.Form; import org.apache.guacamole.net.auth.ActiveConnection; import org.apache.guacamole.net.auth.AuthenticationProvider; @@ -41,7 +42,6 @@ import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.SharingProfile; import org.apache.guacamole.net.auth.User; -import org.apache.guacamole.net.auth.simple.SimpleDirectory; /** * UserContext implementation which is driven by an arbitrary, underlying @@ -80,6 +80,13 @@ public class UserContext extends RestrictedObject @Inject private ConnectionGroupDirectory connectionGroupDirectory; + /** + * Sharing profile directory restricted by the permissions of the user + * associated with this context. + */ + @Inject + private SharingProfileDirectory sharingProfileDirectory; + /** * ActiveConnection directory restricted by the permissions of the user * associated with this context. @@ -108,6 +115,7 @@ public class UserContext extends RestrictedObject userDirectory.init(currentUser); connectionDirectory.init(currentUser); connectionGroupDirectory.init(currentUser); + sharingProfileDirectory.init(currentUser); activeConnectionDirectory.init(currentUser); } @@ -140,7 +148,7 @@ public class UserContext extends RestrictedObject @Override public Directory getSharingProfileDirectory() throws GuacamoleException { - return new SimpleDirectory(); + return sharingProfileDirectory; } @Override @@ -184,7 +192,7 @@ public class UserContext extends RestrictedObject @Override public Collection getSharingProfileAttributes() { - return Collections.emptyList(); + return ModeledSharingProfile.ATTRIBUTES; } }