You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by jm...@apache.org on 2016/08/21 04:04:25 UTC

[2/3] incubator-guacamole-client git commit: GUACAMOLE-81: Generalize permissions surrounding parent/child relationship.

GUACAMOLE-81: Generalize permissions surrounding parent/child relationship.


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

Branch: refs/heads/master
Commit: 26d9dd85935bd526b3ddb954709b7a10cbfea3cd
Parents: 39a25db
Author: Michael Jumper <mj...@apache.org>
Authored: Sat Aug 20 18:03:32 2016 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Sat Aug 20 19:13:01 2016 -0700

----------------------------------------------------------------------
 .../auth/jdbc/base/ChildObjectModel.java        |  65 ++++++
 .../auth/jdbc/base/GroupedObjectModel.java      |  64 ------
 .../jdbc/base/ModeledChildDirectoryObject.java  |  75 +++++++
 .../ModeledChildDirectoryObjectService.java     | 209 +++++++++++++++++++
 .../base/ModeledGroupedDirectoryObject.java     |  75 -------
 .../ModeledGroupedDirectoryObjectService.java   | 194 -----------------
 .../auth/jdbc/connection/ConnectionModel.java   |   4 +-
 .../auth/jdbc/connection/ConnectionService.java |  13 +-
 .../auth/jdbc/connection/ModeledConnection.java |   4 +-
 .../connectiongroup/ConnectionGroupModel.java   |   4 +-
 .../connectiongroup/ConnectionGroupService.java |  13 +-
 .../connectiongroup/ModeledConnectionGroup.java |   4 +-
 12 files changed, 379 insertions(+), 345 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ChildObjectModel.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ChildObjectModel.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ChildObjectModel.java
