GUAC-1101: Implement/stub retrieval and mapping of system permissions.

This commit is contained in:
Michael Jumper
2015-02-13 02:19:28 -08:00
parent 57d252c463
commit 2614ba7041
7 changed files with 236 additions and 21 deletions

View File

@@ -36,6 +36,38 @@ import org.glyptodon.guacamole.net.auth.Identifiable;
*/
public interface DirectoryObject<ModelType> extends Identifiable {
/**
* Initializes this object, associating it with the current authenticated
* user and populating it with data from the given model object
*
* @param currentUser
* The user that created or retrieved this object.
*
* @param model
* The backing model object.
*/
public void init(AuthenticatedUser currentUser, ModelType model);
/**
* Returns the user that created or queried this object. This user's
* permissions dictate what operations can be performed on or through this
* object.
*
* @return
* The user that created or queried this object.
*/
public AuthenticatedUser getCurrentUser();
/**
* Sets the user that created or queried this object. This user's
* permissions dictate what operations can be performed on or through this
* object.
*
* @param currentUser
* The user that created or queried this object.
*/
public void setCurrentUser(AuthenticatedUser currentUser);
/**
* Returns the backing model object. Changes to the model object will
* affect this object, and changes to this object will affect the model

View File

@@ -29,6 +29,7 @@ import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.name.Names;
import java.util.Properties;
import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
import org.glyptodon.guacamole.net.auth.Credentials;
@@ -39,6 +40,7 @@ import net.sourceforge.guacamole.net.auth.mysql.service.PasswordEncryptionServic
import net.sourceforge.guacamole.net.auth.mysql.service.SHA256PasswordEncryptionService;
import net.sourceforge.guacamole.net.auth.mysql.service.SaltService;
import net.sourceforge.guacamole.net.auth.mysql.service.SecureRandomSaltService;
import net.sourceforge.guacamole.net.auth.mysql.service.SystemPermissionService;
import net.sourceforge.guacamole.net.auth.mysql.service.UserService;
import org.glyptodon.guacamole.properties.GuacamoleProperties;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
@@ -72,7 +74,7 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider {
// Upon successful authentication, return new user context
MySQLUserContext context = injector.getInstance(MySQLUserContext.class);
context.init(new AuthenticatedUser(user, credentials));
context.init(user.getCurrentUser());
return context;
}
@@ -132,6 +134,7 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider {
bindTransactionFactoryType(JdbcTransactionFactory.class);
// Add MyBatis mappers
addMapperClass(SystemPermissionMapper.class);
addMapperClass(UserMapper.class);
// Bind interfaces
@@ -139,6 +142,7 @@ public class MySQLAuthenticationProvider implements AuthenticationProvider {
bind(MySQLUserContext.class);
bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class);
bind(SaltService.class).to(SecureRandomSaltService.class);
bind(SystemPermissionService.class);
bind(UserDirectory.class);
bind(UserService.class);

View File

@@ -26,6 +26,7 @@ import com.google.inject.Inject;
import net.sourceforge.guacamole.net.auth.mysql.model.UserModel;
import net.sourceforge.guacamole.net.auth.mysql.service.PasswordEncryptionService;
import net.sourceforge.guacamole.net.auth.mysql.service.SaltService;
import net.sourceforge.guacamole.net.auth.mysql.service.SystemPermissionService;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.User;
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
@@ -40,6 +41,12 @@ import org.glyptodon.guacamole.net.auth.simple.SimpleSystemPermissionSet;
*/
public class MySQLUser implements User, DirectoryObject<UserModel> {
/**
* The user this user belongs to. Access is based on his/her permission
* settings.
*/
private AuthenticatedUser currentUser;
/**
* Service for hashing passwords.
*/
@@ -51,6 +58,12 @@ public class MySQLUser implements User, DirectoryObject<UserModel> {
*/
@Inject
private SaltService saltService;
/**
* Service for retrieving system permissions.
*/
@Inject
private SystemPermissionService systemPermissionService;
/**
* The internal model object containing the values which represent this
@@ -73,16 +86,20 @@ public class MySQLUser implements User, DirectoryObject<UserModel> {
public MySQLUser() {
}
/**
* Creates a new MySQLUser backed by the given user model object. Changes
* to this model object will affect the new MySQLUser even after creation,
* and changes to the new MySQLUser will affect this model object.
*
* @param userModel
* The user model object to use to back this MySQLUser.
*/
public MySQLUser(UserModel userModel) {
this.userModel = userModel;
@Override
public void init(AuthenticatedUser currentUser, UserModel userModel) {
this.currentUser = currentUser;
setModel(userModel);
}
@Override
public AuthenticatedUser getCurrentUser() {
return currentUser;
}
@Override
public void setCurrentUser(AuthenticatedUser currentUser) {
this.currentUser = currentUser;
}
@Override
@@ -147,7 +164,7 @@ public class MySQLUser implements User, DirectoryObject<UserModel> {
public SystemPermissionSet getSystemPermissions()
throws GuacamoleException {
// STUB
return new SimpleSystemPermissionSet();
return new SimpleSystemPermissionSet(systemPermissionService.retrievePermissions(getCurrentUser(), this));
}
@Override

View File

@@ -62,13 +62,17 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
* Returns an instance of an object which is backed by the given model
* object.
*
* @param currentUser
* The user for whom this object is being created.
*
* @param model
* The model object to use to back the returned object.
*
* @return
* An object which is backed by the given model object.
*/
protected abstract ObjectType getObjectInstance(ModelType model);
protected abstract ObjectType getObjectInstance(AuthenticatedUser currentUser,
ModelType model);
/**
* Returns whether the given user has permission to create the type of
@@ -109,6 +113,9 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
* Returns a collection of objects which are backed by the models in the
* given collection.
*
* @param currentUser
* The user for whom these objects are being created.
*
* @param models
* The model objects to use to back the objects within the returned
* collection.
@@ -117,12 +124,13 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
* A collection of objects which are backed by the models in the given
* collection.
*/
protected Collection<ObjectType> getObjectInstances(Collection<ModelType> models) {
protected Collection<ObjectType> getObjectInstances(AuthenticatedUser currentUser,
Collection<ModelType> models) {
// Create new collection of objects by manually converting each model
Collection<ObjectType> objects = new ArrayList<ObjectType>(models.size());
for (ModelType model : models)
objects.add(getObjectInstance(model));
objects.add(getObjectInstance(currentUser, model));
return objects;
@@ -198,7 +206,7 @@ public abstract class DirectoryObjectService<ObjectType extends DirectoryObject<
objects = getObjectMapper().selectReadable(user.getUser().getModel(), identifiers);
// Return collection of requested objects
return getObjectInstances(objects);
return getObjectInstances(user, objects);
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2013 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 net.sourceforge.guacamole.net.auth.mysql.service;
import com.google.inject.Inject;
import java.util.Collection;
import net.sourceforge.guacamole.net.auth.mysql.AuthenticatedUser;
import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper;
import net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionModel;
import org.glyptodon.guacamole.GuacamoleException;
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
/**
* Service which provides convenience methods for creating, retrieving, and
* deleting system permissions.
*
* @author Michael Jumper
*/
public class SystemPermissionService
extends PermissionService<SystemPermission, SystemPermissionModel> {
/**
* Mapper for system-level permissions.
*/
@Inject
private SystemPermissionMapper systemPermissionMapper;
@Override
protected SystemPermissionMapper getPermissionMapper() {
return systemPermissionMapper;
}
@Override
protected SystemPermission getPermissionInstance(SystemPermissionModel model) {
// TODO: Will need an implementation-specific SystemPermission, but this
// will suffice for testing
return new SystemPermission(model.getType());
}
@Override
public void createPermissions(AuthenticatedUser user,
Collection<SystemPermission> permissions) throws GuacamoleException {
// TODO: Implement, including perm checks
}
@Override
public void deletePermissions(AuthenticatedUser user,
Collection<SystemPermission> permissions) throws GuacamoleException {
// TODO: Implement, including perm checks
}
}

View File

@@ -61,9 +61,10 @@ public class UserService extends DirectoryObjectService<MySQLUser, UserModel> {
}
@Override
protected MySQLUser getObjectInstance(UserModel model) {
protected MySQLUser getObjectInstance(AuthenticatedUser currentUser,
UserModel model) {
MySQLUser user = mySQLUserProvider.get();
user.setModel(model);
user.init(currentUser, model);
return user;
}
@@ -105,9 +106,11 @@ public class UserService extends DirectoryObjectService<MySQLUser, UserModel> {
if (userModel == null)
return null;
// Return corresponding user
return getObjectInstance(userModel);
// Return corresponding user, set up cyclic reference
MySQLUser user = getObjectInstance(null, userModel);
user.setCurrentUser(new AuthenticatedUser(user, credentials));
return user;
}
}

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--
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.
-->
<mapper namespace="net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper" >
<!-- Result mapper for system permissions -->
<resultMap id="SystemPermissionResultMap" type="net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionModel">
<result column="user_id" property="userID" jdbcType="INTEGER"/>
<result column="username" property="username" jdbcType="VARCHAR"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.glyptodon.guacamole.net.auth.permission.SystemPermission$Type"/>
</resultMap>
<!-- Select all permissions for a given user -->
<select id="select" resultMap="SystemPermissionResultMap">
SELECT
guacamole_system_permission.user_id,
username,
permission
FROM guacamole_system_permission
JOIN guacamole_user ON guacamole_system_permission.user_id = guacamole_user.user_id
WHERE guacamole_system_permission.user_id = #{user.userID,jdbcType=INTEGER}
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionModel">
DELETE FROM guacamole_system_permission
WHERE (user_id, permission) IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.userID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR})
</foreach>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="net.sourceforge.guacamole.net.auth.mysql.model.SystemPermissionModel">
INSERT INTO guacamole_system_permission (
user_id,
permission
)
VALUES
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.userID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR})
</foreach>
</insert>
</mapper>