diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml
index 3b1cae511..a3b7f92fd 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/pom.xml
@@ -109,33 +109,33 @@
org.mybatis
mybatis
- 3.2.8
+ 3.4.6
org.mybatis
mybatis-guice
- 3.6
+ 3.10
com.google.inject
guice
- 3.0
+ 4.1.0
com.google.inject.extensions
guice-multibindings
- 3.0
+ 4.1.0
com.google.guava
guava
- 18.0
+ 19.0
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 0f72559e2..5203cfee7 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
@@ -59,10 +59,15 @@ import org.apache.guacamole.auth.jdbc.activeconnection.ActiveConnectionPermissio
import org.apache.guacamole.auth.jdbc.activeconnection.ActiveConnectionPermissionSet;
import org.apache.guacamole.auth.jdbc.activeconnection.ActiveConnectionService;
import org.apache.guacamole.auth.jdbc.activeconnection.TrackedActiveConnection;
+import org.apache.guacamole.auth.jdbc.base.EntityMapper;
+import org.apache.guacamole.auth.jdbc.base.EntityService;
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.permission.UserGroupPermissionMapper;
+import org.apache.guacamole.auth.jdbc.permission.UserGroupPermissionService;
+import org.apache.guacamole.auth.jdbc.permission.UserGroupPermissionSet;
import org.apache.guacamole.auth.jdbc.security.PasswordPolicyService;
import org.apache.guacamole.auth.jdbc.sharing.ConnectionSharingService;
import org.apache.guacamole.auth.jdbc.sharing.HashSharedConnectionMap;
@@ -77,8 +82,16 @@ import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileService;
import org.apache.guacamole.auth.jdbc.tunnel.RestrictedGuacamoleTunnelService;
import org.apache.guacamole.auth.jdbc.user.PasswordRecordMapper;
import org.apache.guacamole.auth.jdbc.user.UserRecordMapper;
+import org.apache.guacamole.auth.jdbc.usergroup.ModeledUserGroup;
+import org.apache.guacamole.auth.jdbc.usergroup.UserGroupDirectory;
+import org.apache.guacamole.auth.jdbc.usergroup.UserGroupMapper;
+import org.apache.guacamole.auth.jdbc.usergroup.UserGroupMemberUserGroupMapper;
+import org.apache.guacamole.auth.jdbc.usergroup.UserGroupMemberUserMapper;
+import org.apache.guacamole.auth.jdbc.usergroup.UserGroupParentUserGroupMapper;
+import org.apache.guacamole.auth.jdbc.usergroup.UserGroupService;
import org.mybatis.guice.MyBatisModule;
import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider;
+import org.apache.guacamole.auth.jdbc.user.UserParentUserGroupMapper;
/**
* Guice module which configures the injections used by the JDBC authentication
@@ -120,12 +133,19 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule {
addMapperClass(ConnectionPermissionMapper.class);
addMapperClass(ConnectionRecordMapper.class);
addMapperClass(ConnectionParameterMapper.class);
+ addMapperClass(EntityMapper.class);
addMapperClass(PasswordRecordMapper.class);
addMapperClass(SystemPermissionMapper.class);
addMapperClass(SharingProfileMapper.class);
addMapperClass(SharingProfileParameterMapper.class);
addMapperClass(SharingProfilePermissionMapper.class);
+ addMapperClass(UserGroupMapper.class);
+ addMapperClass(UserGroupMemberUserGroupMapper.class);
+ addMapperClass(UserGroupMemberUserMapper.class);
+ addMapperClass(UserGroupParentUserGroupMapper.class);
+ addMapperClass(UserGroupPermissionMapper.class);
addMapperClass(UserMapper.class);
+ addMapperClass(UserParentUserGroupMapper.class);
addMapperClass(UserPermissionMapper.class);
addMapperClass(UserRecordMapper.class);
@@ -143,12 +163,15 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule {
bind(ModeledSharingProfile.class);
bind(ModeledUser.class);
bind(ModeledUserContext.class);
+ bind(ModeledUserGroup.class);
bind(RootConnectionGroup.class);
bind(SharingProfileDirectory.class);
bind(SharingProfilePermissionSet.class);
bind(SystemPermissionSet.class);
bind(TrackedActiveConnection.class);
bind(UserDirectory.class);
+ bind(UserGroupDirectory.class);
+ bind(UserGroupPermissionSet.class);
bind(UserPermissionSet.class);
// Bind services
@@ -159,6 +182,7 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule {
bind(ConnectionPermissionService.class);
bind(ConnectionSharingService.class);
bind(ConnectionService.class);
+ bind(EntityService.class);
bind(GuacamoleTunnelService.class).to(RestrictedGuacamoleTunnelService.class);
bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class);
bind(PasswordPolicyService.class);
@@ -168,6 +192,8 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule {
bind(SharingProfilePermissionService.class);
bind(SharingProfileService.class);
bind(SystemPermissionService.class);
+ bind(UserGroupService.class);
+ bind(UserGroupPermissionService.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/JDBCEnvironment.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
index 53935e62f..9158afb85 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/JDBCEnvironment.java
@@ -22,6 +22,7 @@ package org.apache.guacamole.auth.jdbc;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.environment.LocalEnvironment;
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
+import org.apache.ibatis.session.SqlSession;
/**
* A JDBC-specific implementation of Environment that defines generic properties
@@ -137,4 +138,18 @@ public abstract class JDBCEnvironment extends LocalEnvironment {
*/
public abstract PasswordPolicy getPasswordPolicy();
+ /**
+ * Returns whether the database supports recursive queries. Many database
+ * engines support recursive queries through CTEs. If recursive queries are
+ * not supported, queries that are intended to be recursive may need to be
+ * invoked multiple times to retrieve the same data.
+ *
+ * @param session
+ * The SqlSession provided by MyBatis for the current transaction.
+ *
+ * @return
+ * true if the database supports recursive queries, false otherwise.
+ */
+ public abstract boolean isRecursiveQuerySupported(SqlSession session);
+
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java
index 91ad11d7e..e7cbd5db5 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/activeconnection/ActiveConnectionPermissionService.java
@@ -23,17 +23,17 @@ import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
import org.apache.guacamole.auth.jdbc.permission.AbstractPermissionService;
import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionService;
import org.apache.guacamole.auth.jdbc.tunnel.ActiveConnectionRecord;
import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
import org.apache.guacamole.net.auth.permission.ObjectPermission;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
@@ -58,32 +58,32 @@ public class ActiveConnectionPermissionService
private Provider activeConnectionPermissionSetProvider;
@Override
- public ObjectPermission retrievePermission(ModeledAuthenticatedUser user,
- ModeledUser targetUser, ObjectPermission.Type type,
- String identifier) throws GuacamoleException {
+ public boolean hasPermission(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
+ ObjectPermission.Type type, String identifier,
+ Set effectiveGroups) throws GuacamoleException {
// Retrieve permissions
- Set permissions = retrievePermissions(user, targetUser);
+ Set permissions = retrievePermissions(user,
+ targetEntity, effectiveGroups);
- // If retrieved permissions contains the requested permission, return it
+ // Permission is granted if retrieved permissions contains the
+ // requested permission
ObjectPermission permission = new ObjectPermission(type, identifier);
- if (permissions.contains(permission))
- return permission;
-
- // Otherwise, no such permission
- return null;
+ return permissions.contains(permission);
}
@Override
public Set retrievePermissions(ModeledAuthenticatedUser user,
- ModeledUser targetUser) throws GuacamoleException {
+ ModeledPermissions extends EntityModel> targetEntity,
+ Set effectiveGroups) throws GuacamoleException {
// Retrieve permissions only if allowed
- if (canReadPermissions(user, targetUser)) {
+ if (canReadPermissions(user, targetEntity)) {
// Only administrators may access active connections
- boolean isAdmin = targetUser.isAdministrator();
+ boolean isAdmin = targetEntity.isAdministrator();
// Get all active connections
Collection records = tunnelService.getActiveConnections(user);
@@ -112,10 +112,12 @@ public class ActiveConnectionPermissionService
@Override
public Collection retrieveAccessibleIdentifiers(ModeledAuthenticatedUser user,
- ModeledUser targetUser, Collection permissionTypes,
- Collection identifiers) throws GuacamoleException {
+ ModeledPermissions extends EntityModel> targetEntity,
+ Collection permissionTypes,
+ Collection identifiers, Set effectiveGroups)
+ throws GuacamoleException {
- Set permissions = retrievePermissions(user, targetUser);
+ Set permissions = retrievePermissions(user, targetEntity, effectiveGroups);
Collection accessibleObjects = new ArrayList(permissions.size());
// For each identifier/permission combination
@@ -138,11 +140,12 @@ public class ActiveConnectionPermissionService
@Override
public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
- ModeledUser targetUser) throws GuacamoleException {
+ ModeledPermissions extends EntityModel> targetEntity,
+ Set effectiveGroups) throws GuacamoleException {
- // Create permission set for requested user
+ // Create permission set for requested entity
ActiveConnectionPermissionSet permissionSet = activeConnectionPermissionSetProvider.get();
- permissionSet.init(user, targetUser);
+ permissionSet.init(user, targetEntity, effectiveGroups);
return permissionSet;
@@ -150,7 +153,8 @@ public class ActiveConnectionPermissionService
@Override
public void createPermissions(ModeledAuthenticatedUser user,
- ModeledUser targetUser, Collection permissions)
+ ModeledPermissions extends EntityModel> targetEntity,
+ Collection permissions)
throws GuacamoleException {
// Creating active connection permissions is not implemented
@@ -160,7 +164,8 @@ public class ActiveConnectionPermissionService
@Override
public void deletePermissions(ModeledAuthenticatedUser user,
- ModeledUser targetUser, Collection permissions)
+ ModeledPermissions extends EntityModel> targetEntity,
+ Collection permissions)
throws GuacamoleException {
// Deleting active connection permissions is not implemented
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityMapper.java
new file mode 100644
index 000000000..dbe7cb4d0
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityMapper.java
@@ -0,0 +1,80 @@
+/*
+ * 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.base;
+
+import java.util.Collection;
+import java.util.Set;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * Mapper for entities. An entity is the base concept behind a user or user
+ * group, and serves as a common point for granting permissions and defining
+ * group membership.
+ */
+public interface EntityMapper {
+
+ /**
+ * Inserts the given entity into the database. If the entity already
+ * exists, this will result in an error.
+ *
+ * @param entity
+ * The entity to insert.
+ *
+ * @return
+ * The number of rows inserted.
+ */
+ int insert(@Param("entity") EntityModel entity);
+
+ /**
+ * Returns the set of all group identifiers of which the given entity is a
+ * member, taking into account the given collection of known group
+ * memberships which are not necessarily defined within the database.
+ *
+ * NOTE: This query is expected to handle recursion through the membership
+ * graph on its own. If the database engine does not support recursive
+ * queries (isRecursiveQuerySupported() of JDBCEnvironment returns false),
+ * then this query will only return one level of depth past the effective
+ * groups given and will need to be invoked multiple times.
+ *
+ * @param entity
+ * The entity whose effective groups should be returned.
+ *
+ * @param effectiveGroups
+ * The identifiers of any known effective groups that should be taken
+ * into account, such as those defined externally to the database.
+ *
+ * @param recursive
+ * Whether the query should leverage database engine features to return
+ * absolutely all effective groups, including those inherited through
+ * group membership. If false, this query will return only one level of
+ * depth and may need to be executed multiple times. If it is known
+ * that the database engine in question will always support (or always
+ * not support) recursive queries, this parameter may be ignored.
+ *
+ * @return
+ * The set of identifiers of all groups that the given entity is a
+ * member of, including those where membership is inherited through
+ * membership in other groups.
+ */
+ Set selectEffectiveGroupIdentifiers(@Param("entity") EntityModel entity,
+ @Param("effectiveGroups") Collection effectiveGroups,
+ @Param("recursive") boolean recursive);
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityModel.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityModel.java
new file mode 100644
index 000000000..c42db16b9
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityModel.java
@@ -0,0 +1,113 @@
+/*
+ * 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.base;
+
+/**
+ * Base representation of a Guacamole object that can be granted permissions
+ * (an "entity"), such as a user or user group, as represented in the database.
+ * Each entity has three base properties:
+ *
+ * 1. The "entityID", which points to the common entry in the
+ * guacamole_entity table and is common to any type of entity.
+ *
+ * 2. The "objectID", which points to the type-specific entry for the object
+ * in question (ie: an entry in guacamole_user or guacamole_user_group).
+ *
+ * 3. The "identifier", which contains the unique "name" value defined for
+ * the entity within the guacamole_entity table.
+ */
+public abstract class EntityModel extends ObjectModel {
+
+ /**
+ * The ID of the entity entry which corresponds to this object in the
+ * database, if any. Note that this is distinct from the objectID,
+ * inherited from ObjectModel, which is specific to the actual type of
+ * object represented by the entity.
+ */
+ private Integer entityID;
+
+ /**
+ * The type of object represented by the entity (user or user group).
+ */
+ private EntityType type;
+
+ /**
+ * Creates a new, empty entity.
+ */
+ public EntityModel() {
+ }
+
+ /**
+ * Creates a new entity of the given type which is otherwise empty.
+ *
+ * @param type
+ * The type to assign to the new entity.
+ */
+ public EntityModel(EntityType type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the ID of the entity entry which corresponds to this object in
+ * the database, if it exists. Note that this is distinct from the objectID,
+ * inherited from ObjectModel, which is specific to the actual type of
+ * object represented by the entity.
+ *
+ * @return
+ * The ID of this entity in the database, or null if this entity was
+ * not retrieved from the database.
+ */
+ public Integer getEntityID() {
+ return entityID;
+ }
+
+ /**
+ * Sets the ID of this entity to the given value.
+ *
+ * @param entityID
+ * The ID to assign to this entity.
+ */
+ public void setEntityID(Integer entityID) {
+ this.entityID = entityID;
+ }
+
+ /**
+ * Returns the type of object represented by the entity. Each entity may be
+ * either a user or a user group.
+ *
+ * @return
+ * The type of object represented by the entity.
+ */
+ public EntityType getEntityType() {
+ return type;
+ }
+
+ /**
+ * Sets the type of object represented by the entity. Each entity may be
+ * either a user or a user group.
+ *
+ * @param type
+ * The type of object represented by the entity.
+ */
+ public void setEntityType(EntityType type) {
+ this.type = type;
+ }
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityService.java
new file mode 100644
index 000000000..cc2a9aaf9
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityService.java
@@ -0,0 +1,98 @@
+/*
+ * 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.base;
+
+import com.google.inject.Inject;
+import java.util.Collection;
+import java.util.Set;
+import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
+import org.apache.ibatis.session.SqlSession;
+import org.mybatis.guice.transactional.Transactional;
+
+/**
+ * Service which provides convenience methods for creating, retrieving, and
+ * manipulating entities.
+ */
+public class EntityService {
+
+ /**
+ * The Guacamole server environment.
+ */
+ @Inject
+ private JDBCEnvironment environment;
+
+ /**
+ * Mapper for Entity model objects.
+ */
+ @Inject
+ private EntityMapper entityMapper;
+
+ /**
+ * The current SQL session used by MyBatis.
+ */
+ @Inject
+ private SqlSession sqlSession;
+
+ /**
+ * Returns the set of all group identifiers of which the given entity is a
+ * member, taking into account the given collection of known group
+ * memberships which are not necessarily defined within the database.
+ *
+ * Note that group visibility with respect to the queried entity is NOT
+ * taken into account. If the entity is a member of a group, the identifier
+ * of that group will be included in the returned set even if the current
+ * user lacks "READ" permission for that group.
+ *
+ * @param entity
+ * The entity whose effective groups should be returned.
+ *
+ * @param effectiveGroups
+ * The identifiers of any known effective groups that should be taken
+ * into account, such as those defined externally to the database.
+ *
+ * @return
+ * The set of identifiers of all groups that the given entity is a
+ * member of, including those where membership is inherited through
+ * membership in other groups.
+ */
+ @Transactional
+ public Set retrieveEffectiveGroups(ModeledPermissions extends EntityModel> entity,
+ Collection effectiveGroups) {
+
+ // Retrieve the effective user groups of the given entity, recursively if possible
+ boolean recursive = environment.isRecursiveQuerySupported(sqlSession);
+ Set identifiers = entityMapper.selectEffectiveGroupIdentifiers(entity.getModel(), effectiveGroups, recursive);
+
+ // If the set of user groups retrieved was not produced recursively,
+ // manually repeat the query to expand the set until all effective
+ // groups have been found
+ if (!recursive && !identifiers.isEmpty()) {
+ Set previousIdentifiers;
+ do {
+ previousIdentifiers = identifiers;
+ identifiers = entityMapper.selectEffectiveGroupIdentifiers(entity.getModel(), previousIdentifiers, false);
+ } while (identifiers.size() > previousIdentifiers.size());
+ }
+
+ return identifiers;
+
+ }
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityType.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityType.java
new file mode 100644
index 000000000..9b1f1edc9
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/EntityType.java
@@ -0,0 +1,38 @@
+/*
+ * 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.base;
+
+/**
+ * The type of object represented by an entity. Each entity may represent
+ * either a user or a user group.
+ */
+public enum EntityType {
+
+ /**
+ * An individual user.
+ */
+ USER,
+
+ /**
+ * A group of users and/or other groups.
+ */
+ USER_GROUP
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObjectService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObjectService.java
index 74ca5bb34..f517e2788 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObjectService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObjectService.java
@@ -53,7 +53,8 @@ public abstract class ModeledChildDirectoryObjectService modifiedParents = getModifiedParents(user, identifier, model);
if (!modifiedParents.isEmpty()) {
- ObjectPermissionSet permissionSet = getParentPermissionSet(user);
+ ObjectPermissionSet permissionSet = getParentEffectivePermissionSet(user);
Collection updateableParents = permissionSet.getAccessibleObjects(
Collections.singleton(ObjectPermission.Type.UPDATE),
modifiedParents
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
index 4431e8f42..8ff0cc1c7 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
@@ -57,10 +57,15 @@ public interface ModeledDirectoryObjectMapper {
* The user whose permissions should determine whether an identifier
* is returned.
*
+ * @param effectiveGroups
+ * The identifiers of any known effective groups that should be taken
+ * into account, such as those defined externally to the database.
+ *
* @return
* A Set containing all identifiers of all readable objects.
*/
- Set selectReadableIdentifiers(@Param("user") UserModel user);
+ Set selectReadableIdentifiers(@Param("user") UserModel user,
+ @Param("effectiveGroups") Collection effectiveGroups);
/**
* Selects all objects which have the given identifiers. If an identifier
@@ -91,11 +96,16 @@ public interface ModeledDirectoryObjectMapper {
* @param identifiers
* The identifiers of the objects to return.
*
+ * @param effectiveGroups
+ * The identifiers of any known effective groups that should be taken
+ * into account, such as those defined externally to the database.
+ *
* @return
* A Collection of all objects having the given identifiers.
*/
Collection selectReadable(@Param("user") UserModel user,
- @Param("identifiers") Collection identifiers);
+ @Param("identifiers") Collection identifiers,
+ @Param("effectiveGroups") Collection effectiveGroups);
/**
* Inserts the given object into the database. If the object already
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
index 21508c471..edbb67e3e 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
@@ -126,7 +126,8 @@ public abstract class ModeledDirectoryObjectService
+ * The type of model object that corresponds to this object.
+ */
+public abstract class ModeledPermissions
+ extends ModeledDirectoryObject implements Permissions {
+
+ /**
+ * Service for retrieving entity details.
+ */
+ @Inject
+ private EntityService entityService;
+
+ /**
+ * Service for retrieving system permissions.
+ */
+ @Inject
+ private SystemPermissionService systemPermissionService;
+
+ /**
+ * Service for retrieving connection permissions.
+ */
+ @Inject
+ private ConnectionPermissionService connectionPermissionService;
+
+ /**
+ * Service for retrieving connection group permissions.
+ */
+ @Inject
+ private ConnectionGroupPermissionService connectionGroupPermissionService;
+
+ /**
+ * Service for retrieving sharing profile permissions.
+ */
+ @Inject
+ private SharingProfilePermissionService sharingProfilePermissionService;
+
+ /**
+ * Service for retrieving active connection permissions.
+ */
+ @Inject
+ private ActiveConnectionPermissionService activeConnectionPermissionService;
+
+ /**
+ * Service for retrieving user permissions.
+ */
+ @Inject
+ private UserPermissionService userPermissionService;
+
+ /**
+ * Service for retrieving user group permissions.
+ */
+ @Inject
+ private UserGroupPermissionService userGroupPermissionService;
+
+ /**
+ * Returns whether the underlying entity is a user. Entities may be either
+ * users or user groups.
+ *
+ * @return
+ * true if the underlying entity is a user, false otherwise.
+ */
+ public boolean isUser() {
+ return getModel().getEntityType() == EntityType.USER;
+ }
+
+ /**
+ * Returns whether the underlying entity is a user group. Entities may be
+ * either users or user groups.
+ *
+ * @return
+ * true if the underlying entity is a user group, false otherwise.
+ */
+ public boolean isUserGroup() {
+ return getModel().getEntityType() == EntityType.USER_GROUP;
+ }
+
+ /**
+ * Returns whether this entity is a system administrator, and thus is not
+ * restricted by permissions, taking into account permission inheritance
+ * via user groups.
+ *
+ * @return
+ * true if this entity is a system administrator, false otherwise.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while determining the entity's system administrator
+ * status.
+ */
+ public boolean isAdministrator() throws GuacamoleException {
+ SystemPermissionSet systemPermissionSet = getEffective().getSystemPermissions();
+ return systemPermissionSet.hasPermission(SystemPermission.Type.ADMINISTER);
+ }
+
+ @Override
+ public SystemPermissionSet getSystemPermissions()
+ throws GuacamoleException {
+ return systemPermissionService.getPermissionSet(getCurrentUser(), this,
+ Collections.emptySet());
+ }
+
+ @Override
+ public ObjectPermissionSet getConnectionPermissions()
+ throws GuacamoleException {
+ return connectionPermissionService.getPermissionSet(getCurrentUser(),
+ this, Collections.emptySet());
+ }
+
+ @Override
+ public ObjectPermissionSet getConnectionGroupPermissions()
+ throws GuacamoleException {
+ return connectionGroupPermissionService.getPermissionSet(
+ getCurrentUser(), this, Collections.emptySet());
+ }
+
+ @Override
+ public ObjectPermissionSet getSharingProfilePermissions()
+ throws GuacamoleException {
+ return sharingProfilePermissionService.getPermissionSet(
+ getCurrentUser(), this, Collections.emptySet());
+ }
+
+ @Override
+ public ObjectPermissionSet getActiveConnectionPermissions()
+ throws GuacamoleException {
+ return activeConnectionPermissionService.getPermissionSet(
+ getCurrentUser(), this, Collections.emptySet());
+ }
+
+ @Override
+ public ObjectPermissionSet getUserPermissions()
+ throws GuacamoleException {
+ return userPermissionService.getPermissionSet(getCurrentUser(), this,
+ Collections.emptySet());
+ }
+
+ @Override
+ public ObjectPermissionSet getUserGroupPermissions() throws GuacamoleException {
+ return userGroupPermissionService.getPermissionSet(getCurrentUser(),
+ this, Collections.emptySet());
+ }
+
+ /**
+ * Returns the identifiers of all user groups defined within the database
+ * which apply to this user, including any groups inherited through
+ * membership in yet more groups.
+ *
+ * @return
+ * The identifiers of all user groups defined within the database which
+ * apply to this user.
+ */
+ public Set getEffectiveUserGroups() {
+ return entityService.retrieveEffectiveGroups(this,
+ Collections.emptySet());
+ }
+
+ /**
+ * Returns a Permissions object which represents all permissions granted to
+ * this entity, including any permissions inherited through group
+ * membership.
+ *
+ * @return
+ * A Permissions object which represents all permissions granted to
+ * this entity.
+ */
+ public Permissions getEffective() {
+
+ final ModeledAuthenticatedUser authenticatedUser = getCurrentUser();
+ final Set effectiveGroups;
+
+ // If this user is the currently-authenticated user, include any
+ // additional effective groups declared by the authentication system
+ if (authenticatedUser.getIdentifier().equals(getIdentifier()))
+ effectiveGroups = entityService.retrieveEffectiveGroups(this,
+ authenticatedUser.getEffectiveUserGroups());
+
+ // Otherwise, just include effective groups from the database
+ else
+ effectiveGroups = getEffectiveUserGroups();
+
+ // Return a permissions object which describes all effective
+ // permissions, including any permissions inherited via user groups
+ return new Permissions() {
+
+ @Override
+ public ObjectPermissionSet getActiveConnectionPermissions()
+ throws GuacamoleException {
+ return activeConnectionPermissionService.getPermissionSet(authenticatedUser, ModeledPermissions.this, effectiveGroups);
+ }
+
+ @Override
+ public ObjectPermissionSet getConnectionGroupPermissions()
+ throws GuacamoleException {
+ return connectionGroupPermissionService.getPermissionSet(authenticatedUser, ModeledPermissions.this, effectiveGroups);
+ }
+
+ @Override
+ public ObjectPermissionSet getConnectionPermissions()
+ throws GuacamoleException {
+ return connectionPermissionService.getPermissionSet(authenticatedUser, ModeledPermissions.this, effectiveGroups);
+ }
+
+ @Override
+ public ObjectPermissionSet getSharingProfilePermissions()
+ throws GuacamoleException {
+ return sharingProfilePermissionService.getPermissionSet(authenticatedUser, ModeledPermissions.this, effectiveGroups);
+ }
+
+ @Override
+ public SystemPermissionSet getSystemPermissions()
+ throws GuacamoleException {
+ return systemPermissionService.getPermissionSet(authenticatedUser, ModeledPermissions.this, effectiveGroups);
+ }
+
+ @Override
+ public ObjectPermissionSet getUserPermissions()
+ throws GuacamoleException {
+ return userPermissionService.getPermissionSet(authenticatedUser, ModeledPermissions.this, effectiveGroups);
+ }
+
+ @Override
+ public ObjectPermissionSet getUserGroupPermissions()
+ throws GuacamoleException {
+ return userGroupPermissionService.getPermissionSet(getCurrentUser(), ModeledPermissions.this, effectiveGroups);
+ }
+
+ };
+ }
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectRelationMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectRelationMapper.java
new file mode 100644
index 000000000..c2763ecc8
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectRelationMapper.java
@@ -0,0 +1,126 @@
+/*
+ * 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.base;
+
+import java.util.Collection;
+import java.util.Set;
+import org.apache.guacamole.auth.jdbc.user.UserModel;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * Mapper for the relations represented by a particular RelatedObjectSet
+ * implementation.
+ *
+ * @param
+ * The underlying database model of the object on the parent side of the
+ * one-to-many relationship represented by the RelatedObjectSet mapped by
+ * this ObjectRelationMapper.
+ */
+public interface ObjectRelationMapper {
+
+ /**
+ * Inserts rows as necessary to establish the one-to-many relationship
+ * represented by the RelatedObjectSet between the given parent and
+ * children. If the relation for any parent/child pair is already present,
+ * no attempt is made to insert a new row for that relation.
+ *
+ * @param parent
+ * The model of the object on the parent side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @param children
+ * The identifiers of the objects on the child side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @return
+ * The number of rows inserted.
+ */
+ int insert(@Param("parent") ParentModelType parent,
+ @Param("children") Collection children);
+
+ /**
+ * Deletes rows as necessary to modify the one-to-many relationship
+ * represented by the RelatedObjectSet between the given parent and
+ * children. If the relation for any parent/child pair does not exist,
+ * that specific relation is ignored, and deletion proceeds with the
+ * remaining relations.
+ *
+ * @param parent
+ * The model of the object on the parent side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @param children
+ * The identifiers of the objects on the child side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @return
+ * The number of rows deleted.
+ */
+ int delete(@Param("parent") ParentModelType parent,
+ @Param("children") Collection children);
+
+ /**
+ * Retrieves the identifiers of all objects on the child side of the
+ * one-to-many relationship represented by the RelatedObjectSet mapped by
+ * this ObjectRelationMapper. This should only be called on behalf of a
+ * system administrator. If identifiers are needed by a non-administrative
+ * user who must have explicit read rights, use
+ * selectReadableChildIdentifiers() instead.
+ *
+ * @param parent
+ * The model of the object on the parent side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @return
+ * A Set containing the identifiers of all objects on the child side
+ * of the one-to-many relationship.
+ */
+ Set selectChildIdentifiers(@Param("parent") ParentModelType parent);
+
+ /**
+ * Retrieves the identifiers of all objects on the child side of the
+ * one-to-many relationship represented by the RelatedObjectSet mapped by
+ * this ObjectRelationMapper, including only those objects which are
+ * explicitly readable by the given user. If identifiers are needed by a
+ * system administrator (who, by definition, does not need explicit read
+ * rights), use selectChildIdentifiers() instead.
+
+ *
+ * @param user
+ * The user whose permissions should determine whether an identifier
+ * is returned.
+ *
+ * @param effectiveGroups
+ * The identifiers of any known effective groups that should be taken
+ * into account, such as those defined externally to the database.
+ *
+ * @param parent
+ * The model of the object on the parent side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @return
+ * A Set containing the identifiers of all readable objects on the
+ * child side of the one-to-many relationship.
+ */
+ Set selectReadableChildIdentifiers(@Param("user") UserModel user,
+ @Param("effectiveGroups") Collection effectiveGroups,
+ @Param("parent") ParentModelType parent);
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RelatedObjectSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RelatedObjectSet.java
new file mode 100644
index 000000000..f7b75ef12
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RelatedObjectSet.java
@@ -0,0 +1,211 @@
+/*
+ * 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.base;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleSecurityException;
+import org.apache.guacamole.net.auth.permission.ObjectPermission;
+import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
+
+/**
+ * A database implementation of RelatedObjectSet which provides access to a
+ * parent object and corresponding set of objects related to the parent, subject
+ * to object-level permissions. Though the parent and child objects have
+ * specific types, only the parent object's type is enforced through type
+ * parameters, as child objects are represented by identifiers only.
+ *
+ * @param
+ * The type of object that represents the parent side of the relation.
+ *
+ * @param
+ * The underlying database model of the parent object.
+ */
+public abstract class RelatedObjectSet, ParentModelType extends ObjectModel>
+ extends RestrictedObject implements org.apache.guacamole.net.auth.RelatedObjectSet {
+
+ /**
+ * The parent object which shares some arbitrary relation with the objects
+ * within this set.
+ */
+ private ParentObjectType parent;
+
+ /**
+ * Creates a new RelatedObjectSet. The resulting object set must still be
+ * initialized by a call to init().
+ */
+ public RelatedObjectSet() {
+ }
+
+ /**
+ * Initializes this RelatedObjectSet with the current user and the single
+ * object on the parent side of the one-to-many relation represented by the
+ * set.
+ *
+ * @param currentUser
+ * The user who queried this RelatedObjectSet, and whose permissions
+ * dictate the access level of all operations performed on this set.
+ *
+ * @param parent
+ * The parent object which shares some arbitrary relation with the
+ * objects within this set.
+ */
+ public void init(ModeledAuthenticatedUser currentUser, ParentObjectType parent) {
+ super.init(currentUser);
+ this.parent = parent;
+ }
+
+ /**
+ * Returns the mapper which provides low-level access to the the database
+ * models which drive the relation represented by this RelatedObjectSet.
+ *
+ * @return
+ * The mapper which provides low-level access to the the database
+ * models which drive the relation represented by this
+ * RelatedObjectSet.
+ */
+ protected abstract ObjectRelationMapper getObjectRelationMapper();
+
+ /**
+ * Returns the permission set which exposes the effective permissions
+ * available to the current user regarding the objects on the parent side
+ * of the one-to-many relationship represented by this RelatedObjectSet.
+ * Permission inheritance through user groups is taken into account.
+ *
+ * @return
+ * The permission set which exposes the effective permissions
+ * available to the current user regarding the objects on the parent
+ * side of the one-to-many relationship represented by this
+ * RelatedObjectSet.
+ *
+ * @throws GuacamoleException
+ * If permission to query permission status is denied.
+ */
+ protected abstract ObjectPermissionSet getParentObjectEffectivePermissionSet()
+ throws GuacamoleException;
+
+ /**
+ * Returns the permission set which exposes the effective permissions
+ * available to the current user regarding the objects on the child side
+ * of the one-to-many relationship represented by this RelatedObjectSet.
+ * Permission inheritance through user groups is taken into account.
+ *
+ * @return
+ * The permission set which exposes the effective permissions
+ * available to the current user regarding the objects on the child
+ * side of the one-to-many relationship represented by this
+ * RelatedObjectSet.
+ *
+ * @throws GuacamoleException
+ * If permission to query permission status is denied.
+ */
+ protected abstract ObjectPermissionSet getChildObjectEffectivePermissionSet()
+ throws GuacamoleException;
+
+ /**
+ * Returns whether the current user has permission to alter the status of
+ * the relation between the parent object and the given child objects.
+ *
+ * @param identifiers
+ * The identifiers of all objects on the child side of the one-to-many
+ * relation being changed.
+ *
+ * @return
+ * true if the user has permission to make the described changes,
+ * false otherwise.
+ *
+ * @throws GuacamoleException
+ * If permission to query permission status is denied.
+ */
+ private boolean canAlterRelation(Collection identifiers)
+ throws GuacamoleException {
+
+ // System administrators may alter any relations
+ if (getCurrentUser().getUser().isAdministrator())
+ return true;
+
+ // Non-admin users require UPDATE permission on the parent object ...
+ if (!getParentObjectEffectivePermissionSet().hasPermission(
+ ObjectPermission.Type.UPDATE, parent.getIdentifier()))
+ return false;
+
+ // ... as well as UPDATE permission on all child objects being changed
+ Collection accessibleIdentifiers =
+ getChildObjectEffectivePermissionSet().getAccessibleObjects(
+ Collections.singleton(ObjectPermission.Type.UPDATE),
+ identifiers);
+
+ return accessibleIdentifiers.size() == identifiers.size();
+
+ }
+
+ @Override
+ public Set getObjects() throws GuacamoleException {
+
+ // Bypass permission checks if the user is a system admin
+ ModeledAuthenticatedUser user = getCurrentUser();
+ if (user.getUser().isAdministrator())
+ return getObjectRelationMapper().selectChildIdentifiers(parent.getModel());
+
+ // Otherwise only return explicitly readable identifiers
+ return getObjectRelationMapper().selectReadableChildIdentifiers(
+ user.getUser().getModel(), user.getEffectiveUserGroups(),
+ parent.getModel());
+
+ }
+
+ @Override
+ public void addObjects(Set identifiers) throws GuacamoleException {
+
+ // Nothing to do if nothing provided
+ if (identifiers.isEmpty())
+ return;
+
+ // Create relations only if permission is granted
+ if (canAlterRelation(identifiers))
+ getObjectRelationMapper().insert(parent.getModel(), identifiers);
+
+ // User lacks permission to add user groups
+ else
+ throw new GuacamoleSecurityException("Permission denied.");
+
+ }
+
+ @Override
+ public void removeObjects(Set identifiers) throws GuacamoleException {
+
+ // Nothing to do if nothing provided
+ if (identifiers.isEmpty())
+ return;
+
+ // Delete relations only if permission is granted
+ if (canAlterRelation(identifiers))
+ getObjectRelationMapper().delete(parent.getModel(), identifiers);
+
+ // User lacks permission to remove user groups
+ else
+ throw new GuacamoleSecurityException("Permission denied.");
+
+ }
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.java
index 9a4913242..3cd542fd2 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.java
@@ -19,6 +19,7 @@
package org.apache.guacamole.auth.jdbc.connection;
+import java.util.Collection;
import java.util.Set;
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
import org.apache.guacamole.auth.jdbc.user.UserModel;
@@ -61,11 +62,18 @@ public interface ConnectionMapper extends ModeledDirectoryObjectMapper selectReadableIdentifiersWithin(@Param("user") UserModel user,
- @Param("parentIdentifier") String parentIdentifier);
+ @Param("parentIdentifier") String parentIdentifier,
+ @Param("effectiveGroups") Collection effectiveGroups);
/**
* Selects the connection within the given parent group and having the
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.java
index 637fd0fed..7380b213b 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.java
@@ -102,12 +102,19 @@ public interface ConnectionRecordMapper {
* @param limit
* The maximum number of records that should be returned.
*
+ * @param effectiveGroups
+ * The identifiers of all groups that should be taken into account
+ * when determining the permissions effectively granted to the user. If
+ * no groups are given, only permissions directly granted to the user
+ * will be used.
+ *
* @return
* The results of the search performed with the given parameters.
*/
List searchReadable(@Param("user") UserModel user,
@Param("terms") Collection terms,
@Param("sortPredicates") List sortPredicates,
- @Param("limit") int limit);
+ @Param("limit") int limit,
+ @Param("effectiveGroups") Collection effectiveGroups);
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
index 983f395f7..8dcf6f59a 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
@@ -131,26 +131,26 @@ public class ConnectionService extends ModeledChildDirectoryObjectService selectReadableIdentifiersWithin(@Param("user") UserModel user,
- @Param("parentIdentifier") String parentIdentifier);
+ @Param("parentIdentifier") String parentIdentifier,
+ @Param("effectiveGroups") Collection effectiveGroups);
/**
* Selects the connection group within the given parent group and having
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
index e23081c50..01119b92e 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
@@ -112,26 +112,26 @@ public class ConnectionGroupService extends ModeledChildDirectoryObjectService
implements PermissionService {
+ /**
+ * Returns the ObjectPermissionSet related to the type of the given entity.
+ * If the given entity represents a user, then the ObjectPermissionSet
+ * containing user permissions is returned. If the given entity represents
+ * a user group, then the ObjectPermissionSet containing user group
+ * permissions is returned.
+ *
+ * @param user
+ * The user to retrieve the ObjectPermissionSet from.
+ *
+ * @param targetEntity
+ * The entity whose type dictates the ObjectPermissionSet returned.
+ *
+ * @return
+ * The ObjectPermissionSet related to the type of the given entity.
+ *
+ * @throws GuacamoleException
+ * If the relevant ObjectPermissionSet cannot be retrieved.
+ */
+ protected ObjectPermissionSet getRelevantPermissionSet(ModeledUser user,
+ ModeledPermissions extends EntityModel> targetEntity)
+ throws GuacamoleException {
+
+ if (targetEntity.isUser())
+ return user.getUserPermissions();
+
+ if (targetEntity.isUserGroup())
+ return user.getUserGroupPermissions();
+
+ // Entities should be only users or groups
+ throw new UnsupportedOperationException("Unexpected entity type.");
+
+ }
+
/**
* Determines whether the given user can read the permissions currently
- * granted to the given target user. If the reading user and the target
- * user are not the same, then explicit READ or SYSTEM_ADMINISTER access is
- * required.
+ * granted to the given target entity. If the reading user and the target
+ * entity are not the same, then explicit READ or SYSTEM_ADMINISTER access
+ * is required. Permission inheritance via user groups is taken into account.
*
* @param user
* The user attempting to read permissions.
*
- * @param targetUser
- * The user whose permissions are being read.
+ * @param targetEntity
+ * The entity whose permissions are being read.
*
* @return
* true if permission is granted, false otherwise.
@@ -61,19 +97,20 @@ public abstract class AbstractPermissionService targetEntity)
+ throws GuacamoleException {
// A user can always read their own permissions
- if (user.getUser().getIdentifier().equals(targetUser.getIdentifier()))
+ if (targetEntity.isUser() && user.getUser().getIdentifier().equals(targetEntity.getIdentifier()))
return true;
// A system adminstrator can do anything
if (user.getUser().isAdministrator())
return true;
- // Can read permissions on target user if explicit READ is granted
- ObjectPermissionSet userPermissionSet = user.getUser().getUserPermissions();
- return userPermissionSet.hasPermission(ObjectPermission.Type.READ, targetUser.getIdentifier());
+ // Can read permissions on target entity if explicit READ is granted
+ ObjectPermissionSet permissionSet = getRelevantPermissionSet(user.getUser(), targetEntity);
+ return permissionSet.hasPermission(ObjectPermission.Type.READ, targetEntity.getIdentifier());
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionGroupPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionGroupPermissionService.java
index 68fc3ed4b..d0f1f0b98 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionGroupPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionGroupPermissionService.java
@@ -21,9 +21,11 @@ package org.apache.guacamole.auth.jdbc.permission;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
/**
* Service which provides convenience methods for creating, retrieving, and
@@ -51,11 +53,12 @@ public class ConnectionGroupPermissionService extends ModeledObjectPermissionSer
@Override
public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
- ModeledUser targetUser) throws GuacamoleException {
+ ModeledPermissions extends EntityModel> targetEntity,
+ Set effectiveGroups) throws GuacamoleException {
- // Create permission set for requested user
+ // Create permission set for requested entity
ObjectPermissionSet permissionSet = connectionGroupPermissionSetProvider.get();
- permissionSet.init(user, targetUser);
+ permissionSet.init(user, targetEntity, effectiveGroups);
return permissionSet;
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionPermissionService.java
index 80c4b0b43..1dc70ad7b 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ConnectionPermissionService.java
@@ -21,9 +21,11 @@ package org.apache.guacamole.auth.jdbc.permission;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
/**
* Service which provides convenience methods for creating, retrieving, and
@@ -51,11 +53,12 @@ public class ConnectionPermissionService extends ModeledObjectPermissionService
@Override
public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
- ModeledUser targetUser) throws GuacamoleException {
+ ModeledPermissions extends EntityModel> targetEntity,
+ Set effectiveGroups) throws GuacamoleException {
- // Create permission set for requested user
+ // Create permission set for requested entity
ObjectPermissionSet permissionSet = connectionPermissionSetProvider.get();
- permissionSet.init(user, targetUser);
+ permissionSet.init(user, targetEntity, effectiveGroups);
return permissionSet;
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledObjectPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledObjectPermissionService.java
index a4f1f3f1f..8c4be58fd 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledObjectPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledObjectPermissionService.java
@@ -22,10 +22,12 @@ package org.apache.guacamole.auth.jdbc.permission;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
+import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
import org.apache.guacamole.net.auth.permission.ObjectPermission;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
@@ -47,14 +49,14 @@ public abstract class ModeledObjectPermissionService
}
@Override
- protected ObjectPermissionModel getModelInstance(ModeledUser targetUser,
+ protected ObjectPermissionModel getModelInstance(
+ ModeledPermissions extends EntityModel> targetEntity,
ObjectPermission permission) {
ObjectPermissionModel model = new ObjectPermissionModel();
- // Populate model object with data from user and permission
- model.setUserID(targetUser.getModel().getObjectID());
- model.setUsername(targetUser.getModel().getIdentifier());
+ // Populate model object with data from entity and permission
+ model.setEntityID(targetEntity.getModel().getEntityID());
model.setType(permission.getType());
model.setObjectIdentifier(permission.getObjectIdentifier());
@@ -64,30 +66,32 @@ public abstract class ModeledObjectPermissionService
/**
* Determines whether the current user has permission to update the given
- * target user, adding or removing the given permissions. Such permission
+ * target entity, adding or removing the given permissions. Such permission
* depends on whether the current user is a system administrator, whether
- * they have explicit UPDATE permission on the target user, and whether
+ * they have explicit UPDATE permission on the target entity, and whether
* they have explicit ADMINISTER permission on all affected objects.
+ * Permission inheritance via user groups is taken into account.
*
* @param user
* The user who is changing permissions.
*
- * @param targetUser
- * The user whose permissions are being changed.
+ * @param targetEntity
+ * The entity whose permissions are being changed.
*
* @param permissions
* The permissions that are being added or removed from the target
- * user.
+ * entity.
*
* @return
- * true if the user has permission to change the target users
+ * true if the user has permission to change the target entity's
* permissions as specified, false otherwise.
*
* @throws GuacamoleException
* If an error occurs while checking permission status, or if
* permission is denied to read the current user's permissions.
*/
- protected boolean canAlterPermissions(ModeledAuthenticatedUser user, ModeledUser targetUser,
+ protected boolean canAlterPermissions(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
Collection permissions)
throws GuacamoleException {
@@ -95,9 +99,9 @@ public abstract class ModeledObjectPermissionService
if (user.getUser().isAdministrator())
return true;
- // Verify user has update permission on the target user
- ObjectPermissionSet userPermissionSet = user.getUser().getUserPermissions();
- if (!userPermissionSet.hasPermission(ObjectPermission.Type.UPDATE, targetUser.getIdentifier()))
+ // Verify user has update permission on the target entity
+ ObjectPermissionSet permissionSet = getRelevantPermissionSet(user.getUser(), targetEntity);
+ if (!permissionSet.hasPermission(ObjectPermission.Type.UPDATE, targetEntity.getIdentifier()))
return false;
// Produce collection of affected identifiers
@@ -106,7 +110,7 @@ public abstract class ModeledObjectPermissionService
affectedIdentifiers.add(permission.getObjectIdentifier());
// Determine subset of affected identifiers that we have admin access to
- ObjectPermissionSet affectedPermissionSet = getPermissionSet(user, user.getUser());
+ ObjectPermissionSet affectedPermissionSet = getPermissionSet(user, user.getUser(), user.getEffectiveUserGroups());
Collection allowedSubset = affectedPermissionSet.getAccessibleObjects(
Collections.singleton(ObjectPermission.Type.ADMINISTER),
affectedIdentifiers
@@ -121,13 +125,14 @@ public abstract class ModeledObjectPermissionService
}
@Override
- public void createPermissions(ModeledAuthenticatedUser user, ModeledUser targetUser,
+ public void createPermissions(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
Collection permissions)
throws GuacamoleException {
// Create permissions only if user has permission to do so
- if (canAlterPermissions(user, targetUser, permissions)) {
- Collection models = getModelInstances(targetUser, permissions);
+ if (canAlterPermissions(user, targetEntity, permissions)) {
+ Collection models = getModelInstances(targetEntity, permissions);
getPermissionMapper().insert(models);
return;
}
@@ -138,13 +143,14 @@ public abstract class ModeledObjectPermissionService
}
@Override
- public void deletePermissions(ModeledAuthenticatedUser user, ModeledUser targetUser,
+ public void deletePermissions(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
Collection permissions)
throws GuacamoleException {
// Delete permissions only if user has permission to do so
- if (canAlterPermissions(user, targetUser, permissions)) {
- Collection models = getModelInstances(targetUser, permissions);
+ if (canAlterPermissions(user, targetEntity, permissions)) {
+ Collection models = getModelInstances(targetEntity, permissions);
getPermissionMapper().delete(models);
return;
}
@@ -155,49 +161,43 @@ public abstract class ModeledObjectPermissionService
}
@Override
- public ObjectPermission retrievePermission(ModeledAuthenticatedUser user,
- ModeledUser targetUser, ObjectPermission.Type type,
- String identifier) throws GuacamoleException {
+ public boolean hasPermission(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
+ ObjectPermission.Type type, String identifier,
+ Set effectiveGroups) throws GuacamoleException {
// Retrieve permissions only if allowed
- if (canReadPermissions(user, targetUser)) {
+ if (canReadPermissions(user, targetEntity))
+ return getPermissionMapper().selectOne(targetEntity.getModel(),
+ type, identifier, effectiveGroups) != null;
- // Read permission from database, return null if not found
- ObjectPermissionModel model = getPermissionMapper().selectOne(targetUser.getModel(), type, identifier);
- if (model == null)
- return null;
-
- return getPermissionInstance(model);
-
- }
-
- // User cannot read this user's permissions
+ // User cannot read this entity's permissions
throw new GuacamoleSecurityException("Permission denied.");
}
@Override
public Collection retrieveAccessibleIdentifiers(ModeledAuthenticatedUser user,
- ModeledUser targetUser, Collection permissions,
- Collection identifiers) throws GuacamoleException {
+ ModeledPermissions extends EntityModel> targetEntity,
+ Collection permissions,
+ Collection identifiers, Set effectiveGroups)
+ throws GuacamoleException {
// Nothing is always accessible
if (identifiers.isEmpty())
return identifiers;
- // Retrieve permissions only if allowed
- if (canReadPermissions(user, targetUser)) {
+ // If user is an admin, everything is accessible
+ if (user.getUser().isAdministrator())
+ return identifiers;
- // If user is an admin, everything is accessible
- if (user.getUser().isAdministrator())
- return identifiers;
+ // Otherwise, return explicitly-retrievable identifiers only if allowed
+ if (canReadPermissions(user, targetEntity))
+ return getPermissionMapper().selectAccessibleIdentifiers(
+ targetEntity.getModel(), permissions, identifiers,
+ effectiveGroups);
- // Otherwise, return explicitly-retrievable identifiers
- return getPermissionMapper().selectAccessibleIdentifiers(targetUser.getModel(), permissions, identifiers);
-
- }
-
- // User cannot read this user's permissions
+ // User cannot read this entity's permissions
throw new GuacamoleSecurityException("Permission denied.");
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledPermissionService.java
index 28008451f..a102f3434 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ModeledPermissionService.java
@@ -24,9 +24,10 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
import org.apache.guacamole.net.auth.permission.Permission;
import org.apache.guacamole.net.auth.permission.PermissionSet;
@@ -92,47 +93,49 @@ public abstract class ModeledPermissionService targetEntity,
PermissionType permission);
-
+
/**
* Returns a collection of model objects which are based on the given
- * permissions and target user.
+ * permissions and target entity.
*
- * @param targetUser
- * The user to whom this permission is granted.
+ * @param targetEntity
+ * The entity to whom this permission is granted.
*
* @param permissions
* The permissions to use to produce the returned model objects.
*
* @return
* A collection of model objects which are based on the given
- * permissions and target user.
+ * permissions and target entity.
*/
- protected Collection getModelInstances(ModeledUser targetUser,
+ protected Collection getModelInstances(
+ ModeledPermissions extends EntityModel> targetEntity,
Collection permissions) {
- // Create new collection of models by manually converting each permission
+ // Create new collection of models by manually converting each permission
Collection models = new ArrayList(permissions.size());
for (PermissionType permission : permissions)
- models.add(getModelInstance(targetUser, permission));
+ models.add(getModelInstance(targetEntity, permission));
return models;
@@ -140,15 +143,16 @@ public abstract class ModeledPermissionService retrievePermissions(ModeledAuthenticatedUser user,
- ModeledUser targetUser) throws GuacamoleException {
+ ModeledPermissions extends EntityModel> targetEntity,
+ Set effectiveGroups) throws GuacamoleException {
// Retrieve permissions only if allowed
- if (canReadPermissions(user, targetUser))
- return getPermissionInstances(getPermissionMapper().select(targetUser.getModel()));
+ if (canReadPermissions(user, targetEntity))
+ return getPermissionInstances(getPermissionMapper().select(targetEntity.getModel(), effectiveGroups));
- // User cannot read this user's permissions
+ // User cannot read this entity's permissions
throw new GuacamoleSecurityException("Permission denied.");
-
+
}
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java
index ff8369ae3..b6f9801d2 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java
@@ -20,8 +20,8 @@
package org.apache.guacamole.auth.jdbc.permission;
import java.util.Collection;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
import org.apache.ibatis.annotations.Param;
-import org.apache.guacamole.auth.jdbc.user.UserModel;
import org.apache.guacamole.net.auth.permission.ObjectPermission;
/**
@@ -31,32 +31,39 @@ public interface ObjectPermissionMapper extends PermissionMapper effectiveGroups);
/**
- * Retrieves the subset of the given identifiers for which the given user
+ * Retrieves the subset of the given identifiers for which the given entity
* has at least one of the given permissions.
*
- * @param user
- * The user to check permissions of.
+ * @param entity
+ * The entity to check permissions of.
*
* @param permissions
* The permissions to check. An identifier will be included in the
@@ -67,12 +74,19 @@ public interface ObjectPermissionMapper extends PermissionMapper selectAccessibleIdentifiers(@Param("user") UserModel user,
+ Collection selectAccessibleIdentifiers(@Param("entity") EntityModel entity,
@Param("permissions") Collection permissions,
- @Param("identifiers") Collection identifiers);
+ @Param("identifiers") Collection identifiers,
+ @Param("effectiveGroups") Collection effectiveGroups);
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionService.java
index 5eead24e1..a841c96c3 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionService.java
@@ -20,9 +20,11 @@
package org.apache.guacamole.auth.jdbc.permission;
import java.util.Collection;
+import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
import org.apache.guacamole.net.auth.permission.ObjectPermission;
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
@@ -35,41 +37,48 @@ public interface ObjectPermissionService
extends PermissionService {
/**
- * Retrieves the permission of the given type associated with the given
- * user and object, if it exists. If no such permission exists, null is
+ * Returns whether the permission of the given type and associated with the
+ * given object has been granted to the given entity.
*
* @param user
* The user retrieving the permission.
*
- * @param targetUser
- * The user associated with the permission to be retrieved.
- *
+ * @param targetEntity
+ * The entity associated with the permission to be retrieved.
+ *
* @param type
* The type of permission to retrieve.
*
* @param identifier
* The identifier of the object affected by the permission to return.
*
+ * @param effectiveGroups
+ * The identifiers of all groups that should be taken into account
+ * when determining the permissions effectively granted to the entity.
+ * If no groups are given, only permissions directly granted to the
+ * entity will be used.
+ *
* @return
- * The permission of the given type associated with the given user and
- * object, or null if no such permission exists.
+ * true if permission of the given type and associated with the given
+ * object has been granted to the given entity, false otherwise.
*
* @throws GuacamoleException
* If an error occurs while retrieving the requested permission.
*/
- ObjectPermission retrievePermission(ModeledAuthenticatedUser user,
- ModeledUser targetUser, ObjectPermission.Type type,
- String identifier) throws GuacamoleException;
+ boolean hasPermission(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
+ ObjectPermission.Type type, String identifier,
+ Set effectiveGroups) throws GuacamoleException;
/**
- * Retrieves the subset of the given identifiers for which the given user
+ * Retrieves the subset of the given identifiers for which the given entity
* has at least one of the given permissions.
*
* @param user
* The user checking the permissions.
*
- * @param targetUser
- * The user to check permissions of.
+ * @param targetEntity
+ * The entity to check permissions of.
*
* @param permissions
* The permissions to check. An identifier will be included in the
@@ -80,6 +89,12 @@ public interface ObjectPermissionService
* The identifiers of the objects affected by the permissions being
* checked.
*
+ * @param effectiveGroups
+ * The identifiers of all groups that should be taken into account
+ * when determining the permissions effectively granted to the entity.
+ * If no groups are given, only permissions directly granted to the
+ * entity will be used.
+ *
* @return
* A collection containing the subset of identifiers for which at least
* one of the specified permissions is granted.
@@ -88,7 +103,9 @@ public interface ObjectPermissionService
* If an error occurs while retrieving permissions.
*/
Collection retrieveAccessibleIdentifiers(ModeledAuthenticatedUser user,
- ModeledUser targetUser, Collection permissions,
- Collection identifiers) throws GuacamoleException;
+ ModeledPermissions extends EntityModel> targetEntity,
+ Collection permissions,
+ Collection identifiers, Set effectiveGroups)
+ throws GuacamoleException;
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionSet.java
index 712a42242..d179c686a 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionSet.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/ObjectPermissionSet.java
@@ -19,28 +19,35 @@
package org.apache.guacamole.auth.jdbc.permission;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
import org.apache.guacamole.net.auth.permission.ObjectPermission;
/**
* A database implementation of ObjectPermissionSet which uses an injected
* service to query and manipulate the object-level permissions associated with
- * a particular user.
+ * a particular entity.
*/
public abstract class ObjectPermissionSet extends RestrictedObject
implements org.apache.guacamole.net.auth.permission.ObjectPermissionSet {
/**
- * The user associated with this permission set. Each of the permissions in
- * this permission set is granted to this user.
+ * The entity associated with this permission set. Each of the permissions
+ * in this permission set is granted to this entity.
*/
- private ModeledUser user;
+ private ModeledPermissions extends EntityModel> entity;
+
+ /**
+ * The identifiers of all groups that should be taken into account
+ * when determining the permissions effectively granted to the entity.
+ */
+ private Set effectiveGroups;
/**
* Creates a new ObjectPermissionSet. The resulting permission set
@@ -51,19 +58,28 @@ public abstract class ObjectPermissionSet extends RestrictedObject
}
/**
- * Initializes this permission set with the current user and the user
+ * Initializes this permission set with the current user and the entity
* to whom the permissions in this set are granted.
*
* @param currentUser
* The user who queried this permission set, and whose permissions
* dictate the access level of all operations performed on this set.
*
- * @param user
- * The user to whom the permissions in this set are granted.
+ * @param entity
+ * The entity to whom the permissions in this set are granted.
+ *
+ * @param effectiveGroups
+ * The identifiers of all groups that should be taken into account
+ * when determining the permissions effectively granted to the entity.
+ * If no groups are given, only permissions directly granted to the
+ * entity will be used.
*/
- public void init(ModeledAuthenticatedUser currentUser, ModeledUser user) {
+ public void init(ModeledAuthenticatedUser currentUser,
+ ModeledPermissions extends EntityModel> entity,
+ Set effectiveGroups) {
super.init(currentUser);
- this.user = user;
+ this.entity = entity;
+ this.effectiveGroups = effectiveGroups;
}
/**
@@ -75,16 +91,16 @@ public abstract class ObjectPermissionSet extends RestrictedObject
* permissions contained within this permission set.
*/
protected abstract ObjectPermissionService getObjectPermissionService();
-
+
@Override
public Set getPermissions() throws GuacamoleException {
- return getObjectPermissionService().retrievePermissions(getCurrentUser(), user);
+ return getObjectPermissionService().retrievePermissions(getCurrentUser(), entity, effectiveGroups);
}
@Override
public boolean hasPermission(ObjectPermission.Type permission,
String identifier) throws GuacamoleException {
- return getObjectPermissionService().retrievePermission(getCurrentUser(), user, permission, identifier) != null;
+ return getObjectPermissionService().hasPermission(getCurrentUser(), entity, permission, identifier, effectiveGroups);
}
@Override
@@ -102,19 +118,19 @@ public abstract class ObjectPermissionSet extends RestrictedObject
@Override
public Collection getAccessibleObjects(Collection permissions,
Collection identifiers) throws GuacamoleException {
- return getObjectPermissionService().retrieveAccessibleIdentifiers(getCurrentUser(), user, permissions, identifiers);
+ return getObjectPermissionService().retrieveAccessibleIdentifiers(getCurrentUser(), entity, permissions, identifiers, effectiveGroups);
}
@Override
public void addPermissions(Set permissions)
throws GuacamoleException {
- getObjectPermissionService().createPermissions(getCurrentUser(), user, permissions);
+ getObjectPermissionService().createPermissions(getCurrentUser(), entity, permissions);
}
@Override
public void removePermissions(Set permissions)
throws GuacamoleException {
- getObjectPermissionService().deletePermissions(getCurrentUser(), user, permissions);
+ getObjectPermissionService().deletePermissions(getCurrentUser(), entity, permissions);
}
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionMapper.java
index d49dc30c3..edd66f494 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionMapper.java
@@ -20,7 +20,7 @@
package org.apache.guacamole.auth.jdbc.permission;
import java.util.Collection;
-import org.apache.guacamole.auth.jdbc.user.UserModel;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
import org.apache.ibatis.annotations.Param;
/**
@@ -32,15 +32,23 @@ import org.apache.ibatis.annotations.Param;
public interface PermissionMapper {
/**
- * Retrieves all permissions associated with the given user.
+ * Retrieves all permissions associated with the given entity (user or user
+ * group).
*
- * @param user
- * The user to retrieve permissions for.
+ * @param entity
+ * The entity to retrieve permissions for.
+ *
+ * @param effectiveGroups
+ * The identifiers of all groups that should be taken into account
+ * when determining the permissions effectively granted to the user. If
+ * no groups are given, only permissions directly granted to the user
+ * will be used.
*
* @return
- * All permissions associated with the given user.
+ * All permissions associated with the given entity.
*/
- Collection select(@Param("user") UserModel user);
+ Collection select(@Param("entity") EntityModel entity,
+ @Param("effectiveGroups") Collection effectiveGroups);
/**
* Inserts the given permissions into the database. If any permissions
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionModel.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionModel.java
index fbc3e8de4..da1ec2d28 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionModel.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionModel.java
@@ -21,7 +21,7 @@ package org.apache.guacamole.auth.jdbc.permission;
/**
* Generic base permission model which grants a permission of a particular type
- * to a specific user.
+ * to a specific entity (user or user group).
*
* @param
* The type of permissions allowed within this model.
@@ -29,14 +29,9 @@ package org.apache.guacamole.auth.jdbc.permission;
public abstract class PermissionModel {
/**
- * The database ID of the user to whom this permission is granted.
+ * The database ID of the entity to whom this permission is granted.
*/
- private Integer userID;
-
- /**
- * The username of the user to whom this permission is granted.
- */
- private String username;
+ private Integer entityID;
/**
* The type of action granted by this permission.
@@ -44,43 +39,24 @@ public abstract class PermissionModel {
private PermissionType type;
/**
- * Returns the database ID of the user to whom this permission is granted.
+ * Returns the database ID of the entity to whom this permission is
+ * granted.
*
* @return
- * The database ID of the user to whom this permission is granted.
+ * The database ID of the entity to whom this permission is granted.
*/
- public Integer getUserID() {
- return userID;
+ public Integer getEntityID() {
+ return entityID;
}
/**
- * Sets the database ID of the user to whom this permission is granted.
+ * Sets the database ID of the entity to whom this permission is granted.
*
- * @param userID
- * The database ID of the user to whom this permission is granted.
+ * @param entityID
+ * The database ID of the entity to whom this permission is granted.
*/
- public void setUserID(Integer userID) {
- this.userID = userID;
- }
-
- /**
- * Returns the username of the user to whom this permission is granted.
- *
- * @return
- * The username of the user to whom this permission is granted.
- */
- public String getUsername() {
- return username;
- }
-
- /**
- * Sets the username of the user to whom this permission is granted.
- *
- * @param username
- * The username of the user to whom this permission is granted.
- */
- public void setUsername(String username) {
- this.username = username;
+ public void setEntityID(Integer entityID) {
+ this.entityID = entityID;
}
/**
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionService.java
index 12b046b4d..a48157ebc 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/PermissionService.java
@@ -19,16 +19,12 @@
package org.apache.guacamole.auth.jdbc.permission;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.GuacamoleSecurityException;
-import org.apache.guacamole.net.auth.permission.ObjectPermission;
-import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
import org.apache.guacamole.net.auth.permission.Permission;
import org.apache.guacamole.net.auth.permission.PermissionSet;
@@ -49,45 +45,60 @@ public interface PermissionService targetEntity,
+ Set effectiveGroups) throws GuacamoleException;
/**
- * Retrieves all permissions associated with the given user.
+ * Retrieves all permissions associated with the given entity.
*
* @param user
* The user retrieving the permissions.
*
- * @param targetUser
- * The user associated with the permissions to be retrieved.
+ * @param targetEntity
+ * The entity associated with the permissions to be retrieved.
+ *
+ * @param effectiveGroups
+ * The identifiers of all groups that should be taken into account
+ * when determining the permissions effectively granted to the entity.
+ * If no groups are given, only permissions directly granted to the
+ * entity will be used.
*
* @return
- * The permissions associated with the given user.
+ * The permissions associated with the given entity.
*
* @throws GuacamoleException
* If an error occurs while retrieving the requested permissions.
*/
Set retrievePermissions(ModeledAuthenticatedUser user,
- ModeledUser targetUser) throws GuacamoleException;
+ ModeledPermissions extends EntityModel> targetEntity,
+ Set effectiveGroups) throws GuacamoleException;
/**
* Creates the given permissions within the database. If any permissions
@@ -96,8 +107,8 @@ public interface PermissionService permissions) throws GuacamoleException;
+ void createPermissions(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
+ Collection permissions)
+ throws GuacamoleException;
/**
* Deletes the given permissions. If any permissions do not exist, they
@@ -116,8 +129,8 @@ public interface PermissionService permissions) throws GuacamoleException;
+ void deletePermissions(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
+ Collection permissions)
+ throws GuacamoleException;
}
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
index ac16fc2c7..c30ff73b6 100644
--- 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
@@ -21,9 +21,11 @@ package org.apache.guacamole.auth.jdbc.permission;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
/**
* Service which provides convenience methods for creating, retrieving, and
@@ -51,11 +53,12 @@ public class SharingProfilePermissionService extends ModeledObjectPermissionServ
@Override
public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
- ModeledUser targetUser) throws GuacamoleException {
+ ModeledPermissions extends EntityModel> targetEntity,
+ Set effectiveGroups) throws GuacamoleException {
- // Create permission set for requested user
+ // Create permission set for requested entity
ObjectPermissionSet permissionSet = sharingProfilePermissionSetProvider.get();
- permissionSet.init(user, targetUser);
+ permissionSet.init(user, targetEntity, effectiveGroups);
return permissionSet;
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionMapper.java
index 929d6e9aa..c676b72b1 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionMapper.java
@@ -19,7 +19,8 @@
package org.apache.guacamole.auth.jdbc.permission;
-import org.apache.guacamole.auth.jdbc.user.UserModel;
+import java.util.Collection;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
import org.apache.ibatis.annotations.Param;
import org.apache.guacamole.net.auth.permission.SystemPermission;
@@ -30,19 +31,26 @@ public interface SystemPermissionMapper extends PermissionMapper effectiveGroups);
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionService.java
index db1d81e61..5e5a43bc4 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionService.java
@@ -22,11 +22,13 @@ package org.apache.guacamole.auth.jdbc.permission;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.Collection;
+import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.GuacamoleUnsupportedException;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
import org.apache.guacamole.net.auth.permission.SystemPermission;
/**
@@ -60,14 +62,14 @@ public class SystemPermissionService
}
@Override
- protected SystemPermissionModel getModelInstance(final ModeledUser targetUser,
+ protected SystemPermissionModel getModelInstance(
+ final ModeledPermissions extends EntityModel> targetEntity,
final SystemPermission permission) {
SystemPermissionModel model = new SystemPermissionModel();
- // Populate model object with data from user and permission
- model.setUserID(targetUser.getModel().getObjectID());
- model.setUsername(targetUser.getModel().getIdentifier());
+ // Populate model object with data from entity and permission
+ model.setEntityID(targetEntity.getModel().getEntityID());
model.setType(permission.getType());
return model;
@@ -76,23 +78,25 @@ public class SystemPermissionService
@Override
public SystemPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
- ModeledUser targetUser) throws GuacamoleException {
+ ModeledPermissions extends EntityModel> targetEntity,
+ Set effectiveGroups) throws GuacamoleException {
- // Create permission set for requested user
+ // Create permission set for requested entity
SystemPermissionSet permissionSet = systemPermissionSetProvider.get();
- permissionSet.init(user, targetUser);
+ permissionSet.init(user, targetEntity, effectiveGroups);
return permissionSet;
}
@Override
- public void createPermissions(ModeledAuthenticatedUser user, ModeledUser targetUser,
+ public void createPermissions(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
Collection permissions) throws GuacamoleException {
// Only an admin can create system permissions
if (user.getUser().isAdministrator()) {
- Collection models = getModelInstances(targetUser, permissions);
+ Collection models = getModelInstances(targetEntity, permissions);
systemPermissionMapper.insert(models);
return;
}
@@ -103,17 +107,18 @@ public class SystemPermissionService
}
@Override
- public void deletePermissions(ModeledAuthenticatedUser user, ModeledUser targetUser,
+ public void deletePermissions(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
Collection permissions) throws GuacamoleException {
// Only an admin can delete system permissions
if (user.getUser().isAdministrator()) {
// Do not allow users to remove their own admin powers
- if (user.getUser().getIdentifier().equals(targetUser.getIdentifier()))
+ if (user.getUser().getIdentifier().equals(targetEntity.getIdentifier()))
throw new GuacamoleUnsupportedException("Removing your own administrative permissions is not allowed.");
- Collection models = getModelInstances(targetUser, permissions);
+ Collection models = getModelInstances(targetEntity, permissions);
systemPermissionMapper.delete(models);
return;
}
@@ -124,41 +129,42 @@ public class SystemPermissionService
}
/**
- * Retrieves the permission of the given type associated with the given
- * user, if it exists. If no such permission exists, null is returned.
+ * Retrieves whether the permission of the given type has been granted to
+ * the given entity. Permission inheritance through group membership is
+ * taken into account.
*
* @param user
* The user retrieving the permission.
*
- * @param targetUser
- * The user associated with the permission to be retrieved.
+ * @param targetEntity
+ * The entity associated with the permission to be retrieved.
*
* @param type
* The type of permission to retrieve.
*
+ * @param effectiveGroups
+ * The identifiers of all groups that should be taken into account
+ * when determining the permissions effectively granted to the entity.
+ * If no groups are given, only permissions directly granted to the
+ * entity will be used.
+ *
* @return
- * The permission of the given type associated with the given user, or
- * null if no such permission exists.
+ * true if permission of the given type has been granted to the given
+ * entity, false otherwise.
*
* @throws GuacamoleException
* If an error occurs while retrieving the requested permission.
*/
- public SystemPermission retrievePermission(ModeledAuthenticatedUser user,
- ModeledUser targetUser, SystemPermission.Type type) throws GuacamoleException {
+ public boolean hasPermission(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
+ SystemPermission.Type type, Set effectiveGroups)
+ throws GuacamoleException {
// Retrieve permissions only if allowed
- if (canReadPermissions(user, targetUser)) {
+ if (canReadPermissions(user, targetEntity))
+ return getPermissionMapper().selectOne(targetEntity.getModel(), type, effectiveGroups) != null;
- // Read permission from database, return null if not found
- SystemPermissionModel model = getPermissionMapper().selectOne(targetUser.getModel(), type);
- if (model == null)
- return null;
-
- return getPermissionInstance(model);
-
- }
-
- // User cannot read this user's permissions
+ // User cannot read this entity's permissions
throw new GuacamoleSecurityException("Permission denied.");
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionSet.java
index 9c84a84a4..1948facaa 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionSet.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/SystemPermissionSet.java
@@ -19,28 +19,35 @@
package org.apache.guacamole.auth.jdbc.permission;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
import com.google.inject.Inject;
import java.util.Collections;
import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
import org.apache.guacamole.net.auth.permission.SystemPermission;
/**
* A database implementation of SystemPermissionSet which uses an injected
* service to query and manipulate the system permissions associated with a
- * particular user.
+ * particular entity.
*/
public class SystemPermissionSet extends RestrictedObject
implements org.apache.guacamole.net.auth.permission.SystemPermissionSet {
/**
- * The user associated with this permission set. Each of the permissions in
- * this permission set is granted to this user.
+ * The entity associated with this permission set. Each of the permissions
+ * in this permission set is granted to this entity.
*/
- private ModeledUser user;
+ private ModeledPermissions extends EntityModel> entity;
+
+ /**
+ * The identifiers of all groups that should be taken into account when
+ * determining the permissions effectively granted to the entity.
+ */
+ private Set effectiveGroups;
/**
* Service for reading and manipulating system permissions.
@@ -57,30 +64,39 @@ public class SystemPermissionSet extends RestrictedObject
}
/**
- * Initializes this permission set with the current user and the user
+ * Initializes this permission set with the current user and the entity
* to whom the permissions in this set are granted.
*
* @param currentUser
* The user who queried this permission set, and whose permissions
* dictate the access level of all operations performed on this set.
*
- * @param user
- * The user to whom the permissions in this set are granted.
+ * @param entity
+ * The entity to whom the permissions in this set are granted.
+ *
+ * @param effectiveGroups
+ * The identifiers of all groups that should be taken into account
+ * when determining the permissions effectively granted to the entity.
+ * If no groups are given, only permissions directly granted to the
+ * entity will be used.
*/
- public void init(ModeledAuthenticatedUser currentUser, ModeledUser user) {
+ public void init(ModeledAuthenticatedUser currentUser,
+ ModeledPermissions extends EntityModel> entity,
+ Set effectiveGroups) {
super.init(currentUser);
- this.user = user;
+ this.entity = entity;
+ this.effectiveGroups = effectiveGroups;
}
@Override
public Set getPermissions() throws GuacamoleException {
- return systemPermissionService.retrievePermissions(getCurrentUser(), user);
+ return systemPermissionService.retrievePermissions(getCurrentUser(), entity, effectiveGroups);
}
@Override
public boolean hasPermission(SystemPermission.Type permission)
throws GuacamoleException {
- return systemPermissionService.retrievePermission(getCurrentUser(), user, permission) != null;
+ return systemPermissionService.hasPermission(getCurrentUser(), entity, permission, effectiveGroups);
}
@Override
@@ -98,13 +114,13 @@ public class SystemPermissionSet extends RestrictedObject
@Override
public void addPermissions(Set permissions)
throws GuacamoleException {
- systemPermissionService.createPermissions(getCurrentUser(), user, permissions);
+ systemPermissionService.createPermissions(getCurrentUser(), entity, permissions);
}
@Override
public void removePermissions(Set permissions)
throws GuacamoleException {
- systemPermissionService.deletePermissions(getCurrentUser(), user, permissions);
+ systemPermissionService.deletePermissions(getCurrentUser(), entity, permissions);
}
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserGroupPermissionMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserGroupPermissionMapper.java
new file mode 100644
index 000000000..d2a7494e2
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserGroupPermissionMapper.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+/**
+ * Mapper for user group permissions.
+ */
+public interface UserGroupPermissionMapper extends ObjectPermissionMapper {}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserGroupPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserGroupPermissionService.java
new file mode 100644
index 000000000..852b9f04c
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserGroupPermissionService.java
@@ -0,0 +1,67 @@
+/*
+ * 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 java.util.Set;
+import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
+
+/**
+ * Service which provides convenience methods for creating, retrieving, and
+ * deleting user group permissions. This service will automatically enforce the
+ * permissions of the current user.
+ */
+public class UserGroupPermissionService extends ModeledObjectPermissionService {
+
+ /**
+ * Mapper for user group permissions.
+ */
+ @Inject
+ private UserGroupPermissionMapper userGroupPermissionMapper;
+
+ /**
+ * Provider for user group permission sets.
+ */
+ @Inject
+ private Provider userGroupPermissionSetProvider;
+
+ @Override
+ protected ObjectPermissionMapper getPermissionMapper() {
+ return userGroupPermissionMapper;
+ }
+
+ @Override
+ public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
+ ModeledPermissions extends EntityModel> targetEntity,
+ Set effectiveGroups) throws GuacamoleException {
+
+ // Create permission set for requested entity
+ ObjectPermissionSet permissionSet = userGroupPermissionSetProvider.get();
+ permissionSet.init(user, targetEntity, effectiveGroups);
+
+ return permissionSet;
+
+ }
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserGroupPermissionSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserGroupPermissionSet.java
new file mode 100644
index 000000000..a864144a2
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserGroupPermissionSet.java
@@ -0,0 +1,42 @@
+/*
+ * 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 user group permissions associated with a
+ * particular user.
+ */
+public class UserGroupPermissionSet extends ObjectPermissionSet {
+
+ /**
+ * Service for querying and manipulating user group permissions.
+ */
+ @Inject
+ private UserGroupPermissionService userGroupPermissionService;
+
+ @Override
+ protected ObjectPermissionService getObjectPermissionService() {
+ return userGroupPermissionService;
+ }
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserPermissionService.java
index d56ed28bc..ed8689a7f 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserPermissionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/permission/UserPermissionService.java
@@ -21,9 +21,11 @@ package org.apache.guacamole.auth.jdbc.permission;
import com.google.inject.Inject;
import com.google.inject.Provider;
+import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.auth.jdbc.user.ModeledUser;
+import org.apache.guacamole.auth.jdbc.base.EntityModel;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
/**
* Service which provides convenience methods for creating, retrieving, and
@@ -51,11 +53,12 @@ public class UserPermissionService extends ModeledObjectPermissionService {
@Override
public ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user,
- ModeledUser targetUser) throws GuacamoleException {
+ ModeledPermissions extends EntityModel> targetEntity,
+ Set effectiveGroups) throws GuacamoleException {
- // Create permission set for requested user
+ // Create permission set for requested entity
ObjectPermissionSet permissionSet = userPermissionSetProvider.get();
- permissionSet.init(user, targetUser);
+ permissionSet.init(user, targetEntity, effectiveGroups);
return permissionSet;
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedAuthenticatedUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedAuthenticatedUser.java
index 958213cbc..96c6a9e31 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedAuthenticatedUser.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedAuthenticatedUser.java
@@ -20,7 +20,6 @@
package org.apache.guacamole.auth.jdbc.sharing.user;
import java.util.Collections;
-import java.util.Set;
import org.apache.guacamole.auth.jdbc.user.RemoteAuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticatedUser;
import org.apache.guacamole.net.auth.AuthenticationProvider;
@@ -52,7 +51,8 @@ public class SharedAuthenticatedUser extends RemoteAuthenticatedUser {
* The AuthenticatedUser to copy.
*/
public SharedAuthenticatedUser(AuthenticatedUser authenticatedUser) {
- super(authenticatedUser.getAuthenticationProvider(), authenticatedUser.getCredentials());
+ super(authenticatedUser.getAuthenticationProvider(),
+ authenticatedUser.getCredentials(), Collections.emptySet());
this.shareKey = null;
this.identifier = authenticatedUser.getIdentifier();
}
@@ -75,7 +75,7 @@ public class SharedAuthenticatedUser extends RemoteAuthenticatedUser {
*/
public SharedAuthenticatedUser(AuthenticationProvider authenticationProvider,
Credentials credentials, String shareKey) {
- super(authenticationProvider, credentials);
+ super(authenticationProvider, credentials, Collections.emptySet());
this.shareKey = shareKey;
this.identifier = AuthenticatedUser.ANONYMOUS_IDENTIFIER;
}
@@ -102,9 +102,4 @@ public class SharedAuthenticatedUser extends RemoteAuthenticatedUser {
throw new UnsupportedOperationException("Users authenticated via share keys are immutable.");
}
- @Override
- public Set getEffectiveUserGroups() {
- return Collections.emptySet();
- }
-
}
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
index 4b4d2d12f..4ca492c84 100644
--- 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
@@ -112,26 +112,26 @@ public class SharingProfileService
throws GuacamoleException {
// Return whether user has explicit sharing profile creation permission
- SystemPermissionSet permissionSet = user.getUser().getSystemPermissions();
+ SystemPermissionSet permissionSet = user.getUser().getEffectivePermissions().getSystemPermissions();
return permissionSet.hasPermission(SystemPermission.Type.CREATE_SHARING_PROFILE);
}
@Override
- protected ObjectPermissionSet getPermissionSet(ModeledAuthenticatedUser user)
+ protected ObjectPermissionSet getEffectivePermissionSet(ModeledAuthenticatedUser user)
throws GuacamoleException {
// Return permissions related to sharing profiles
- return user.getUser().getSharingProfilePermissions();
+ return user.getUser().getEffectivePermissions().getSharingProfilePermissions();
}
@Override
- protected ObjectPermissionSet getParentPermissionSet(ModeledAuthenticatedUser user)
+ protected ObjectPermissionSet getParentEffectivePermissionSet(ModeledAuthenticatedUser user)
throws GuacamoleException {
// Sharing profiles are children of connections
- return user.getUser().getConnectionPermissions();
+ return user.getUser().getEffectivePermissions().getConnectionPermissions();
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
index fe3a45b2f..5f7fc1ba3 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java
@@ -628,7 +628,9 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
identifiers.add(record.getConnection().getIdentifier());
// Produce collection of readable connection identifiers
- Collection connections = connectionMapper.selectReadable(user.getUser().getModel(), identifiers);
+ Collection connections =
+ connectionMapper.selectReadable(user.getUser().getModel(),
+ identifiers, user.getEffectiveUserGroups());
// Ensure set contains only identifiers of readable connections
identifiers.clear();
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledAuthenticatedUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledAuthenticatedUser.java
index 8c201d004..e756374cb 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledAuthenticatedUser.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledAuthenticatedUser.java
@@ -76,7 +76,7 @@ public class ModeledAuthenticatedUser extends RemoteAuthenticatedUser {
*/
public ModeledAuthenticatedUser(AuthenticatedUser authenticatedUser,
AuthenticationProvider modelAuthenticationProvider, ModeledUser user) {
- super(authenticatedUser.getAuthenticationProvider(), authenticatedUser.getCredentials());
+ super(authenticatedUser.getAuthenticationProvider(), authenticatedUser.getCredentials(), authenticatedUser.getEffectiveUserGroups());
this.modelAuthenticationProvider = modelAuthenticationProvider;
this.user = user;
}
@@ -98,7 +98,7 @@ public class ModeledAuthenticatedUser extends RemoteAuthenticatedUser {
*/
public ModeledAuthenticatedUser(AuthenticationProvider authenticationProvider,
ModeledUser user, Credentials credentials) {
- super(authenticationProvider, credentials);
+ super(authenticationProvider, credentials, user.getEffectiveUserGroups());
this.modelAuthenticationProvider = authenticationProvider;
this.user = user;
}
@@ -169,9 +169,4 @@ public class ModeledAuthenticatedUser extends RemoteAuthenticatedUser {
user.setIdentifier(identifier);
}
- @Override
- public Set getEffectiveUserGroups() {
- return Collections.emptySet();
- }
-
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
index 583aa7fc1..b7924edd9 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
@@ -20,6 +20,7 @@
package org.apache.guacamole.auth.jdbc.user;
import com.google.inject.Inject;
+import com.google.inject.Provider;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
@@ -33,16 +34,10 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
-import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObject;
import org.apache.guacamole.auth.jdbc.security.PasswordEncryptionService;
import org.apache.guacamole.auth.jdbc.security.SaltService;
-import org.apache.guacamole.auth.jdbc.permission.SystemPermissionService;
import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.auth.jdbc.activeconnection.ActiveConnectionPermissionService;
-import org.apache.guacamole.auth.jdbc.permission.ConnectionGroupPermissionService;
-import org.apache.guacamole.auth.jdbc.permission.ConnectionPermissionService;
-import org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionService;
-import org.apache.guacamole.auth.jdbc.permission.UserPermissionService;
+import org.apache.guacamole.auth.jdbc.base.ModeledPermissions;
import org.apache.guacamole.form.BooleanField;
import org.apache.guacamole.form.DateField;
import org.apache.guacamole.form.EmailField;
@@ -55,18 +50,13 @@ import org.apache.guacamole.net.auth.ActivityRecord;
import org.apache.guacamole.net.auth.Permissions;
import org.apache.guacamole.net.auth.RelatedObjectSet;
import org.apache.guacamole.net.auth.User;
-import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
-import org.apache.guacamole.net.auth.permission.SystemPermission;
-import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
-import org.apache.guacamole.net.auth.simple.SimpleObjectPermissionSet;
-import org.apache.guacamole.net.auth.simple.SimpleRelatedObjectSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An implementation of the User object which is backed by a database model.
*/
-public class ModeledUser extends ModeledDirectoryObject implements User {
+public class ModeledUser extends ModeledPermissions implements User {
/**
* Logger for this class.
@@ -187,40 +177,11 @@ public class ModeledUser extends ModeledDirectoryObject implements Us
private SaltService saltService;
/**
- * Service for retrieving system permissions.
+ * Provider for RelatedObjectSets containing the user groups of which this
+ * user is a member.
*/
@Inject
- private SystemPermissionService systemPermissionService;
-
- /**
- * Service for retrieving connection permissions.
- */
- @Inject
- private ConnectionPermissionService connectionPermissionService;
-
- /**
- * Service for retrieving connection group permissions.
- */
- @Inject
- private ConnectionGroupPermissionService connectionGroupPermissionService;
-
- /**
- * Service for retrieving sharing profile permissions.
- */
- @Inject
- private SharingProfilePermissionService sharingProfilePermissionService;
-
- /**
- * Service for retrieving active connection permissions.
- */
- @Inject
- private ActiveConnectionPermissionService activeConnectionPermissionService;
-
- /**
- * Service for retrieving user permissions.
- */
- @Inject
- private UserPermissionService userPermissionService;
+ private Provider parentUserGroupSetProvider;
/**
* Whether attributes which control access restrictions should be exposed
@@ -331,63 +292,6 @@ public class ModeledUser extends ModeledDirectoryObject implements Us
return passwordRecord;
}
- /**
- * Returns whether this user is a system administrator, and thus is not
- * restricted by permissions.
- *
- * @return
- * true if this user is a system administrator, false otherwise.
- *
- * @throws GuacamoleException
- * If an error occurs while determining the user's system administrator
- * status.
- */
- public boolean isAdministrator() throws GuacamoleException {
- SystemPermissionSet systemPermissionSet = getSystemPermissions();
- return systemPermissionSet.hasPermission(SystemPermission.Type.ADMINISTER);
- }
-
- @Override
- public SystemPermissionSet getSystemPermissions()
- throws GuacamoleException {
- return systemPermissionService.getPermissionSet(getCurrentUser(), this);
- }
-
- @Override
- public ObjectPermissionSet getConnectionPermissions()
- throws GuacamoleException {
- return connectionPermissionService.getPermissionSet(getCurrentUser(), this);
- }
-
- @Override
- public ObjectPermissionSet getConnectionGroupPermissions()
- throws GuacamoleException {
- return connectionGroupPermissionService.getPermissionSet(getCurrentUser(), this);
- }
-
- @Override
- public ObjectPermissionSet getSharingProfilePermissions()
- throws GuacamoleException {
- return sharingProfilePermissionService.getPermissionSet(getCurrentUser(), this);
- }
-
- @Override
- public ObjectPermissionSet getActiveConnectionPermissions()
- throws GuacamoleException {
- return activeConnectionPermissionService.getPermissionSet(getCurrentUser(), this);
- }
-
- @Override
- public ObjectPermissionSet getUserPermissions()
- throws GuacamoleException {
- return userPermissionService.getPermissionSet(getCurrentUser(), this);
- }
-
- @Override
- public ObjectPermissionSet getUserGroupPermissions() throws GuacamoleException {
- return new SimpleObjectPermissionSet();
- }
-
/**
* Stores all restricted (privileged) attributes within the given Map,
* pulling the values of those attributes from the underlying user model.
@@ -850,12 +754,14 @@ public class ModeledUser extends ModeledDirectoryObject implements Us
@Override
public RelatedObjectSet getUserGroups() throws GuacamoleException {
- return new SimpleRelatedObjectSet();
+ UserParentUserGroupSet parentUserGroupSet = parentUserGroupSetProvider.get();
+ parentUserGroupSet.init(getCurrentUser(), this);
+ return parentUserGroupSet;
}
@Override
public Permissions getEffectivePermissions() throws GuacamoleException {
- return this;
+ return super.getEffective();
}
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java
index d53164b36..e98a25a04 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java
@@ -26,7 +26,6 @@ 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 java.util.Date;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
@@ -37,6 +36,8 @@ 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.auth.jdbc.usergroup.ModeledUserGroup;
+import org.apache.guacamole.auth.jdbc.usergroup.UserGroupDirectory;
import org.apache.guacamole.form.Form;
import org.apache.guacamole.net.auth.ActiveConnection;
import org.apache.guacamole.net.auth.ActivityRecord;
@@ -48,7 +49,6 @@ 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.UserGroup;
-import org.apache.guacamole.net.auth.simple.SimpleDirectory;
/**
* UserContext implementation which is driven by an arbitrary, underlying
@@ -63,6 +63,13 @@ public class ModeledUserContext extends RestrictedObject
*/
@Inject
private UserDirectory userDirectory;
+
+ /**
+ * User group directory restricted by the permissions of the user associated
+ * with this context.
+ */
+ @Inject
+ private UserGroupDirectory userGroupDirectory;
/**
* Connection directory restricted by the permissions of the user
@@ -128,6 +135,7 @@ public class ModeledUserContext extends RestrictedObject
// Init directories
userDirectory.init(currentUser);
+ userGroupDirectory.init(currentUser);
connectionDirectory.init(currentUser);
connectionGroupDirectory.init(currentUser);
sharingProfileDirectory.init(currentUser);
@@ -166,7 +174,7 @@ public class ModeledUserContext extends RestrictedObject
@Override
public Directory getUserGroupDirectory() throws GuacamoleException {
- return new SimpleDirectory();
+ return userGroupDirectory;
}
@Override
@@ -224,7 +232,7 @@ public class ModeledUserContext extends RestrictedObject
@Override
public Collection