new file mode 100644
index 0000000..5a458ca
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ChildObjectModel.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.guacamole.auth.jdbc.base;
+
+/**
+ * Object representation of a Guacamole object which can be the child of another
+ * object, such as a connection or sharing profile, as represented in the
+ * database.
+ *
+ * @author Michael Jumper
+ */
+public abstract class ChildObjectModel extends ObjectModel {
+
+    /**
+     * The unique identifier which identifies the parent of this object.
+     */
+    private String parentIdentifier;
+    
+    /**
+     * Creates a new, empty object.
+     */
+    public ChildObjectModel() {
+    }
+
+    /**
+     * Returns the identifier of the parent connection group, or null if the
+     * parent connection group is the root connection group.
+     *
+     * @return 
+     *     The identifier of the parent connection group, or null if the parent
+     *     connection group is the root connection group.
+     */
+    public String getParentIdentifier() {
+        return parentIdentifier;
+    }
+
+    /**
+     * Sets the identifier of the parent connection group.
+     *
+     * @param parentIdentifier
+     *     The identifier of the parent connection group, or null if the parent
+     *     connection group is the root connection group.
+     */
+    public void setParentIdentifier(String parentIdentifier) {
+        this.parentIdentifier = parentIdentifier;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/GroupedObjectModel.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/GroupedObjectModel.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/GroupedObjectModel.java
deleted file mode 100644
index 18dffee..0000000
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/GroupedObjectModel.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.guacamole.auth.jdbc.base;
-
-/**
- * Object representation of a Guacamole object, such as a user or connection,
- * as represented in the database.
- *
- * @author Michael Jumper
- */
-public abstract class GroupedObjectModel extends ObjectModel {
-
-    /**
-     * The unique identifier which identifies the parent of this object.
-     */
-    private String parentIdentifier;
-    
-    /**
-     * Creates a new, empty object.
-     */
-    public GroupedObjectModel() {
-    }
-
-    /**
-     * Returns the identifier of the parent connection group, or null if the
-     * parent connection group is the root connection group.
-     *
-     * @return 
-     *     The identifier of the parent connection group, or null if the parent
-     *     connection group is the root connection group.
-     */
-    public String getParentIdentifier() {
-        return parentIdentifier;
-    }
-
-    /**
-     * Sets the identifier of the parent connection group.
-     *
-     * @param parentIdentifier
-     *     The identifier of the parent connection group, or null if the parent
-     *     connection group is the root connection group.
-     */
-    public void setParentIdentifier(String parentIdentifier) {
-        this.parentIdentifier = parentIdentifier;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObject.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObject.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObject.java
new file mode 100644
index 0000000..f086112
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObject.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.guacamole.auth.jdbc.base;
+
+import org.apache.guacamole.auth.jdbc.connectiongroup.RootConnectionGroup;
+
+/**
+ * Common base class for objects that will ultimately be made available through
+ * the Directory class. All such objects will need the same base set of queries
+ * to fulfill the needs of the Directory class.
+ *
+ * @author Michael Jumper
+ * @param <ModelType>
+ *     The type of model object that corresponds to this object.
+ */
+public abstract class ModeledChildDirectoryObject<ModelType extends ChildObjectModel>
+    extends ModeledDirectoryObject<ModelType> {
+
+    /**
+     * Returns the identifier of the parent connection group, which cannot be
+     * null. If the parent is the root connection group, this will be
+     * RootConnectionGroup.IDENTIFIER.
+     *
+     * @return
+     *     The identifier of the parent connection group.
+     */
+    public String getParentIdentifier() {
+
+        // Translate null parent to proper identifier
+        String parentIdentifier = getModel().getParentIdentifier();
+        if (parentIdentifier == null)
+            return RootConnectionGroup.IDENTIFIER;
+
+        return parentIdentifier;
+        
+    }
+
+    /**
+     * Sets the identifier of the associated parent connection group. If the
+     * parent is the root connection group, this should be
+     * RootConnectionGroup.IDENTIFIER.
+     * 
+     * @param parentIdentifier
+     *     The identifier of the connection group to associate as this object's
+     *     parent.
+     */
+    public void setParentIdentifier(String parentIdentifier) {
+
+        // Translate root identifier back into null
+        if (parentIdentifier != null
+                && parentIdentifier.equals(RootConnectionGroup.IDENTIFIER))
+            parentIdentifier = null;
+
+        getModel().setParentIdentifier(parentIdentifier);
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObjectService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObjectService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObjectService.java
new file mode 100644
index 0000000..61f48d4
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledChildDirectoryObjectService.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.guacamole.auth.jdbc.base;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleSecurityException;
+import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
+import org.apache.guacamole.net.auth.Identifiable;
+import org.apache.guacamole.net.auth.permission.ObjectPermission;
+import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
+
+/**
+ * Service which provides convenience methods for creating, retrieving, and
+ * manipulating objects that can be children of other objects. This service will
+ * automatically enforce the permissions of the current user.
+ *
+ * @author Michael Jumper
+ * @param <InternalType>
+ *     The specific internal implementation of the type of object this service
+ *     provides access to.
+ *
+ * @param <ExternalType>
+ *     The external interface or implementation of the type of object this
+ *     service provides access to, as defined by the guacamole-ext API.
+ *
+ * @param <ModelType>
+ *     The underlying model object used to represent InternalType in the
+ *     database.
+ */
+public abstract class ModeledChildDirectoryObjectService<InternalType extends ModeledChildDirectoryObject<ModelType>,
+        ExternalType extends Identifiable, ModelType extends ChildObjectModel>
+        extends ModeledDirectoryObjectService<InternalType, ExternalType, ModelType> {
+
+    /**
+     * Returns the permission set associated with the given user and related
+     * to the type of objects which can be parents of the child objects handled
+     * by this directory object service.
+     *
+     * @param user
+     *     The user whose permissions are being retrieved.
+     *
+     * @return
+     *     A permission set which contains the permissions associated with the
+     *     given user and related to the type of objects which can be parents
+     *     of the child objects handled by this directory object service.
+     *
+     * @throws GuacamoleException
+     *     If permission to read the user's permissions is denied.
+     */
+    protected abstract ObjectPermissionSet getParentPermissionSet(
+            ModeledAuthenticatedUser user) throws GuacamoleException;
+
+    /**
+     * Returns the set of parent objects that are modified by the given model
+     * object (by virtue of the object changing parents). If the model is not
+     * changing parents, the resulting collection will be empty.
+     *
+     * @param user
+     *     The user making the given changes to the model.
+     *
+     * @param identifier
+     *     The identifier of the object that has been modified, if it exists.
+     *     If the object is being created, this will be null.
+     *
+     * @param model
+     *     The model that has been modified, if any. If the object is being
+     *     deleted, this will be null.
+     *
+     * @return
+     *     A collection of the identifiers of all parents that will be affected
+     *     (updated) by the change.
+     *
+     * @throws GuacamoleException
+     *     If an error occurs while determining which parents are affected.
+     */
+    protected Collection<String> getModifiedParents(ModeledAuthenticatedUser user,
+            String identifier, ModelType model) throws GuacamoleException {
+
+        // Get old parent identifier
+        String oldParentIdentifier = null;
+        if (identifier != null) {
+            ModelType current = retrieveObject(user, identifier).getModel();
+            oldParentIdentifier = current.getParentIdentifier();
+        }
+
+        // Get new parent identifier
+        String parentIdentifier = null;
+        if (model != null) {
+
+            parentIdentifier = model.getParentIdentifier();
+
+            // If both parents have the same identifier, nothing has changed
+            if (parentIdentifier != null && parentIdentifier.equals(oldParentIdentifier))
+                return Collections.<String>emptyList();
+
+        }
+
+        // Return collection of all non-root parents involved
+        Collection<String> parents = new ArrayList<String>(2);
+        if (oldParentIdentifier != null) parents.add(oldParentIdentifier);
+        if (parentIdentifier    != null) parents.add(parentIdentifier);
+        return parents;
+
+    }
+
+    /**
+     * Returns whether the given user has permission to modify the parents
+     * affected by the modifications made to the given model object.
+     *
+     * @param user
+     *     The user who changed the model object.
+     *
+     * @param identifier
+     *     The identifier of the object that has been modified, if it exists.
+     *     If the object is being created, this will be null.
+     *
+     * @param model
+     *     The model that has been modified, if any. If the object is being
+     *     deleted, this will be null.
+     *
+     * @return
+     *     true if the user has update permission for all modified parents,
+     *     false otherwise.
+     *
+     * @throws GuacamoleException
+     *     If an error occurs while determining which parents are affected.
+     */
+    protected boolean canUpdateModifiedParents(ModeledAuthenticatedUser user,
+            String identifier, ModelType model) throws GuacamoleException {
+
+        // If user is an administrator, no need to check
+        if (user.getUser().isAdministrator())
+            return true;
+        
+        // Verify that we have permission to modify any modified parents
+        Collection<String> modifiedParents = getModifiedParents(user, identifier, model);
+        if (!modifiedParents.isEmpty()) {
+
+            ObjectPermissionSet permissionSet = getParentPermissionSet(user);
+            Collection<String> updateableParents = permissionSet.getAccessibleObjects(
+                Collections.singleton(ObjectPermission.Type.UPDATE),
+                modifiedParents
+            );
+
+            return updateableParents.size() == modifiedParents.size();
+            
+        }
+
+        return true;
+
+    }
+
+    @Override
+    protected void beforeCreate(ModeledAuthenticatedUser user,
+            ModelType model) throws GuacamoleException {
+
+        super.beforeCreate(user, model);
+        
+        // Validate that we can update all applicable parents
+        if (!canUpdateModifiedParents(user, null, model))
+            throw new GuacamoleSecurityException("Permission denied.");
+        
+    }
+
+    @Override
+    protected void beforeUpdate(ModeledAuthenticatedUser user,
+            ModelType model) throws GuacamoleException {
+
+        super.beforeUpdate(user, model);
+
+        // Validate that we can update all applicable parents
+        if (!canUpdateModifiedParents(user, model.getIdentifier(), model))
+            throw new GuacamoleSecurityException("Permission denied.");
+        
+    }
+
+    @Override
+    protected void beforeDelete(ModeledAuthenticatedUser user,
+            String identifier) throws GuacamoleException {
+
+        super.beforeDelete(user, identifier);
+
+        // Validate that we can update all applicable parents
+        if (!canUpdateModifiedParents(user, identifier, null))
+            throw new GuacamoleSecurityException("Permission denied.");
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledGroupedDirectoryObject.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledGroupedDirectoryObject.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledGroupedDirectoryObject.java
deleted file mode 100644
index 6aca740..0000000
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledGroupedDirectoryObject.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.guacamole.auth.jdbc.base;
-
-import org.apache.guacamole.auth.jdbc.connectiongroup.RootConnectionGroup;
-
-/**
- * Common base class for objects that will ultimately be made available through
- * the Directory class. All such objects will need the same base set of queries
- * to fulfill the needs of the Directory class.
- *
- * @author Michael Jumper
- * @param <ModelType>
- *     The type of model object that corresponds to this object.
- */
-public abstract class ModeledGroupedDirectoryObject<ModelType extends GroupedObjectModel>
-    extends ModeledDirectoryObject<ModelType> {
-
-    /**
-     * Returns the identifier of the parent connection group, which cannot be
-     * null. If the parent is the root connection group, this will be
-     * RootConnectionGroup.IDENTIFIER.
-     *
-     * @return
-     *     The identifier of the parent connection group.
-     */
-    public String getParentIdentifier() {
-
-        // Translate null parent to proper identifier
-        String parentIdentifier = getModel().getParentIdentifier();
-        if (parentIdentifier == null)
-            return RootConnectionGroup.IDENTIFIER;
-
-        return parentIdentifier;
-        
-    }
-
-    /**
-     * Sets the identifier of the associated parent connection group. If the
-     * parent is the root connection group, this should be
-     * RootConnectionGroup.IDENTIFIER.
-     * 
-     * @param parentIdentifier
-     *     The identifier of the connection group to associate as this object's
-     *     parent.
-     */
-    public void setParentIdentifier(String parentIdentifier) {
-
-        // Translate root identifier back into null
-        if (parentIdentifier != null
-                && parentIdentifier.equals(RootConnectionGroup.IDENTIFIER))
-            parentIdentifier = null;
-
-        getModel().setParentIdentifier(parentIdentifier);
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledGroupedDirectoryObjectService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledGroupedDirectoryObjectService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledGroupedDirectoryObjectService.java
deleted file mode 100644
index 718def7..0000000
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledGroupedDirectoryObjectService.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.guacamole.auth.jdbc.base;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import org.apache.guacamole.GuacamoleException;
-import org.apache.guacamole.GuacamoleSecurityException;
-import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
-import org.apache.guacamole.net.auth.Identifiable;
-import org.apache.guacamole.net.auth.permission.ObjectPermission;
-import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
-
-/**
- * Service which provides convenience methods for creating, retrieving, and
- * manipulating objects that can be within connection groups. This service will
- * automatically enforce the permissions of the current user.
- *
- * @author Michael Jumper
- * @param <InternalType>
- *     The specific internal implementation of the type of object this service
- *     provides access to.
- *
- * @param <ExternalType>
- *     The external interface or implementation of the type of object this
- *     service provides access to, as defined by the guacamole-ext API.
- *
- * @param <ModelType>
- *     The underlying model object used to represent InternalType in the
- *     database.
- */
-public abstract class ModeledGroupedDirectoryObjectService<InternalType extends ModeledGroupedDirectoryObject<ModelType>,
-        ExternalType extends Identifiable, ModelType extends GroupedObjectModel>
-        extends ModeledDirectoryObjectService<InternalType, ExternalType, ModelType> {
-
-    /**
-     * Returns the set of parent connection groups that are modified by the
-     * given model object (by virtue of the object changing parent groups). If
-     * the model is not changing parents, the resulting collection will be
-     * empty.
-     *
-     * @param user
-     *     The user making the given changes to the model.
-     *
-     * @param identifier
-     *     The identifier of the object that has been modified, if it exists.
-     *     If the object is being created, this will be null.
-     *
-     * @param model
-     *     The model that has been modified, if any. If the object is being
-     *     deleted, this will be null.
-     *
-     * @return
-     *     A collection of the identifiers of all parent connection groups
-     *     that will be affected (updated) by the change.
-     *
-     * @throws GuacamoleException
-     *     If an error occurs while determining which parent connection groups
-     *     are affected.
-     */
-    protected Collection<String> getModifiedGroups(ModeledAuthenticatedUser user,
-            String identifier, ModelType model) throws GuacamoleException {
-
-        // Get old parent identifier
-        String oldParentIdentifier = null;
-        if (identifier != null) {
-            ModelType current = retrieveObject(user, identifier).getModel();
-            oldParentIdentifier = current.getParentIdentifier();
-        }
-
-        // Get new parent identifier
-        String parentIdentifier = null;
-        if (model != null) {
-
-            parentIdentifier = model.getParentIdentifier();
-
-            // If both parents have the same identifier, nothing has changed
-            if (parentIdentifier != null && parentIdentifier.equals(oldParentIdentifier))
-                return Collections.<String>emptyList();
-
-        }
-
-        // Return collection of all non-root groups involved
-        Collection<String> groups = new ArrayList<String>(2);
-        if (oldParentIdentifier != null) groups.add(oldParentIdentifier);
-        if (parentIdentifier    != null) groups.add(parentIdentifier);
-        return groups;
-
-    }
-
-    /**
-     * Returns whether the given user has permission to modify the parent
-     * connection groups affected by the modifications made to the given model
-     * object.
-     *
-     * @param user
-     *     The user who changed the model object.
-     *
-     * @param identifier
-     *     The identifier of the object that has been modified, if it exists.
-     *     If the object is being created, this will be null.
-     *
-     * @param model
-     *     The model that has been modified, if any. If the object is being
-     *     deleted, this will be null.
-     *
-     * @return
-     *     true if the user has update permission for all modified groups,
-     *     false otherwise.
-     *
-     * @throws GuacamoleException
-     *     If an error occurs while determining which parent connection groups
-     *     are affected.
-     */
-    protected boolean canUpdateModifiedGroups(ModeledAuthenticatedUser user,
-            String identifier, ModelType model) throws GuacamoleException {
-
-        // If user is an administrator, no need to check
-        if (user.getUser().isAdministrator())
-            return true;
-        
-        // Verify that we have permission to modify any modified groups
-        Collection<String> modifiedGroups = getModifiedGroups(user, identifier, model);
-        if (!modifiedGroups.isEmpty()) {
-
-            ObjectPermissionSet permissionSet = user.getUser().getConnectionGroupPermissions();
-            Collection<String> updateableGroups = permissionSet.getAccessibleObjects(
-                Collections.singleton(ObjectPermission.Type.UPDATE),
-                modifiedGroups
-            );
-
-            return updateableGroups.size() == modifiedGroups.size();
-            
-        }
-
-        return true;
-
-    }
-
-    @Override
-    protected void beforeCreate(ModeledAuthenticatedUser user,
-            ModelType model) throws GuacamoleException {
-
-        super.beforeCreate(user, model);
-        
-        // Validate that we can update all applicable parent groups
-        if (!canUpdateModifiedGroups(user, null, model))
-            throw new GuacamoleSecurityException("Permission denied.");
-        
-    }
-
-    @Override
-    protected void beforeUpdate(ModeledAuthenticatedUser user,
-            ModelType model) throws GuacamoleException {
-
-        super.beforeUpdate(user, model);
-
-        // Validate that we can update all applicable parent groups
-        if (!canUpdateModifiedGroups(user, model.getIdentifier(), model))
-            throw new GuacamoleSecurityException("Permission denied.");
-        
-    }
-
-    @Override
-    protected void beforeDelete(ModeledAuthenticatedUser user,
-            String identifier) throws GuacamoleException {
-
-        super.beforeDelete(user, identifier);
-
-        // Validate that we can update all applicable parent groups
-        if (!canUpdateModifiedGroups(user, identifier, null))
-            throw new GuacamoleSecurityException("Permission denied.");
-        
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionModel.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionModel.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionModel.java
index 0a1a475..5e8a8f3 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionModel.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionModel.java
@@ -21,7 +21,7 @@ package org.apache.guacamole.auth.jdbc.connection;
 
 import java.util.HashSet;
 import java.util.Set;
-import org.apache.guacamole.auth.jdbc.base.GroupedObjectModel;
+import org.apache.guacamole.auth.jdbc.base.ChildObjectModel;
 
 /**
  * Object representation of a Guacamole connection, as represented in the
@@ -29,7 +29,7 @@ import org.apache.guacamole.auth.jdbc.base.GroupedObjectModel;
  *
  * @author Michael Jumper
  */
-public class ConnectionModel extends GroupedObjectModel {
+public class ConnectionModel extends ChildObjectModel {
 
     /**
      * The human-readable name associated with this connection.

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
index cf64f8a..d6de326 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionService.java
@@ -34,7 +34,7 @@ import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
 import org.apache.guacamole.GuacamoleClientException;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.GuacamoleSecurityException;
-import org.apache.guacamole.auth.jdbc.base.ModeledGroupedDirectoryObjectService;
+import org.apache.guacamole.auth.jdbc.base.ModeledChildDirectoryObjectService;
 import org.apache.guacamole.auth.jdbc.permission.ConnectionPermissionMapper;
 import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
 import org.apache.guacamole.net.GuacamoleTunnel;
@@ -52,7 +52,7 @@ import org.apache.guacamole.protocol.GuacamoleClientInformation;
  *
  * @author Michael Jumper, James Muehlner
  */
-public class ConnectionService extends ModeledGroupedDirectoryObjectService<ModeledConnection, Connection, ConnectionModel> {
+public class ConnectionService extends ModeledChildDirectoryObjectService<ModeledConnection, Connection, ConnectionModel> {
 
     /**
      * Mapper for accessing connections.
@@ -146,6 +146,15 @@ public class ConnectionService extends ModeledGroupedDirectoryObjectService<Mode
     }
 
     @Override
+    protected ObjectPermissionSet getParentPermissionSet(ModeledAuthenticatedUser user)
+            throws GuacamoleException {
+
+        // Connections are contained by connection groups
+        return user.getUser().getConnectionGroupPermissions();
+
+    }
+
+    @Override
     protected void beforeCreate(ModeledAuthenticatedUser user,
             ConnectionModel model) throws GuacamoleException {
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
index 1ee896a..ead81ec 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
@@ -31,7 +31,7 @@ import java.util.Set;
 import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
-import org.apache.guacamole.auth.jdbc.base.ModeledGroupedDirectoryObject;
+import org.apache.guacamole.auth.jdbc.base.ModeledChildDirectoryObject;
 import org.apache.guacamole.form.Field;
 import org.apache.guacamole.form.Form;
 import org.apache.guacamole.form.NumericField;
@@ -50,7 +50,7 @@ import org.slf4j.LoggerFactory;
  * @author James Muehlner
  * @author Michael Jumper
  */
-public class ModeledConnection extends ModeledGroupedDirectoryObject<ConnectionModel>
+public class ModeledConnection extends ModeledChildDirectoryObject<ConnectionModel>
     implements Connection {
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupModel.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupModel.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupModel.java
index 1d938c9..3784578 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupModel.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupModel.java
@@ -21,7 +21,7 @@ package org.apache.guacamole.auth.jdbc.connectiongroup;
 
 import java.util.HashSet;
 import java.util.Set;
-import org.apache.guacamole.auth.jdbc.base.GroupedObjectModel;
+import org.apache.guacamole.auth.jdbc.base.ChildObjectModel;
 import org.apache.guacamole.net.auth.ConnectionGroup;
 
 /**
@@ -30,7 +30,7 @@ import org.apache.guacamole.net.auth.ConnectionGroup;
  *
  * @author Michael Jumper
  */
-public class ConnectionGroupModel extends GroupedObjectModel {
+public class ConnectionGroupModel extends ChildObjectModel {
 
     /**
      * The human-readable name associated with this connection group.

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
index 68ebdae..0382c35 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupService.java
@@ -29,7 +29,7 @@ import org.apache.guacamole.GuacamoleClientException;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.GuacamoleSecurityException;
 import org.apache.guacamole.GuacamoleUnsupportedException;
-import org.apache.guacamole.auth.jdbc.base.ModeledGroupedDirectoryObjectService;
+import org.apache.guacamole.auth.jdbc.base.ModeledChildDirectoryObjectService;
 import org.apache.guacamole.auth.jdbc.permission.ConnectionGroupPermissionMapper;
 import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
 import org.apache.guacamole.net.GuacamoleTunnel;
@@ -46,7 +46,7 @@ import org.apache.guacamole.protocol.GuacamoleClientInformation;
  *
  * @author Michael Jumper, James Muehlner
  */
-public class ConnectionGroupService extends ModeledGroupedDirectoryObjectService<ModeledConnectionGroup,
+public class ConnectionGroupService extends ModeledChildDirectoryObjectService<ModeledConnectionGroup,
         ConnectionGroup, ConnectionGroupModel> {
 
     /**
@@ -129,6 +129,15 @@ public class ConnectionGroupService extends ModeledGroupedDirectoryObjectService
     }
 
     @Override
+    protected ObjectPermissionSet getParentPermissionSet(ModeledAuthenticatedUser user)
+            throws GuacamoleException {
+
+        // Connection groups are contained by other connection groups
+        return user.getUser().getConnectionGroupPermissions();
+
+    }
+
+    @Override
     protected void beforeCreate(ModeledAuthenticatedUser user,
             ConnectionGroupModel model) throws GuacamoleException {
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-client/blob/26d9dd85/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ModeledConnectionGroup.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ModeledConnectionGroup.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ModeledConnectionGroup.java
index 59a93ec..5fdf6f7 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ModeledConnectionGroup.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ModeledConnectionGroup.java
@@ -28,7 +28,7 @@ import java.util.Map;
 import java.util.Set;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
-import org.apache.guacamole.auth.jdbc.base.ModeledGroupedDirectoryObject;
+import org.apache.guacamole.auth.jdbc.base.ModeledChildDirectoryObject;
 import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
 import org.apache.guacamole.form.BooleanField;
 import org.apache.guacamole.form.Field;
@@ -47,7 +47,7 @@ import org.slf4j.LoggerFactory;
  * @author James Muehlner
  * @author Michael Jumper
  */
-public class ModeledConnectionGroup extends ModeledGroupedDirectoryObject<ConnectionGroupModel>
+public class ModeledConnectionGroup extends ModeledChildDirectoryObject<ConnectionGroupModel>
     implements ConnectionGroup {
 
     /**