From 68fd8e225c83fdfc131ef5a3ed50b8164c8630f4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sat, 28 Feb 2015 13:53:07 -0800 Subject: [PATCH] GUAC-1101: Partial object permission implementation. --- .../permission/ObjectPermissionMapper.java | 29 +++- .../permission/ObjectPermissionService.java | 59 +++++++- .../jdbc/permission/ObjectPermissionSet.java | 130 ++++++++++++++++++ 3 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionSet.java diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java index 777f54046..232f1efd5 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionMapper.java @@ -22,10 +22,37 @@ package org.glyptodon.guacamole.auth.jdbc.permission; +import org.apache.ibatis.annotations.Param; +import org.glyptodon.guacamole.auth.jdbc.user.UserModel; +import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; + /** * Mapper for object-related permissions. * * @author Michael Jumper */ public interface ObjectPermissionMapper extends PermissionMapper { -} \ No newline at end of file + + /** + * Retrieve the permission of the given type associated with the given + * user and object, if it exists. If no such permission exists, null is + * returned. + * + * @param user + * The user to retrieve permissions for. + * + * @param type + * The type of permission to return. + * + * @param identifier + * The identifier of the object affected by the permission to return. + * + * @return + * The requested permission, or null if no such permission is granted + * to the given user for the given object. + */ + ObjectPermissionModel selectOne(@Param("user") UserModel user, + @Param("type") ObjectPermission.Type type, + @Param("identifier") String identifier); + +} diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionService.java index 88b391600..d5abdc1a2 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionService.java @@ -38,12 +38,12 @@ import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet; * permissions of the current user. * * @author Michael Jumper - * @param - * The underlying model object used to represent PermissionType in the - * database. */ -public abstract class ObjectPermissionService - extends PermissionService { +public abstract class ObjectPermissionService + extends PermissionService { + + @Override + protected abstract ObjectPermissionMapper getPermissionMapper(); /** * Returns the permission set associated with the given user and related @@ -129,7 +129,7 @@ public abstract class ObjectPermissionService // Create permissions only if user has permission to do so if (canAlterPermissions(user, targetUser, permissions)) { - Collection models = getModelInstances(targetUser, permissions); + Collection models = getModelInstances(targetUser, permissions); getPermissionMapper().insert(models); return; } @@ -146,7 +146,7 @@ public abstract class ObjectPermissionService // Delete permissions only if user has permission to do so if (canAlterPermissions(user, targetUser, permissions)) { - Collection models = getModelInstances(targetUser, permissions); + Collection models = getModelInstances(targetUser, permissions); getPermissionMapper().delete(models); return; } @@ -156,4 +156,49 @@ public abstract class ObjectPermissionService } + /** + * Retrieves the permission of the given type associated with the given + * user and object, if it exists. If no such permission exists, null is + * + * @param user + * The user retrieving the permission. + * + * @param targetUser + * The user associated with the permission to be retrieved. + * + * @param type + * The type of permission to retrieve. + * + * @param identifier + * The identifier of the object affected by the permission to return. + * + * @return + * The permission of the given type associated with the given user and + * object, or null if no such permission exists. + * + * @throws GuacamoleException + * If an error occurs while retrieving the requested permission. + */ + public ObjectPermission retrievePermission(AuthenticatedUser user, + ModeledUser targetUser, ObjectPermission.Type type, + String identifier) throws GuacamoleException { + + // Only an admin can read permissions that aren't his own + if (user.getUser().getIdentifier().equals(targetUser.getIdentifier()) + || user.getUser().isAdministrator()) { + + // Read permission from database, return null if not found + ObjectPermissionModel model = getPermissionMapper().selectOne(targetUser.getModel(), type, identifier); + if (model == null) + return null; + + return getPermissionInstance(model); + + } + + // User cannot read this user's permissions + throw new GuacamoleSecurityException("Permission denied."); + + } + } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionSet.java new file mode 100644 index 000000000..fc1a1ae2f --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/permission/ObjectPermissionSet.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.glyptodon.guacamole.auth.jdbc.permission; + +import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser; +import org.glyptodon.guacamole.GuacamoleException; +import org.glyptodon.guacamole.net.auth.permission.ObjectPermission; + +/** + * A database implementation of ObjectPermissionSet which uses an injected + * service to query and manipulate the object-level permissions associated with + * a particular user. + * + * @author Michael Jumper + */ +public abstract class ObjectPermissionSet + implements org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet { + + /** + * The user that queried this permission set. Access is based on his/her + * permission settings. + */ + private AuthenticatedUser currentUser; + + /** + * The user associated with this permission set. Each of the permissions in + * this permission set is granted to this user. + */ + private ModeledUser user; + + /** + * Creates a new ObjectPermissionSet. The resulting permission set + * must still be initialized by a call to init(), or the information + * necessary to read and modify this set will be missing. + */ + public ObjectPermissionSet() { + } + + /** + * Initializes this permission set with the current user and the user + * to whom the permissions in this set are granted. + * + * @param currentUser + * The user who queried this permission set, and whose permissions + * dictate the access level of all operations performed on this set. + * + * @param user + * The user to whom the permissions in this set are granted. + */ + public void init(AuthenticatedUser currentUser, ModeledUser user) { + this.currentUser = currentUser; + this.user = user; + } + + /** + * Returns an ObjectPermissionService implementation for manipulating the + * type of permissions contained within this permission set. + * + * @return + * An object permission service for manipulating the type of + * permissions contained within this permission set. + */ + protected abstract ObjectPermissionService getObjectPermissionService(); + + @Override + public Set getPermissions() throws GuacamoleException { + return getObjectPermissionService().retrievePermissions(currentUser, user); + } + + @Override + public boolean hasPermission(ObjectPermission.Type permission, + String identifier) throws GuacamoleException { + return getObjectPermissionService().retrievePermission(currentUser, user, permission, identifier) != null; + } + + @Override + public void addPermission(ObjectPermission.Type permission, + String identifier) throws GuacamoleException { + addPermissions(Collections.singleton(new ObjectPermission(permission, identifier))); + } + + @Override + public void removePermission(ObjectPermission.Type permission, + String identifier) throws GuacamoleException { + removePermissions(Collections.singleton(new ObjectPermission(permission, identifier))); + } + + @Override + public Collection getAccessibleObjects(Collection permissions, + Collection identifiers) throws GuacamoleException { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + @Override + public void addPermissions(Set permissions) + throws GuacamoleException { + getObjectPermissionService().createPermissions(currentUser, user, permissions); + } + + @Override + public void removePermissions(Set permissions) + throws GuacamoleException { + getObjectPermissionService().deletePermissions(currentUser, user, permissions); + } + +}