Repository: guacamole-client
Updated Branches:
  refs/heads/master 456ad7f28 -> 1ac08257b


GUACAMOLE-220: Add base API support for user groups. Refactor as minimally 
necessary.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/dfb07edf
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/dfb07edf
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/dfb07edf

Branch: refs/heads/master
Commit: dfb07edf2967a3f3a4317b062786f88b390f8dae
Parents: aac9d87
Author: Michael Jumper <[email protected]>
Authored: Thu Apr 19 14:17:25 2018 -0700
Committer: Michael Jumper <[email protected]>
Committed: Thu Apr 19 15:29:10 2018 -0700

----------------------------------------------------------------------
 .../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 ++
 .../guacamole/net/auth/AbstractUserContext.java |  25 ++++
 .../guacamole/net/auth/AuthenticatedUser.java   |  19 +++
 .../guacamole/net/auth/DelegatingUser.java      |  16 +++
 .../net/auth/DelegatingUserContext.java         |  10 ++
 .../guacamole/net/auth/DelegatingUserGroup.java | 125 ++++++++++++++++++
 .../apache/guacamole/net/auth/Permissions.java  | 129 +++++++++++++++++++
 .../guacamole/net/auth/RelatedObjectSet.java    |  78 +++++++++++
 .../org/apache/guacamole/net/auth/User.java     |  85 +++---------
 .../apache/guacamole/net/auth/UserContext.java  |  25 ++++
 .../apache/guacamole/net/auth/UserGroup.java    |  76 +++++++++++
 .../simple/SimpleAuthenticationProvider.java    |   7 +
 .../net/auth/simple/SimpleRelatedObjectSet.java |  88 +++++++++++++
 .../guacamole/net/auth/simple/SimpleUser.java   |  18 +++
 .../guacamole/rest/user/APIUserWrapper.java     |  18 +++
 20 files changed, 719 insertions(+), 70 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedAuthenticatedUser.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 84166c6..958213c 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<String> getEffectiveUserGroups() {
+        return Collections.<String>emptySet();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUser.java
----------------------------------------------------------------------
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 8e7931d..697b2ca 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;
 
 /**
@@ -141,6 +144,11 @@ public class SharedUser implements User {
     }
 
     @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;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledAuthenticatedUser.java
----------------------------------------------------------------------
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 6d580ba..8c201d0 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<String> getEffectiveUserGroups() {
+        return Collections.<String>emptySet();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
----------------------------------------------------------------------
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 b295655..583aa7f 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<UserModel> 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<UserModel> implements Us
         return userService.retrieveHistory(getCurrentUser(), this);
     }
 
+    @Override
+    public RelatedObjectSet getUserGroups() throws GuacamoleException {
+        return new SimpleRelatedObjectSet();
+    }
+
+    @Override
+    public Permissions getEffectivePermissions() throws GuacamoleException {
+        return this;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUserContext.java
----------------------------------------------------------------------
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 5bfcda6..cbc3448 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
@@ -162,6 +165,11 @@ public class ModeledUserContext extends RestrictedObject
     }
 
     @Override
+    public Directory<UserGroup> getUserGroupDirectory() throws 
GuacamoleException {
+        return new SimpleDirectory<UserGroup>();
+    }
+
+    @Override
     public Directory<Connection> getConnectionDirectory() throws 
GuacamoleException {
         return connectionDirectory;
     }
@@ -215,6 +223,11 @@ public class ModeledUserContext extends RestrictedObject
     }
 
     @Override
+    public Collection<Form> getUserGroupAttributes() {
+        return Collections.<Form>emptyList();
+    }
+
+    @Override
     public Collection<Form> getConnectionAttributes() {
         return ModeledConnection.ATTRIBUTES;
     }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractAuthenticatedUser.java
----------------------------------------------------------------------
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 08b9b4e..6810001 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
@@ -30,6 +33,11 @@ public abstract class AbstractAuthenticatedUser extends 
AbstractIdentifiable
     // Prior functionality now resides within AbstractIdentifiable
 
     @Override
+    public Set<String> getEffectiveUserGroups() {
+        return Collections.<String>emptySet();
+    }
+
+    @Override
     public void invalidate() {
         // Nothing to invalidate
     }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractUserContext.java
----------------------------------------------------------------------
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 e2de612..eb31f7e 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
@@ -71,6 +71,19 @@ public abstract class AbstractUserContext implements 
UserContext {
      * {@inheritDoc}
      *
      * <p>This implementation simply returns an empty {@link Directory}.
+     * Implementations that wish to expose user groups should override this
+     * function.
+     */
+    @Override
+    public Directory<UserGroup> getUserGroupDirectory()
+            throws GuacamoleException {
+        return new SimpleDirectory<UserGroup>();
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>This implementation simply returns an empty {@link Directory}.
      * Implementations that wish to expose connections should override this
      * function.
      */
@@ -185,6 +198,18 @@ public abstract class AbstractUserContext implements 
UserContext {
      * {@inheritDoc}
      *
      * <p>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<Form> getUserGroupAttributes() {
+        return Collections.<Form>emptyList();
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>This implementation simply returns an empty {@link Collection}.
      * Implementations that wish to expose custom connection attributes as
      * fields within connection edit screens should override this function.
      */

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AuthenticatedUser.java
----------------------------------------------------------------------
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 f6ceb3a..c570759 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
@@ -50,6 +51,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<String> getEffectiveUserGroups();
+
+    /**
      * Invalidates this authenticated user and their associated token such that
      * they are no longer logged in. This function will be automatically
      * invoked when the user logs out, or when their session expires.

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUser.java
----------------------------------------------------------------------
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 65f0577..92873c4 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();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserContext.java
----------------------------------------------------------------------
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 a37faf9..00788f8 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
@@ -66,6 +66,11 @@ public class DelegatingUserContext implements UserContext {
     }
 
     @Override
+    public Directory<UserGroup> getUserGroupDirectory() throws 
GuacamoleException {
+        return userContext.getUserGroupDirectory();
+    }
+
+    @Override
     public Directory<Connection> getConnectionDirectory()
             throws GuacamoleException {
         return userContext.getConnectionDirectory();
@@ -112,6 +117,11 @@ public class DelegatingUserContext implements UserContext {
     }
 
     @Override
+    public Collection<Form> getUserGroupAttributes() {
+        return userContext.getUserGroupAttributes();
+    }
+
+    @Override
     public Collection<Form> getConnectionAttributes() {
         return userContext.getConnectionAttributes();
     }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUserGroup.java
----------------------------------------------------------------------
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 0000000..5093a21
--- /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<String, String> getAttributes() {
+        return userGroup.getAttributes();
+    }
+
+    @Override
+    public void setAttributes(Map<String, String> 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();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Permissions.java
----------------------------------------------------------------------
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 0000000..3b698be
--- /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;
+
+}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/RelatedObjectSet.java
----------------------------------------------------------------------
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 0000000..58bee37
--- /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<String> 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<String> 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<String> identifiers) throws GuacamoleException;
+
+}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java
----------------------------------------------------------------------
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 a39a772..45b5ff9 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<? extends ActivityRecord> getHistory() throws GuacamoleException;
 
     /**
-     * Returns all system-level permissions given to this user.
-     *
-     * @return
-     *     A SystemPermissionSet of all system-level permissions granted to
-     *     this user.
-     *
-     * @throws GuacamoleException 
-     *     If an error occurs while retrieving permissions, or if reading all
-     *     permissions is not allowed.
-     */
-    SystemPermissionSet getSystemPermissions() throws GuacamoleException;
-
-    /**
-     * Returns all connection permissions given to this user.
-     *
-     * @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.
-     *
-     * @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.
+     * 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
-     *     An ObjectPermissionSet of all sharing profile 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.
-     */
-    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.
+     *     If an error occurs while retrieving the user groups.
      */
-    ObjectPermissionSet getActiveConnectionPermissions()
-            throws GuacamoleException;
+    RelatedObjectSet getUserGroups() throws GuacamoleException;
 
     /**
-     * Returns all user 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 user 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 getUserPermissions() throws GuacamoleException;
+    Permissions getEffectivePermissions() throws GuacamoleException;
 
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserContext.java
----------------------------------------------------------------------
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 1c82f9c..ea7c8c4 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
@@ -85,6 +85,20 @@ public interface UserContext {
     Directory<User> 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<UserGroup> getUserGroupDirectory() throws GuacamoleException;
+
+    /**
      * Retrieves a Directory which can be used to view and manipulate
      * connections and their configurations, but only as allowed by the
      * permissions given to the user.
@@ -198,6 +212,17 @@ public interface UserContext {
     Collection<Form> 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<Form> getUserGroupAttributes();
+
+    /**
      * Retrieves a collection of all attributes applicable to connections. This
      * collection will contain only those attributes which the current user has
      * general permission to view or modify. If there are no such attributes,

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/UserGroup.java
----------------------------------------------------------------------
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 0000000..6c59a20
--- /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;
+
+}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleAuthenticationProvider.java
----------------------------------------------------------------------
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 837f1d7..7b1e3e7 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<String> getEffectiveUserGroups() {
+            return Collections.<String>emptySet();
+        }
+
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleRelatedObjectSet.java
----------------------------------------------------------------------
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 0000000..72f2da9
--- /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<String> identifiers = Collections.<String>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<String> 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<String> identifiers) {
+        this.identifiers = identifiers;
+    }
+
+    @Override
+    public Set<String> getObjects() {
+        return identifiers;
+    }
+
+    @Override
+    public void addObjects(Set<String> identifiers) throws GuacamoleException {
+        throw new GuacamoleSecurityException("Permission denied.");
+    }
+
+    @Override
+    public void removeObjects(Set<String> identifiers) throws 
GuacamoleException {
+        throw new GuacamoleSecurityException("Permission denied.");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleUser.java
----------------------------------------------------------------------
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 19ed357..61fce20 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;
@@ -201,6 +203,12 @@ public class SimpleUser extends AbstractUser {
     }
 
     @Override
+    public ObjectPermissionSet getUserGroupPermissions()
+            throws GuacamoleException {
+        return new SimpleObjectPermissionSet();
+    }
+
+    @Override
     public ObjectPermissionSet getActiveConnectionPermissions()
             throws GuacamoleException {
         return new SimpleObjectPermissionSet();
@@ -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;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/dfb07edf/guacamole/src/main/java/org/apache/guacamole/rest/user/APIUserWrapper.java
----------------------------------------------------------------------
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 c4b85f9..c437566 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;
@@ -111,12 +113,28 @@ public class APIUserWrapper implements User {
     }
 
     @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;
     }

Reply via email to