You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by vn...@apache.org on 2018/10/01 17:36:53 UTC
[20/37] guacamole-client git commit: GUACAMOLE-220: Define base
interfaces for mapping RelatedObjectSets to the database.
GUACAMOLE-220: Define base interfaces for mapping RelatedObjectSets to the database.
Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/8f06b7a3
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/8f06b7a3
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/8f06b7a3
Branch: refs/heads/staging/1.0.0
Commit: 8f06b7a3f9293254a546914dd403e322546fe03b
Parents: a39d863
Author: Michael Jumper <mj...@apache.org>
Authored: Tue Apr 10 12:16:11 2018 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Sep 19 23:56:52 2018 -0700
----------------------------------------------------------------------
.../auth/jdbc/base/ObjectRelationMapper.java | 126 +++++++++++
.../auth/jdbc/base/RelatedObjectSet.java | 211 +++++++++++++++++++
2 files changed, 337 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/8f06b7a3/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectRelationMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectRelationMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectRelationMapper.java
new file mode 100644
index 0000000..082db0f
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectRelationMapper.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.guacamole.auth.jdbc.base;
+
+import java.util.Collection;
+import java.util.Set;
+import org.apache.guacamole.auth.jdbc.user.UserModel;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * Mapper for the relations represented by a particular RelatedObjectSet
+ * implementation.
+ *
+ * @param <ParentModelType>
+ * The underlying database model of the object on the parent side of the
+ * one-to-many relationship represented by the RelatedObjectSet mapped by
+ * this ObjectRelationMapper.
+ */
+public interface ObjectRelationMapper<ParentModelType extends ObjectModel> {
+
+ /**
+ * Inserts rows as necessary to establish the one-to-many relationship
+ * represented by the RelatedObjectSet between the given parent and
+ * children. If the relation for any parent/child pair is already present,
+ * no attempt is made to insert a new row for that relation.
+ *
+ * @param parent
+ * The model of the object on the parent side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @param children
+ * The identifiers of the objects on the child side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @return
+ * The number of rows inserted.
+ */
+ int insert(@Param("parent") ParentModelType parent,
+ @Param("children") Collection<String> children);
+
+ /**
+ * Deletes rows as necessary to establish the one-to-many relationship
+ * represented by the RelatedObjectSet between the given parent and
+ * children. If the relation for any parent/child pair does not exist,
+ * that specific relation is ignored, and deletion proceeds with the
+ * remaining relations.
+ *
+ * @param parent
+ * The model of the object on the parent side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @param children
+ * The identifiers of the objects on the child side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @return
+ * The number of rows deleted.
+ */
+ int delete(@Param("parent") ParentModelType parent,
+ @Param("children") Collection<String> children);
+
+ /**
+ * Retrieves the identifiers of all objects on the child side of the
+ * one-to-many relationship represented by the RelatedObjectSet mapped by
+ * this ObjectRelationMapper. This should only be called on behalf of a
+ * system administrator. If identifiers are needed by a non-administrative
+ * user who must have explicit read rights, use
+ * selectReadableChildIdentifiers() instead.
+ *
+ * @param parent
+ * The model of the object on the parent side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @return
+ * A Set containing the identifiers of all objects on the child side
+ * of the one-to-many relationship.
+ */
+ Set<String> selectChildIdentifiers(@Param("parent") ParentModelType parent);
+
+ /**
+ * Retrieves the identifiers of all objects on the child side of the
+ * one-to-many relationship represented by the RelatedObjectSet mapped by
+ * this ObjectRelationMapper, including only those objects which are
+ * explicitly readable by the given user. If identifiers are needed by a
+ * system administrator (who, by definition, does not need explicit read
+ * rights), use selectChildIdentifiers() instead.
+
+ *
+ * @param user
+ * The user whose permissions should determine whether an identifier
+ * is returned.
+ *
+ * @param effectiveGroups
+ * The identifiers of any known effective groups that should be taken
+ * into account, such as those defined externally to the database.
+ *
+ * @param parent
+ * The model of the object on the parent side of the one-to-many
+ * relationship represented by the RelatedObjectSet.
+ *
+ * @return
+ * A Set containing the identifiers of all readable objects on the
+ * child side of the one-to-many relationship.
+ */
+ Set<String> selectReadableChildIdentifiers(@Param("user") UserModel user,
+ @Param("effectiveGroups") Collection<String> effectiveGroups,
+ @Param("parent") ParentModelType parent);
+
+}
http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/8f06b7a3/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RelatedObjectSet.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RelatedObjectSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RelatedObjectSet.java
new file mode 100644
index 0000000..a46cb27
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/RelatedObjectSet.java
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.guacamole.auth.jdbc.base;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
+import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.GuacamoleSecurityException;
+import org.apache.guacamole.net.auth.permission.ObjectPermission;
+import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
+
+/**
+ * A database implementation of RelatedObjectSet which provides access to a
+ * parent object and corresponding set of objects related to the parent, subject
+ * to object-level permissions. Though the parent and child objects have
+ * specific types, only the parent object's type is enforced through type
+ * parameters, as child objects are represented by identifiers only.
+ *
+ * @param <ParentObjectType>
+ * The type of object that represents the parent side of the relation.
+ *
+ * @param <ParentModelType>
+ * The underlying database model of the parent object.
+ */
+public abstract class RelatedObjectSet<ParentObjectType extends ModeledDirectoryObject<ParentModelType>, ParentModelType extends ObjectModel>
+ extends RestrictedObject implements org.apache.guacamole.net.auth.RelatedObjectSet {
+
+ /**
+ * The parent object which shares some arbitrary relation with the objects
+ * within this set.
+ */
+ private ParentObjectType parent;
+
+ /**
+ * Creates a new RelatedObjectSet. The resulting object set must still be
+ * initialized by a call to init().
+ */
+ public RelatedObjectSet() {
+ }
+
+ /**
+ * Initializes this RelatedObjectSet with the current user and the single
+ * object on the parent side of the one-to-many relation represented by the
+ * set.
+ *
+ * @param currentUser
+ * The user who queried this RelatedObjectSet, and whose permissions
+ * dictate the access level of all operations performed on this set.
+ *
+ * @param parent
+ * The parent object which shares some arbitrary relation with the
+ * objects within this set.
+ */
+ public void init(ModeledAuthenticatedUser currentUser, ParentObjectType parent) {
+ super.init(currentUser);
+ this.parent = parent;
+ }
+
+ /**
+ * Returns the mapper which provides low-level access to the the database
+ * models which drive the relation represented by this RelatedObjectSet.
+ *
+ * @return
+ * The mapper which provides low-level access to the the database
+ * models which drive the relation represented by this
+ * RelatedObjectSet.
+ */
+ protected abstract ObjectRelationMapper<ParentModelType> getObjectRelationMapper();
+
+ /**
+ * Returns the permission set which exposes the effective permissions
+ * available to the current user regarding the objects on the parent side
+ * of the one-to-many relationship represented by this RelatedObjectSet.
+ * Permission inheritance through user groups is taken into account.
+ *
+ * @return
+ * The permission set which exposes the effective permissions
+ * available to the current user regarding the objects on the parent
+ * side of the one-to-many relationship represented by this
+ * RelatedObjectSet.
+ *
+ * @throws GuacamoleException
+ * If permission to query permission status is denied.
+ */
+ protected abstract ObjectPermissionSet getParentObjectEffectivePermissionSet()
+ throws GuacamoleException;
+
+ /**
+ * Returns the permission set which exposes the effective permissions
+ * available to the current user regarding the objects on the child side
+ * of the one-to-many relationship represented by this RelatedObjectSet.
+ * Permission inheritance through user groups is taken into account.
+ *
+ * @return
+ * The permission set which exposes the effective permissions
+ * available to the current user regarding the objects on the child
+ * side of the one-to-many relationship represented by this
+ * RelatedObjectSet.
+ *
+ * @throws GuacamoleException
+ * If permission to query permission status is denied.
+ */
+ protected abstract ObjectPermissionSet getChildObjectEffectivePermissionSet()
+ throws GuacamoleException;
+
+ /**
+ * Returns whether the current user has permission to alter that status of
+ * the relation between the parent object and the given child objects.
+ *
+ * @param identifiers
+ * The identifiers of all objects on the child side of the one-to-many
+ * relation being changed.
+ *
+ * @return
+ * true if the user has permission to make the described changes,
+ * false otherwise.
+ *
+ * @throws GuacamoleException
+ * If permission to query permission status is denied.
+ */
+ private boolean canAlterRelation(Collection<String> identifiers)
+ throws GuacamoleException {
+
+ // System administrators may alter any relations
+ if (getCurrentUser().getUser().isAdministrator())
+ return true;
+
+ // Non-admin users require UPDATE permission on the parent object ...
+ if (!getParentObjectEffectivePermissionSet().hasPermission(
+ ObjectPermission.Type.UPDATE, parent.getIdentifier()))
+ return false;
+
+ // ... as well as UPDATE permission on all child objects being changed
+ Collection<String> accessibleIdentifiers =
+ getChildObjectEffectivePermissionSet().getAccessibleObjects(
+ Collections.singleton(ObjectPermission.Type.UPDATE),
+ identifiers);
+
+ return accessibleIdentifiers.size() == identifiers.size();
+
+ }
+
+ @Override
+ public Set<String> getObjects() throws GuacamoleException {
+
+ // Bypass permission checks if the user is a system admin
+ ModeledAuthenticatedUser user = getCurrentUser();
+ if (user.getUser().isAdministrator())
+ return getObjectRelationMapper().selectChildIdentifiers(parent.getModel());
+
+ // Otherwise only return explicitly readable identifiers
+ return getObjectRelationMapper().selectReadableChildIdentifiers(
+ user.getUser().getModel(), user.getEffectiveUserGroups(),
+ parent.getModel());
+
+ }
+
+ @Override
+ public void addObjects(Set<String> identifiers) throws GuacamoleException {
+
+ // Nothing to do if nothing provided
+ if (identifiers.isEmpty())
+ return;
+
+ // Create relations only if permission is granted
+ if (canAlterRelation(identifiers))
+ getObjectRelationMapper().insert(parent.getModel(), identifiers);
+
+ // User lacks permission to add user groups
+ else
+ throw new GuacamoleSecurityException("Permission denied.");
+
+ }
+
+ @Override
+ public void removeObjects(Set<String> identifiers) throws GuacamoleException {
+
+ // Nothing to do if nothing provided
+ if (identifiers.isEmpty())
+ return;
+
+ // Delete relations only if permission is granted
+ if (canAlterRelation(identifiers))
+ getObjectRelationMapper().delete(parent.getModel(), identifiers);
+
+ // User lacks permission to remove user groups
+ else
+ throw new GuacamoleSecurityException("Permission denied.");
+
+ }
+
+}