From dfb07edf2967a3f3a4317b062786f88b390f8dae Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 19 Apr 2018 14:17:25 -0700 Subject: [PATCH] GUACAMOLE-220: Add base API support for user groups. Refactor as minimally necessary. --- .../sharing/user/SharedAuthenticatedUser.java | 7 + .../auth/jdbc/sharing/user/SharedUser.java | 18 +++ .../jdbc/user/ModeledAuthenticatedUser.java | 5 + .../guacamole/auth/jdbc/user/ModeledUser.java | 19 +++ .../auth/jdbc/user/ModeledUserContext.java | 13 ++ .../net/auth/AbstractAuthenticatedUser.java | 8 ++ .../net/auth/AbstractUserContext.java | 25 ++++ .../guacamole/net/auth/AuthenticatedUser.java | 19 +++ .../guacamole/net/auth/DelegatingUser.java | 16 +++ .../net/auth/DelegatingUserContext.java | 10 ++ .../net/auth/DelegatingUserGroup.java | 125 +++++++++++++++++ .../guacamole/net/auth/Permissions.java | 129 ++++++++++++++++++ .../guacamole/net/auth/RelatedObjectSet.java | 78 +++++++++++ .../org/apache/guacamole/net/auth/User.java | 87 +++--------- .../guacamole/net/auth/UserContext.java | 25 ++++ .../apache/guacamole/net/auth/UserGroup.java | 76 +++++++++++ .../simple/SimpleAuthenticationProvider.java | 7 + .../auth/simple/SimpleRelatedObjectSet.java | 88 ++++++++++++ .../guacamole/net/auth/simple/SimpleUser.java | 18 +++ .../guacamole/rest/user/APIUserWrapper.java | 18 +++ 20 files changed, 720 insertions(+), 71 deletions(-) create mode 100644 guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserGroup.java create mode 100644 guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Permissions.java create mode 100644 guacamole-ext/src/main/java/org/apache/guacamole/net/auth/RelatedObjectSet.java create mode 100644 guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserGroup.java create mode 100644 guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleRelatedObjectSet.java 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 84166c658..958213cbc 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 @@ -19,6 +19,8 @@ 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; @@ -100,4 +102,9 @@ 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/sharing/user/SharedUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUser.java index 8e7931d86..697b2ca7f 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUser.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUser.java @@ -30,10 +30,13 @@ import org.apache.guacamole.net.auth.AuthenticatedUser; import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.net.auth.Directory; +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.SystemPermissionSet; import org.apache.guacamole.net.auth.simple.SimpleObjectPermissionSet; +import org.apache.guacamole.net.auth.simple.SimpleRelatedObjectSet; import org.apache.guacamole.net.auth.simple.SimpleSystemPermissionSet; /** @@ -140,6 +143,11 @@ public class SharedUser implements User { return new SharedObjectPermissionSet(userDirectory.getIdentifiers()); } + @Override + public ObjectPermissionSet getUserGroupPermissions() throws GuacamoleException { + return new SimpleObjectPermissionSet(); + } + @Override public ObjectPermissionSet getSharingProfilePermissions() throws GuacamoleException { return new SimpleObjectPermissionSet(); @@ -150,4 +158,14 @@ public class SharedUser implements User { return new SimpleObjectPermissionSet(); } + @Override + public RelatedObjectSet getUserGroups() throws GuacamoleException { + return new SimpleRelatedObjectSet(); + } + + @Override + public Permissions getEffectivePermissions() throws GuacamoleException { + return this; + } + } 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 6d580baf6..8c201d004 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 @@ -169,4 +169,9 @@ 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 b29565551..583aa7fc1 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 @@ -52,10 +52,14 @@ import org.apache.guacamole.form.TextField; import org.apache.guacamole.form.TimeField; import org.apache.guacamole.form.TimeZoneField; 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; @@ -379,6 +383,11 @@ public class ModeledUser extends ModeledDirectoryObject implements Us 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. @@ -839,4 +848,14 @@ public class ModeledUser extends ModeledDirectoryObject implements Us return userService.retrieveHistory(getCurrentUser(), this); } + @Override + public RelatedObjectSet getUserGroups() throws GuacamoleException { + return new SimpleRelatedObjectSet(); + } + + @Override + public Permissions getEffectivePermissions() throws GuacamoleException { + return this; + } + } 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 5bfcda675..cbc3448a7 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,6 +26,7 @@ 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; @@ -46,6 +47,8 @@ import org.apache.guacamole.net.auth.ConnectionGroup; import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.SharingProfile; import org.apache.guacamole.net.auth.User; +import org.apache.guacamole.net.auth.UserGroup; +import org.apache.guacamole.net.auth.simple.SimpleDirectory; /** * UserContext implementation which is driven by an arbitrary, underlying @@ -161,6 +164,11 @@ public class ModeledUserContext extends RestrictedObject return userDirectory; } + @Override + public Directory getUserGroupDirectory() throws GuacamoleException { + return new SimpleDirectory(); + } + @Override public Directory getConnectionDirectory() throws GuacamoleException { return connectionDirectory; @@ -214,6 +222,11 @@ public class ModeledUserContext extends RestrictedObject return ModeledUser.ATTRIBUTES; } + @Override + public Collection
getUserGroupAttributes() { + return Collections.emptyList(); + } + @Override public Collection getConnectionAttributes() { return ModeledConnection.ATTRIBUTES; diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractAuthenticatedUser.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractAuthenticatedUser.java index 08b9b4e56..681000157 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractAuthenticatedUser.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractAuthenticatedUser.java @@ -19,6 +19,9 @@ package org.apache.guacamole.net.auth; +import java.util.Collections; +import java.util.Set; + /** * Basic implementation of an AuthenticatedUser which uses the username to @@ -29,6 +32,11 @@ public abstract class AbstractAuthenticatedUser extends AbstractIdentifiable // Prior functionality now resides within AbstractIdentifiable + @Override + public Set getEffectiveUserGroups() { + return Collections.emptySet(); + } + @Override public void invalidate() { // Nothing to invalidate diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractUserContext.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractUserContext.java index e2de612e3..eb31f7edb 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractUserContext.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractUserContext.java @@ -67,6 +67,19 @@ public abstract class AbstractUserContext implements UserContext { return new SimpleDirectory(self()); } + /** + * {@inheritDoc} + * + *

This implementation simply returns an empty {@link Directory}. + * Implementations that wish to expose user groups should override this + * function. + */ + @Override + public Directory getUserGroupDirectory() + throws GuacamoleException { + return new SimpleDirectory(); + } + /** * {@inheritDoc} * @@ -181,6 +194,18 @@ public abstract class AbstractUserContext implements UserContext { return Collections.emptyList(); } + /** + * {@inheritDoc} + * + *

This implementation simply returns an empty {@link Collection}. + * Implementations that wish to expose custom user group attributes as + * fields within user group edit screens should override this function. + */ + @Override + public Collection getUserGroupAttributes() { + return Collections.emptyList(); + } + /** * {@inheritDoc} * diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AuthenticatedUser.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AuthenticatedUser.java index f6ceb3abe..c570759c8 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AuthenticatedUser.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AuthenticatedUser.java @@ -19,6 +19,7 @@ package org.apache.guacamole.net.auth; +import java.util.Set; /** * A user of the Guacamole web application who has been authenticated by an @@ -49,6 +50,24 @@ public interface AuthenticatedUser extends Identifiable { */ Credentials getCredentials(); + /** + * Returns a read-only set of the identifiers of all user groups which + * apply to this authenticated user. The exact semantics of what user + * groups apply are up to the implementation, and the user groups within + * this set may be implied, derived dynamically, inherited through multiple + * levels of group membership, etc. + * + * Note that, as with user identifiers, user group identifiers form the + * basis of identity which applies across authentication providers. It is + * expected that any two user groups having the same identifier represent + * the same group, even if defined by different authentication providers + * + * @return + * A read-only set of the identifiers of all user groups which apply + * to this authenticated user. + */ + Set getEffectiveUserGroups(); + /** * Invalidates this authenticated user and their associated token such that * they are no longer logged in. This function will be automatically diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUser.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUser.java index 65f057778..92873c48e 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUser.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUser.java @@ -124,4 +124,20 @@ public class DelegatingUser implements User { return user.getUserPermissions(); } + @Override + public ObjectPermissionSet getUserGroupPermissions() + throws GuacamoleException { + return user.getUserGroupPermissions(); + } + + @Override + public RelatedObjectSet getUserGroups() throws GuacamoleException { + return user.getUserGroups(); + } + + @Override + public Permissions getEffectivePermissions() throws GuacamoleException { + return user.getEffectivePermissions(); + } + } diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserContext.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserContext.java index a37faf952..00788f823 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserContext.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserContext.java @@ -65,6 +65,11 @@ public class DelegatingUserContext implements UserContext { return userContext.getUserDirectory(); } + @Override + public Directory getUserGroupDirectory() throws GuacamoleException { + return userContext.getUserGroupDirectory(); + } + @Override public Directory getConnectionDirectory() throws GuacamoleException { @@ -111,6 +116,11 @@ public class DelegatingUserContext implements UserContext { return userContext.getUserAttributes(); } + @Override + public Collection getUserGroupAttributes() { + return userContext.getUserGroupAttributes(); + } + @Override public Collection getConnectionAttributes() { return userContext.getConnectionAttributes(); diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserGroup.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserGroup.java new file mode 100644 index 000000000..5093a21be --- /dev/null +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserGroup.java @@ -0,0 +1,125 @@ +/* + * 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.net.auth; + +import java.util.Map; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; +import org.apache.guacamole.net.auth.permission.SystemPermissionSet; + +/** + * UserGroup implementation which simply delegates all function calls to an + * underlying UserGroup. + */ +public class DelegatingUserGroup implements UserGroup { + + /** + * The wrapped UserGroup. + */ + private final UserGroup userGroup; + + /** + * Wraps the given UserGroup such that all function calls against this + * DelegatingUserGroup will be delegated to it. + * + * @param userGroup + * The UserGroup to wrap. + */ + public DelegatingUserGroup(UserGroup userGroup) { + this.userGroup = userGroup; + } + + @Override + public String getIdentifier() { + return userGroup.getIdentifier(); + } + + @Override + public void setIdentifier(String identifier) { + userGroup.setIdentifier(identifier); + } + + @Override + public Map getAttributes() { + return userGroup.getAttributes(); + } + + @Override + public void setAttributes(Map attributes) { + userGroup.setAttributes(attributes); + } + + @Override + public SystemPermissionSet getSystemPermissions() + throws GuacamoleException { + return userGroup.getSystemPermissions(); + } + + @Override + public ObjectPermissionSet getConnectionPermissions() + throws GuacamoleException { + return userGroup.getConnectionPermissions(); + } + + @Override + public ObjectPermissionSet getConnectionGroupPermissions() + throws GuacamoleException { + return userGroup.getConnectionGroupPermissions(); + } + + @Override + public ObjectPermissionSet getSharingProfilePermissions() + throws GuacamoleException { + return userGroup.getSharingProfilePermissions(); + } + + @Override + public ObjectPermissionSet getActiveConnectionPermissions() + throws GuacamoleException { + return userGroup.getActiveConnectionPermissions(); + } + + @Override + public ObjectPermissionSet getUserPermissions() throws GuacamoleException { + return userGroup.getUserPermissions(); + } + + @Override + public ObjectPermissionSet getUserGroupPermissions() + throws GuacamoleException { + return userGroup.getUserGroupPermissions(); + } + + @Override + public RelatedObjectSet getUserGroups() throws GuacamoleException { + return userGroup.getUserGroups(); + } + + @Override + public RelatedObjectSet getMemberUsers() throws GuacamoleException { + return userGroup.getMemberUsers(); + } + + @Override + public RelatedObjectSet getMemberUserGroups() throws GuacamoleException { + return userGroup.getMemberUserGroups(); + } + +} diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Permissions.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Permissions.java new file mode 100644 index 000000000..3b698bef7 --- /dev/null +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Permissions.java @@ -0,0 +1,129 @@ +/* + * 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.net.auth; + +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; +import org.apache.guacamole.net.auth.permission.SystemPermissionSet; + +/** + * An object which may be granted permissions to access/manipulate various + * other objects or aspects of the system. The permissions granted are exposed + * through subclasses of PermissionSet, and may be mutable depending on the + * access level of the current user. + */ +public interface Permissions { + + /** + * Returns all permissions given to this object regarding currently-active + * connections. + * + * @return + * An ObjectPermissionSet of all active connection permissions granted + * to this object. + * + * @throws GuacamoleException + * If an error occurs while retrieving permissions, or if reading all + * permissions is not allowed. + */ + ObjectPermissionSet getActiveConnectionPermissions() + throws GuacamoleException; + + /** + * Returns all connection group permissions given to this object. + * + * @return + * An ObjectPermissionSet of all connection group permissions granted + * to this object. + * + * @throws GuacamoleException + * If an error occurs while retrieving permissions, or if reading all + * permissions is not allowed. + */ + ObjectPermissionSet getConnectionGroupPermissions() + throws GuacamoleException; + + /** + * Returns all connection permissions given to this object. + * + * @return + * An ObjectPermissionSet of all connection permissions granted to this + * object. + * + * @throws GuacamoleException + * If an error occurs while retrieving permissions, or if reading all + * permissions is not allowed. + */ + ObjectPermissionSet getConnectionPermissions() throws GuacamoleException; + + /** + * Returns all sharing profile permissions given to this object. + * + * @return + * An ObjectPermissionSet of all sharing profile permissions granted to + * this object. + * + * @throws GuacamoleException + * If an error occurs while retrieving permissions, or if reading all + * permissions is not allowed. + */ + ObjectPermissionSet getSharingProfilePermissions() + throws GuacamoleException; + + /** + * Returns all system-level permissions given to this object. + * + * @return + * A SystemPermissionSet of all system-level permissions granted to + * this object. + * + * @throws GuacamoleException + * If an error occurs while retrieving permissions, or if reading all + * permissions is not allowed. + */ + SystemPermissionSet getSystemPermissions() throws GuacamoleException; + + /** + * Returns all user permissions given to this object. + * + * @return + * An ObjectPermissionSet of all user permissions granted to this + * object. + * + * @throws GuacamoleException + * If an error occurs while retrieving permissions, or if reading all + * permissions is not allowed. + */ + ObjectPermissionSet getUserPermissions() throws GuacamoleException; + + /** + * Returns all user group permissions given to this object. + * + * @return + * An ObjectPermissionSet of all user group permissions granted to this + * object. + * + * @throws GuacamoleException + * If an error occurs while retrieving permissions, or if reading all + * permissions is not allowed. + */ + ObjectPermissionSet getUserGroupPermissions() throws GuacamoleException; + +} diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/RelatedObjectSet.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/RelatedObjectSet.java new file mode 100644 index 000000000..58bee372e --- /dev/null +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/RelatedObjectSet.java @@ -0,0 +1,78 @@ +/* + * 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.net.auth; + +import java.util.Set; +import org.apache.guacamole.GuacamoleException; + +/** + * An arbitrary set of existing objects sharing some common relation. Unlike a + * Directory, which provides for maintaining the entire lifecycle of its + * objects, a RelatedObjectSet only maintains the relation between its + * containing object and the objects within the set. Adding/removing an object + * from a RelatedObjectSet affects only the status of the specific relationship + * represented by the RelatedObjectSet, not the existence of the objects + * themselves. + */ +public interface RelatedObjectSet { + + /** + * Returns a Set which contains the identifiers of all objects contained + * within this RelatedObjectSet. + * + * @return + * A Set which contains the identifiers of all objects contained + * within this RelatedObjectSet. + * + * @throws GuacamoleException + * If an error occurs while retrieving the objects within the set, or + * if objects cannot be retrieved due to lack of permissions to do so. + */ + Set getObjects() throws GuacamoleException; + + /** + * Adds the objects having the given identifiers, if not already present. + * If a specified object is already present, no operation is performed + * regarding that object. + * + * @param identifiers + * The identifiers of all objects being added. + * + * @throws GuacamoleException + * If an error occurs while adding the objects, or if permission to add + * objects is denied. + */ + void addObjects(Set identifiers) throws GuacamoleException; + + /** + * Removes each of the objects having the specified identifiers, if + * present. If a specified object is not present, no operation is performed + * regarding that object. + * + * @param identifiers + * The identifiers of all objects being removed. + * + * @throws GuacamoleException + * If an error occurs while removing the objects, or if permission to + * remove objects is denied. + */ + void removeObjects(Set identifiers) throws GuacamoleException; + +} diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java index a39a772f0..45b5ff97b 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java @@ -22,14 +22,11 @@ package org.apache.guacamole.net.auth; import java.util.Date; import java.util.List; import org.apache.guacamole.GuacamoleException; -import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; -import org.apache.guacamole.net.auth.permission.SystemPermissionSet; - /** * A user of the Guacamole web application. */ -public interface User extends Identifiable, Attributes { +public interface User extends Identifiable, Attributes, Permissions { /** * All standard attribute names with semantics defined by the Guacamole web @@ -109,85 +106,33 @@ public interface User extends Identifiable, Attributes { List getHistory() throws GuacamoleException; /** - * Returns all system-level permissions given to this user. + * Returns a set of all readable user groups of which this user is a member. + * If permission is granted for the current user to modify the membership of + * this user, then the returned set will be mutable, and any such + * modifications should be made through changes to the returned set. * * @return - * A SystemPermissionSet of all system-level permissions granted to - * this user. + * The set of all readable user groups of which this user is a member. * - * @throws GuacamoleException - * If an error occurs while retrieving permissions, or if reading all - * permissions is not allowed. + * @throws GuacamoleException + * If an error occurs while retrieving the user groups. */ - SystemPermissionSet getSystemPermissions() throws GuacamoleException; + RelatedObjectSet getUserGroups() throws GuacamoleException; /** - * Returns all connection permissions given to this user. + * Returns a read-only view of all permissions granted to this user. The + * exact semantics of what permissions are granted are up to the + * implementation, and the permissions within this view may implied, + * derived dynamically, inherited through multiple levels of group + * membership, etc. * * @return - * An ObjectPermissionSet of all connection permissions granted to this - * user. - * - * @throws GuacamoleException - * If an error occurs while retrieving permissions, or if reading all - * permissions is not allowed. - */ - ObjectPermissionSet getConnectionPermissions() - throws GuacamoleException; - - /** - * Returns all connection group permissions given to this user. - * - * @return - * An ObjectPermissionSet of all connection group permissions granted - * to this user. + * A read-only view of the permissions which are granted to this user. * * @throws GuacamoleException * If an error occurs while retrieving permissions, or if reading all * permissions is not allowed. */ - ObjectPermissionSet getConnectionGroupPermissions() - throws GuacamoleException; - - /** - * Returns all sharing profile permissions given to this user. - * - * @return - * An ObjectPermissionSet of all sharing profile permissions granted to - * this user. - * - * @throws GuacamoleException - * If an error occurs while retrieving permissions, or if reading all - * permissions is not allowed. - */ - ObjectPermissionSet getSharingProfilePermissions() - throws GuacamoleException; - - /** - * Returns all permissions given to this user regarding currently-active - * connections. - * - * @return - * An ObjectPermissionSet of all active connection permissions granted - * to this user. - * - * @throws GuacamoleException - * If an error occurs while retrieving permissions, or if reading all - * permissions is not allowed. - */ - ObjectPermissionSet getActiveConnectionPermissions() - throws GuacamoleException; - - /** - * Returns all user permissions given to this user. - * - * @return - * An ObjectPermissionSet of all user permissions granted to this user. - * - * @throws GuacamoleException - * If an error occurs while retrieving permissions, or if reading all - * permissions is not allowed. - */ - ObjectPermissionSet getUserPermissions() throws GuacamoleException; + Permissions getEffectivePermissions() throws GuacamoleException; } diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserContext.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserContext.java index 1c82f9ce8..ea7c8c40e 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserContext.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserContext.java @@ -84,6 +84,20 @@ public interface UserContext { */ Directory getUserDirectory() throws GuacamoleException; + /** + * Retrieves a Directory which can be used to view and manipulate user + * groups, but only as allowed by the permissions given to the user of this + * UserContext. + * + * @return + * A Directory whose operations are bound by the restrictions + * of this UserContext. + * + * @throws GuacamoleException + * If an error occurs while creating the Directory. + */ + Directory getUserGroupDirectory() throws GuacamoleException; + /** * Retrieves a Directory which can be used to view and manipulate * connections and their configurations, but only as allowed by the @@ -197,6 +211,17 @@ public interface UserContext { */ Collection getUserAttributes(); + /** + * Retrieves a collection of all attributes applicable to user groups. This + * collection will contain only those attributes which the current user has + * general permission to view or modify. If there are no such attributes, + * this collection will be empty. + * + * @return + * A collection of all attributes applicable to user groups. + */ + Collection getUserGroupAttributes(); + /** * Retrieves a collection of all attributes applicable to connections. This * collection will contain only those attributes which the current user has diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserGroup.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserGroup.java new file mode 100644 index 000000000..6c59a2004 --- /dev/null +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserGroup.java @@ -0,0 +1,76 @@ +/* + * 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.net.auth; + +import org.apache.guacamole.GuacamoleException; + +/** + * A user group of the Guacamole web application. Each user group may contain + * any number of Guacamole users and other user groups, and defines the + * permissions implicitly granted to its members. + */ +public interface UserGroup extends Identifiable, Attributes, Permissions { + + /** + * Returns a set of all readable user groups that are members of this user + * group. If permission is granted for the current user to modify the + * members of this group, then the returned set will be mutable, and any + * such modifications should be made through changes to the returned set. + * + * @return + * The set of all readable user groups that are members of this user + * group, which may be mutable. + * + * @throws GuacamoleException + * If an error occurs while retrieving the user groups. + */ + RelatedObjectSet getUserGroups() throws GuacamoleException; + + /** + * Returns a set of all readable users that are members of this user group. + * If permission is granted for the current user to modify the members of + * this group, then the returned set will be mutable, and any such + * modifications should be made through changes to the returned set. + * + * @return + * The set all readable users that are members of this user group, + * which may be mutable. + * + * @throws GuacamoleException + * If an error occurs while retrieving the users. + */ + RelatedObjectSet getMemberUsers() throws GuacamoleException; + + /** + * Returns a set of all readable user groups that are members of this user + * group. If permission is granted for the current user to modify the + * members of this group, then the returned set will be mutable, and any + * such modifications should be made through changes to the returned set. + * + * @return + * The set of all readable user groups that are members of this user + * group, which may be mutable. + * + * @throws GuacamoleException + * If an error occurs while retrieving the user groups. + */ + RelatedObjectSet getMemberUserGroups() throws GuacamoleException; + +} diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleAuthenticationProvider.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleAuthenticationProvider.java index 837f1d701..7b1e3e7f0 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleAuthenticationProvider.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleAuthenticationProvider.java @@ -19,7 +19,9 @@ package org.apache.guacamole.net.auth.simple; +import java.util.Collections; import java.util.Map; +import java.util.Set; import java.util.UUID; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.net.auth.AbstractAuthenticatedUser; @@ -131,6 +133,11 @@ public abstract class SimpleAuthenticationProvider return credentials; } + @Override + public Set getEffectiveUserGroups() { + return Collections.emptySet(); + } + } /** diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleRelatedObjectSet.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleRelatedObjectSet.java new file mode 100644 index 000000000..72f2da9f1 --- /dev/null +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleRelatedObjectSet.java @@ -0,0 +1,88 @@ +/* + * 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.net.auth.simple; + +import java.util.Collections; +import java.util.Set; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.GuacamoleSecurityException; +import org.apache.guacamole.net.auth.RelatedObjectSet; + +/** + * A read-only implementation of RelatedObjectSet which uses a backing Set + * of identifiers to determine which objects are present. + */ +public class SimpleRelatedObjectSet implements RelatedObjectSet { + + /** + * A set containing the identifiers of all objects currently present. + */ + private Set identifiers = Collections.emptySet(); + + /** + * Creates a new empty SimpleObjectPermissionSet. + */ + public SimpleRelatedObjectSet() { + } + + /** + * Creates a new SimpleRelatedObjectSet which contains the objects having + * the identifiers within the given Set. The given Set backs the contents + * of the new SimpleRelatedObjectSet. While the SimpleRelatedObjectSet is + * read-only, any changes to the underlying Set will be reflected in the + * SimpleRelatedObjectSet. + * + * @param identifiers + * The Set containing the identifiers of all objects which should be + * present within the new SimpleRelatedObjectSet. + */ + public SimpleRelatedObjectSet(Set identifiers) { + this.identifiers = identifiers; + } + + /** + * Replaces the Set of object identifiers which backs this + * SimpleRelatedObjectSet. Future function calls on this + * SimpleRelatedObjectSet will instead use the provided Set. + * + * @param identifiers + * The Set containing the identifiers of all objects which should be + * present within this SimpleRelatedObjectSet. + */ + protected void setObjects(Set identifiers) { + this.identifiers = identifiers; + } + + @Override + public Set getObjects() { + return identifiers; + } + + @Override + public void addObjects(Set identifiers) throws GuacamoleException { + throw new GuacamoleSecurityException("Permission denied."); + } + + @Override + public void removeObjects(Set identifiers) throws GuacamoleException { + throw new GuacamoleSecurityException("Permission denied."); + } + +} diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleUser.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleUser.java index 19ed35731..61fce20f4 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleUser.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleUser.java @@ -29,6 +29,8 @@ import java.util.Set; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.net.auth.AbstractUser; 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.permission.ObjectPermission; import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; import org.apache.guacamole.net.auth.permission.SystemPermissionSet; @@ -200,6 +202,12 @@ public class SimpleUser extends AbstractUser { return new SimpleObjectPermissionSet(userPermissions); } + @Override + public ObjectPermissionSet getUserGroupPermissions() + throws GuacamoleException { + return new SimpleObjectPermissionSet(); + } + @Override public ObjectPermissionSet getActiveConnectionPermissions() throws GuacamoleException { @@ -211,4 +219,14 @@ public class SimpleUser extends AbstractUser { return new SimpleObjectPermissionSet(); } + @Override + public RelatedObjectSet getUserGroups() throws GuacamoleException { + return new SimpleRelatedObjectSet(); + } + + @Override + public Permissions getEffectivePermissions() throws GuacamoleException { + return this; + } + } diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/user/APIUserWrapper.java b/guacamole/src/main/java/org/apache/guacamole/rest/user/APIUserWrapper.java index c4b85f9ae..c4375668d 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/user/APIUserWrapper.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/user/APIUserWrapper.java @@ -26,6 +26,8 @@ import java.util.Map; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleUnsupportedException; 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.SystemPermissionSet; @@ -110,12 +112,28 @@ public class APIUserWrapper implements User { throw new GuacamoleUnsupportedException("APIUserWrapper does not provide permission access."); } + @Override + public ObjectPermissionSet getUserGroupPermissions() + throws GuacamoleException { + throw new GuacamoleUnsupportedException("APIUserWrapper does not provide permission access."); + } + @Override public ObjectPermissionSet getActiveConnectionPermissions() throws GuacamoleException { throw new GuacamoleUnsupportedException("APIUserWrapper does not provide permission access."); } + @Override + public Permissions getEffectivePermissions() throws GuacamoleException { + throw new GuacamoleUnsupportedException("APIUserWrapper does not provide permission access."); + } + + @Override + public RelatedObjectSet getUserGroups() throws GuacamoleException { + throw new GuacamoleUnsupportedException("APIUserWrapper does not provide group access."); + } + @Override public Date getLastActive() { return null;