mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
Merge pull request #98 from glyptodon/mysql-speed
GUAC-1101: Rewrite guacamole-auth-mysql with speed in mind.
This commit is contained in:
102
extensions/guacamole-auth-jdbc/README
Normal file
102
extensions/guacamole-auth-jdbc/README
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
------------------------------------------------------------
|
||||
About this README
|
||||
------------------------------------------------------------
|
||||
|
||||
This README is intended to provide quick and to-the-point documentation for
|
||||
technical users intending to compile parts of Guacamole themselves.
|
||||
|
||||
Distribution-specific packages are available from the files section of the main
|
||||
project page:
|
||||
|
||||
http://sourceforge.net/projects/guacamole/files/
|
||||
|
||||
Distribution-specific documentation is provided on the Guacamole wiki:
|
||||
|
||||
http://guac-dev.org/
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
What is guacamole-auth-jdbc?
|
||||
------------------------------------------------------------
|
||||
|
||||
guacamole-auth-jdbc is a Java library for use with the Guacamole web
|
||||
application to provide database-driven authentication.
|
||||
|
||||
guacamole-auth-jdbc provides multiple authentication provider implementations
|
||||
which each provide a support for a different database. These authentication
|
||||
providers can be set in guacamole.properties to allow authentication of
|
||||
Guacamole users through that type of database.
|
||||
|
||||
Schema files are provided to create the required tables in your database of
|
||||
choice.
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
Compiling and installing guacamole-auth-jdbc
|
||||
------------------------------------------------------------
|
||||
|
||||
guacamole-auth-jdbc is built using Maven. Building guacamole-auth-jdbc compiles
|
||||
all classes and packages them into a redistributable .tar.gz archive. This
|
||||
archive contains multiple .jar files, each of this corresponds to a
|
||||
database-specific authentication provider implementation that can be installed
|
||||
in the library directory configured in guacamole.properties.
|
||||
|
||||
1) Run mvn package
|
||||
|
||||
$ mvn package
|
||||
|
||||
Maven will download any needed dependencies for building the .jar file.
|
||||
Once all dependencies have been downloaded, the .jar file will be
|
||||
created in the target/ subdirectory of the current directory.
|
||||
|
||||
4) Extract the .tar.gz file now present in the target/ directory, and
|
||||
place the .jar files in the extracted lib/ subdirectory in the library
|
||||
directory specified in guacamole.properties.
|
||||
|
||||
You will likely need to do this as root.
|
||||
|
||||
If you do not have a library directory configured in your
|
||||
guacamole.properties, you will need to specify one. The directory
|
||||
is specified using the "lib-directory" property.
|
||||
|
||||
5) Set up your MySQL database to authenticate Guacamole users
|
||||
|
||||
A schema file is provided in the schema directory for creating
|
||||
the guacamole authentication tables in your MySQL database.
|
||||
|
||||
Additionally, a script is provided to create a default admin user
|
||||
with username 'guacadmin' and password 'guacadmin'. This user can
|
||||
be used to set up any other connections and users.
|
||||
|
||||
6) Configure guacamole.properties for your database
|
||||
|
||||
There are additional properties required by JDBC drivers which must
|
||||
be added/changed in your guacamole.properties. These parameters are
|
||||
specific to the database being used.
|
||||
|
||||
For MySQL, the following properties are available:
|
||||
|
||||
# Database connection configuration
|
||||
mysql-hostname: database.host.name
|
||||
mysql-port: 3306
|
||||
mysql-database: guacamole.database.name
|
||||
mysql-username: user
|
||||
mysql-password: pass
|
||||
|
||||
Optionally, the authentication provider can be configured
|
||||
not to allow multiple users to use the same connection
|
||||
at the same time:
|
||||
|
||||
mysql-disallow-simultaneous-connections: true
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
Reporting problems
|
||||
------------------------------------------------------------
|
||||
|
||||
Please report any bugs encountered by opening a new issue in the JIRA system
|
||||
hosted at:
|
||||
|
||||
http://glyptodon.org/jira/
|
||||
|
@@ -0,0 +1,82 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-auth-jdbc-base</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>guacamole-auth-jdbc-base</name>
|
||||
<url>http://guac-dev.org/</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-auth-jdbc</artifactId>
|
||||
<version>0.9.5</version>
|
||||
<relativePath>../../</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<!-- Written for 1.6 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Guacamole Extension API -->
|
||||
<dependency>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-ext</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- SLF4J - logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.7</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MyBatis -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
<version>3.2.8</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MyBatis Guice -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-guice</artifactId>
|
||||
<version>3.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Guice -->
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-multibindings</artifactId>
|
||||
<version>3.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserContext;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.RootConnectionGroup;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupDirectory;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionDirectory;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ModeledGuacamoleConfiguration;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.SystemPermissionSet;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserDirectory;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionRecordMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ParameterMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.SystemPermissionMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.security.PasswordEncryptionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.security.SHA256PasswordEncryptionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.security.SaltService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.security.SecureRandomSaltService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.SystemPermissionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.socket.UnrestrictedGuacamoleSocketService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserService;
|
||||
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionGroupPermissionMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionGroupPermissionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionGroupPermissionSet;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionPermissionMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionPermissionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionPermissionSet;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionSet;
|
||||
import org.glyptodon.guacamole.environment.Environment;
|
||||
import org.mybatis.guice.MyBatisModule;
|
||||
import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider;
|
||||
|
||||
/**
|
||||
* Guice module which configures the injections used by the JDBC authentication
|
||||
* provider base. This module MUST be included in the Guice injector, or
|
||||
* authentication providers based on JDBC will not function.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class JDBCAuthenticationProviderModule extends MyBatisModule {
|
||||
|
||||
/**
|
||||
* The environment of the Guacamole server.
|
||||
*/
|
||||
private final Environment environment;
|
||||
|
||||
/**
|
||||
* Creates a new JDBC authentication provider module that configures the
|
||||
* various injected base classes using the given environment.
|
||||
*
|
||||
* @param environment
|
||||
* The environment to use to configure injected classes.
|
||||
*/
|
||||
public JDBCAuthenticationProviderModule(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
|
||||
// Datasource
|
||||
bindDataSourceProviderType(PooledDataSourceProvider.class);
|
||||
|
||||
// Transaction factory
|
||||
bindTransactionFactoryType(JdbcTransactionFactory.class);
|
||||
|
||||
// Add MyBatis mappers
|
||||
addMapperClass(ConnectionMapper.class);
|
||||
addMapperClass(ConnectionGroupMapper.class);
|
||||
addMapperClass(ConnectionGroupPermissionMapper.class);
|
||||
addMapperClass(ConnectionPermissionMapper.class);
|
||||
addMapperClass(ConnectionRecordMapper.class);
|
||||
addMapperClass(ParameterMapper.class);
|
||||
addMapperClass(SystemPermissionMapper.class);
|
||||
addMapperClass(UserMapper.class);
|
||||
addMapperClass(UserPermissionMapper.class);
|
||||
|
||||
// Bind core implementations of guacamole-ext classes
|
||||
bind(Environment.class).toInstance(environment);
|
||||
bind(ConnectionDirectory.class);
|
||||
bind(ConnectionGroupDirectory.class);
|
||||
bind(ConnectionGroupPermissionSet.class);
|
||||
bind(ConnectionPermissionSet.class);
|
||||
bind(ModeledConnection.class);
|
||||
bind(ModeledConnectionGroup.class);
|
||||
bind(ModeledGuacamoleConfiguration.class);
|
||||
bind(ModeledUser.class);
|
||||
bind(RootConnectionGroup.class);
|
||||
bind(SystemPermissionSet.class);
|
||||
bind(UserContext.class);
|
||||
bind(UserDirectory.class);
|
||||
bind(UserPermissionSet.class);
|
||||
|
||||
// Bind services
|
||||
bind(ConnectionGroupPermissionService.class);
|
||||
bind(ConnectionGroupService.class);
|
||||
bind(ConnectionPermissionService.class);
|
||||
bind(ConnectionService.class);
|
||||
bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class);
|
||||
bind(SaltService.class).to(SecureRandomSaltService.class);
|
||||
bind(SystemPermissionService.class);
|
||||
bind(UserPermissionService.class);
|
||||
bind(UserService.class);
|
||||
|
||||
// Bind appropriate socket service based on policy
|
||||
bind(GuacamoleSocketService.class).to(UnrestrictedGuacamoleSocketService.class);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.base;
|
||||
|
||||
import org.glyptodon.guacamole.net.auth.Identifiable;
|
||||
|
||||
/**
|
||||
* 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 DirectoryObject<ModelType extends ObjectModel>
|
||||
extends ModeledObject<ModelType> implements Identifiable {
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return getModel().getIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(String identifier) {
|
||||
getModel().setIdentifier(identifier);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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.base;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* Common interface 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 object contained within the directory whose objects are
|
||||
* mapped by this mapper.
|
||||
*/
|
||||
public interface DirectoryObjectMapper<ModelType> {
|
||||
|
||||
/**
|
||||
* Selects the identifiers of all objects, regardless of whether they
|
||||
* are readable by any particular user. 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
|
||||
* selectReadableIdentifiers() instead.
|
||||
*
|
||||
* @return
|
||||
* A Set containing all identifiers of all objects.
|
||||
*/
|
||||
Set<String> selectIdentifiers();
|
||||
|
||||
/**
|
||||
* Selects the identifiers of all objects that 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
|
||||
* selectIdentifiers() instead.
|
||||
*
|
||||
* @param user
|
||||
* The user whose permissions should determine whether an identifier
|
||||
* is returned.
|
||||
*
|
||||
* @return
|
||||
* A Set containing all identifiers of all readable objects.
|
||||
*/
|
||||
Set<String> selectReadableIdentifiers(@Param("user") UserModel user);
|
||||
|
||||
/**
|
||||
* Selects all objects which have the given identifiers. If an identifier
|
||||
* has no corresponding object, it will be ignored. This should only be
|
||||
* called on behalf of a system administrator. If objects are needed by a
|
||||
* non-administrative user who must have explicit read rights, use
|
||||
* selectReadable() instead.
|
||||
*
|
||||
* @param identifiers
|
||||
* The identifiers of the objects to return.
|
||||
*
|
||||
* @return
|
||||
* A Collection of all objects having the given identifiers.
|
||||
*/
|
||||
Collection<ModelType> select(@Param("identifiers") Collection<String> identifiers);
|
||||
|
||||
/**
|
||||
* Selects all objects which have the given identifiers and are explicitly
|
||||
* readably by the given user. If an identifier has no corresponding
|
||||
* object, or the corresponding object is unreadable, it will be ignored.
|
||||
* If objects are needed by a system administrator (who, by definition,
|
||||
* does not need explicit read rights), use select() instead.
|
||||
*
|
||||
* @param user
|
||||
* The user whose permissions should determine whether an object
|
||||
* is returned.
|
||||
*
|
||||
* @param identifiers
|
||||
* The identifiers of the objects to return.
|
||||
*
|
||||
* @return
|
||||
* A Collection of all objects having the given identifiers.
|
||||
*/
|
||||
Collection<ModelType> selectReadable(@Param("user") UserModel user,
|
||||
@Param("identifiers") Collection<String> identifiers);
|
||||
|
||||
/**
|
||||
* Inserts the given object into the database. If the object already
|
||||
* exists, this will result in an error.
|
||||
*
|
||||
* @param object
|
||||
* The object to insert.
|
||||
*
|
||||
* @return
|
||||
* The number of rows inserted.
|
||||
*/
|
||||
int insert(@Param("object") ModelType object);
|
||||
|
||||
/**
|
||||
* Deletes the given object into the database. If the object does not
|
||||
* exist, this operation has no effect.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the object to delete.
|
||||
*
|
||||
* @return
|
||||
* The number of rows deleted.
|
||||
*/
|
||||
int delete(@Param("identifier") String identifier);
|
||||
|
||||
/**
|
||||
* Updates the given existing object in the database. If the object does
|
||||
* not actually exist, this operation has no effect.
|
||||
*
|
||||
* @param object
|
||||
* The object to update.
|
||||
*
|
||||
* @return
|
||||
* The number of rows updated.
|
||||
*/
|
||||
int update(@Param("object") ModelType object);
|
||||
|
||||
}
|
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.base;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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.GuacamoleSecurityException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionModel;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* manipulating users. 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 DirectoryObjectService<InternalType extends DirectoryObject<ModelType>,
|
||||
ExternalType, ModelType extends ObjectModel> {
|
||||
|
||||
/**
|
||||
* All object permissions which are implicitly granted upon creation to the
|
||||
* creator of the object.
|
||||
*/
|
||||
private static final ObjectPermission.Type[] IMPLICIT_OBJECT_PERMISSIONS = {
|
||||
ObjectPermission.Type.READ,
|
||||
ObjectPermission.Type.UPDATE,
|
||||
ObjectPermission.Type.DELETE,
|
||||
ObjectPermission.Type.ADMINISTER
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an instance of a mapper for the type of object used by this
|
||||
* service.
|
||||
*
|
||||
* @return
|
||||
* A mapper which provides access to the model objects associated with
|
||||
* the objects used by this service.
|
||||
*/
|
||||
protected abstract DirectoryObjectMapper<ModelType> getObjectMapper();
|
||||
|
||||
/**
|
||||
* Returns an instance of a mapper for the type of permissions that affect
|
||||
* the type of object used by this service.
|
||||
*
|
||||
* @return
|
||||
* A mapper which provides access to the model objects associated with
|
||||
* the permissions that affect the objects used by this service.
|
||||
*/
|
||||
protected abstract ObjectPermissionMapper getPermissionMapper();
|
||||
|
||||
/**
|
||||
* 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 InternalType getObjectInstance(AuthenticatedUser currentUser,
|
||||
ModelType model);
|
||||
|
||||
/**
|
||||
* Returns an instance of a model object which is based on the given
|
||||
* object.
|
||||
*
|
||||
* @param currentUser
|
||||
* The user for whom this model object is being created.
|
||||
*
|
||||
* @param object
|
||||
* The object to use to produce the returned model object.
|
||||
*
|
||||
* @return
|
||||
* A model object which is based on the given object.
|
||||
*/
|
||||
protected abstract ModelType getModelInstance(AuthenticatedUser currentUser,
|
||||
ExternalType object);
|
||||
|
||||
/**
|
||||
* Returns whether the given user has permission to create the type of
|
||||
* objects that this directory object service manages.
|
||||
*
|
||||
* @param user
|
||||
* The user being checked.
|
||||
*
|
||||
* @return
|
||||
* true if the user has object creation permission relevant to this
|
||||
* directory object service, false otherwise.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If permission to read the user's permissions is denied.
|
||||
*/
|
||||
protected abstract boolean hasCreatePermission(AuthenticatedUser user)
|
||||
throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* Returns whether the given user has permission to perform a certain
|
||||
* action on a specific object managed by this directory object service.
|
||||
*
|
||||
* @param user
|
||||
* The user being checked.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the object to check.
|
||||
*
|
||||
* @param type
|
||||
* The type of action that will be performed.
|
||||
*
|
||||
* @return
|
||||
* true if the user has object permission relevant described, false
|
||||
* otherwise.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If permission to read the user's permissions is denied.
|
||||
*/
|
||||
protected boolean hasObjectPermission(AuthenticatedUser user,
|
||||
String identifier, ObjectPermission.Type type)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Get object permissions
|
||||
ObjectPermissionSet permissionSet = getPermissionSet(user);
|
||||
|
||||
// Return whether permission is granted
|
||||
return user.getUser().isAdministrator()
|
||||
|| permissionSet.hasPermission(type, identifier);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the permission set associated with the given user and related
|
||||
* to the type of 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 handled by this
|
||||
* directory object service.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If permission to read the user's permissions is denied.
|
||||
*/
|
||||
protected abstract ObjectPermissionSet getPermissionSet(AuthenticatedUser user)
|
||||
throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return
|
||||
* A collection of objects which are backed by the models in the given
|
||||
* collection.
|
||||
*/
|
||||
protected Collection<InternalType> getObjectInstances(AuthenticatedUser currentUser,
|
||||
Collection<ModelType> models) {
|
||||
|
||||
// Create new collection of objects by manually converting each model
|
||||
Collection<InternalType> objects = new ArrayList<InternalType>(models.size());
|
||||
for (ModelType model : models)
|
||||
objects.add(getObjectInstance(currentUser, model));
|
||||
|
||||
return objects;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the contents of the given model are valid and can be
|
||||
* used to create a new object as-is. The object does not yet exist in the
|
||||
* database, but the user desires to create a new object with the given
|
||||
* model. This function will be called prior to any creation operation, and
|
||||
* provides a means for the implementation to abort prior to completion. The
|
||||
* default implementation does nothing.
|
||||
*
|
||||
* @param user
|
||||
* The user creating the object.
|
||||
*
|
||||
* @param model
|
||||
* The model to validate.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the object is invalid, or an error prevents validating the given
|
||||
* object.
|
||||
*/
|
||||
protected void validateNewModel(AuthenticatedUser user,
|
||||
ModelType model) throws GuacamoleException {
|
||||
|
||||
// By default, do nothing.
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given model is valid and can be used to update an
|
||||
* existing object as-is. The object already exists in the database, but the
|
||||
* user desires to update the object to the given model. This function will
|
||||
* be called prior to update operation, and provides a means for the
|
||||
* implementation to abort prior to completion. The default implementation
|
||||
* does nothing.
|
||||
*
|
||||
* @param user
|
||||
* The user updating the existing object.
|
||||
*
|
||||
* @param model
|
||||
* The model to validate.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the object is invalid, or an error prevents validating the given
|
||||
* object.
|
||||
*/
|
||||
protected void validateExistingModel(AuthenticatedUser user,
|
||||
ModelType model) throws GuacamoleException {
|
||||
|
||||
// By default, do nothing.
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the single object that has the given identifier, if it exists
|
||||
* and the user has permission to read it.
|
||||
*
|
||||
* @param user
|
||||
* The user retrieving the object.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the object to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The object having the given identifier, or null if no such object
|
||||
* exists.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the requested object.
|
||||
*/
|
||||
public InternalType retrieveObject(AuthenticatedUser user,
|
||||
String identifier) throws GuacamoleException {
|
||||
|
||||
// Pull objects having given identifier
|
||||
Collection<InternalType> objects = retrieveObjects(user, Collections.singleton(identifier));
|
||||
|
||||
// If no such object, return null
|
||||
if (objects.isEmpty())
|
||||
return null;
|
||||
|
||||
// The object collection will have exactly one element unless the
|
||||
// database has seriously lost integrity
|
||||
assert(objects.size() == 1);
|
||||
|
||||
// Return first and only object
|
||||
return objects.iterator().next();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all objects that have the identifiers in the given collection.
|
||||
* Only objects that the user has permission to read will be returned.
|
||||
*
|
||||
* @param user
|
||||
* The user retrieving the objects.
|
||||
*
|
||||
* @param identifiers
|
||||
* The identifiers of the objects to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The objects having the given identifiers.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the requested objects.
|
||||
*/
|
||||
public Collection<InternalType> retrieveObjects(AuthenticatedUser user,
|
||||
Collection<String> identifiers) throws GuacamoleException {
|
||||
|
||||
// Do not query if no identifiers given
|
||||
if (identifiers.isEmpty())
|
||||
return Collections.EMPTY_LIST;
|
||||
|
||||
Collection<ModelType> objects;
|
||||
|
||||
// Bypass permission checks if the user is a system admin
|
||||
if (user.getUser().isAdministrator())
|
||||
objects = getObjectMapper().select(identifiers);
|
||||
|
||||
// Otherwise only return explicitly readable identifiers
|
||||
else
|
||||
objects = getObjectMapper().selectReadable(user.getUser().getModel(), identifiers);
|
||||
|
||||
// Return collection of requested objects
|
||||
return getObjectInstances(user, objects);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the given object within the database. If the object already
|
||||
* exists, an error will be thrown. The internal model object will be
|
||||
* updated appropriately to contain the new database ID.
|
||||
*
|
||||
* @param user
|
||||
* The user creating the object.
|
||||
*
|
||||
* @param object
|
||||
* The object to create.
|
||||
*
|
||||
* @return
|
||||
* The newly-created object.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the user lacks permission to create the object, or an error
|
||||
* occurs while creating the object.
|
||||
*/
|
||||
public InternalType createObject(AuthenticatedUser user, ExternalType object)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Only create object if user has permission to do so
|
||||
if (user.getUser().isAdministrator() || hasCreatePermission(user)) {
|
||||
|
||||
// Validate object prior to creation
|
||||
ModelType model = getModelInstance(user, object);
|
||||
validateNewModel(user, model);
|
||||
|
||||
// Create object
|
||||
getObjectMapper().insert(model);
|
||||
|
||||
// Build list of implicit permissions
|
||||
Collection<ObjectPermissionModel> implicitPermissions =
|
||||
new ArrayList<ObjectPermissionModel>(IMPLICIT_OBJECT_PERMISSIONS.length);
|
||||
|
||||
UserModel userModel = user.getUser().getModel();
|
||||
for (ObjectPermission.Type permission : IMPLICIT_OBJECT_PERMISSIONS) {
|
||||
|
||||
// Create model which grants this permission to the current user
|
||||
ObjectPermissionModel permissionModel = new ObjectPermissionModel();
|
||||
permissionModel.setUserID(userModel.getObjectID());
|
||||
permissionModel.setUsername(userModel.getIdentifier());
|
||||
permissionModel.setType(permission);
|
||||
permissionModel.setObjectIdentifier(model.getIdentifier());
|
||||
|
||||
// Add permission
|
||||
implicitPermissions.add(permissionModel);
|
||||
|
||||
}
|
||||
|
||||
// Add implicit permissions
|
||||
getPermissionMapper().insert(implicitPermissions);
|
||||
|
||||
return getObjectInstance(user, model);
|
||||
}
|
||||
|
||||
// User lacks permission to create
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the object having the given identifier. If no such object
|
||||
* exists, this function has no effect.
|
||||
*
|
||||
* @param user
|
||||
* The user deleting the object.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the object to delete.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the user lacks permission to delete the object, or an error
|
||||
* occurs while deleting the object.
|
||||
*/
|
||||
public void deleteObject(AuthenticatedUser user, String identifier)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Only delete object if user has permission to do so
|
||||
if (hasObjectPermission(user, identifier, ObjectPermission.Type.DELETE)) {
|
||||
getObjectMapper().delete(identifier);
|
||||
return;
|
||||
}
|
||||
|
||||
// User lacks permission to delete
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the given object in the database, applying any changes that have
|
||||
* been made. If no such object exists, this function has no effect.
|
||||
*
|
||||
* @param user
|
||||
* The user updating the object.
|
||||
*
|
||||
* @param object
|
||||
* The object to update.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the user lacks permission to update the object, or an error
|
||||
* occurs while updating the object.
|
||||
*/
|
||||
public void updateObject(AuthenticatedUser user, InternalType object)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Only update object if user has permission to do so
|
||||
if (hasObjectPermission(user, object.getIdentifier(), ObjectPermission.Type.UPDATE)) {
|
||||
|
||||
// Validate object prior to creation
|
||||
ModelType model = object.getModel();
|
||||
validateExistingModel(user, model);
|
||||
|
||||
// Update object
|
||||
getObjectMapper().update(model);
|
||||
return;
|
||||
}
|
||||
|
||||
// User lacks permission to update
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of all identifiers for all objects in the database that
|
||||
* the user has read access to.
|
||||
*
|
||||
* @param user
|
||||
* The user retrieving the identifiers.
|
||||
*
|
||||
* @return
|
||||
* The set of all identifiers for all objects in the database.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while reading identifiers.
|
||||
*/
|
||||
public Set<String> getIdentifiers(AuthenticatedUser user)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Bypass permission checks if the user is a system admin
|
||||
if (user.getUser().isAdministrator())
|
||||
return getObjectMapper().selectIdentifiers();
|
||||
|
||||
// Otherwise only return explicitly readable identifiers
|
||||
else
|
||||
return getObjectMapper().selectReadableIdentifiers(user.getUser().getModel());
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.base;
|
||||
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
|
||||
/**
|
||||
* Common base class for objects have an underlying model. For the purposes of
|
||||
* JDBC-driven authentication providers, all modeled objects are also
|
||||
* restricted.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
* @param <ModelType>
|
||||
* The type of model object which corresponds to this object.
|
||||
*/
|
||||
public abstract class ModeledObject<ModelType> extends RestrictedObject {
|
||||
|
||||
/**
|
||||
* The internal model object containing the values which represent this
|
||||
* object in the database.
|
||||
*/
|
||||
private ModelType model;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
super.init(currentUser);
|
||||
setModel(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the backing model object. Changes to the model object will
|
||||
* affect this object, and changes to this object will affect the model
|
||||
* object.
|
||||
*
|
||||
* @return
|
||||
* The backing model object.
|
||||
*/
|
||||
public ModelType getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the backing model object. This will effectively replace all data
|
||||
* contained within this object.
|
||||
*
|
||||
* @param model
|
||||
* The backing model object.
|
||||
*/
|
||||
public void setModel(ModelType model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.base;
|
||||
|
||||
/**
|
||||
* Object representation of a Guacamole object, such as a user or connection,
|
||||
* as represented in the database.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public abstract class ObjectModel {
|
||||
|
||||
/**
|
||||
* The ID of this object in the database, if any.
|
||||
*/
|
||||
private Integer objectID;
|
||||
|
||||
/**
|
||||
* The unique identifier which identifies this object.
|
||||
*/
|
||||
private String identifier;
|
||||
|
||||
/**
|
||||
* Creates a new, empty object.
|
||||
*/
|
||||
public ObjectModel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier that uniquely identifies this object.
|
||||
*
|
||||
* @return
|
||||
* The identifier that uniquely identifies this object.
|
||||
*/
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the identifier that uniquely identifies this object.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier that uniquely identifies this object.
|
||||
*/
|
||||
public void setIdentifier(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of this object in the database, if it exists.
|
||||
*
|
||||
* @return
|
||||
* The ID of this object in the database, or null if this object was
|
||||
* not retrieved from the database.
|
||||
*/
|
||||
public Integer getObjectID() {
|
||||
return objectID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ID of this object to the given value.
|
||||
*
|
||||
* @param objectID
|
||||
* The ID to assign to this object.
|
||||
*/
|
||||
public void setObjectID(Integer objectID) {
|
||||
this.objectID = objectID;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.base;
|
||||
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
|
||||
/**
|
||||
* Common base class for objects that are associated with the users that
|
||||
* obtain them.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public abstract class RestrictedObject {
|
||||
|
||||
/**
|
||||
* The user this object belongs to. Access is based on his/her permission
|
||||
* settings.
|
||||
*/
|
||||
private AuthenticatedUser currentUser;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void init(AuthenticatedUser currentUser) {
|
||||
setCurrentUser(currentUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base classes supporting JDBC-driven authentication providers and defining
|
||||
* the relationships between the model and the implementations of guacamole-ext
|
||||
* classes.
|
||||
*/
|
||||
package org.glyptodon.guacamole.auth.jdbc.base;
|
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.connection;
|
||||
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.RestrictedObject;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.mybatis.guice.transactional.Transactional;
|
||||
|
||||
/**
|
||||
* Implementation of the Connection Directory which is driven by an underlying,
|
||||
* arbitrary database.
|
||||
*
|
||||
* @author James Muehlner
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ConnectionDirectory extends RestrictedObject
|
||||
implements Directory<Connection> {
|
||||
|
||||
/**
|
||||
* Service for managing connection objects.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionService connectionService;
|
||||
|
||||
@Override
|
||||
public Connection get(String identifier) throws GuacamoleException {
|
||||
return connectionService.retrieveObject(getCurrentUser(), identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Collection<Connection> getAll(Collection<String> identifiers) throws GuacamoleException {
|
||||
Collection<ModeledConnection> objects = connectionService.retrieveObjects(getCurrentUser(), identifiers);
|
||||
return Collections.<Connection>unmodifiableCollection(objects);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Set<String> getIdentifiers() throws GuacamoleException {
|
||||
return connectionService.getIdentifiers(getCurrentUser());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void add(Connection object) throws GuacamoleException {
|
||||
connectionService.createObject(getCurrentUser(), object);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void update(Connection object) throws GuacamoleException {
|
||||
ModeledConnection connection = (ModeledConnection) object;
|
||||
connectionService.updateObject(getCurrentUser(), connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void remove(String identifier) throws GuacamoleException {
|
||||
connectionService.deleteObject(getCurrentUser(), identifier);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.connection;
|
||||
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* Mapper for connection objects.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface ConnectionMapper extends DirectoryObjectMapper<ConnectionModel> {
|
||||
|
||||
/**
|
||||
* Selects the identifiers of all connections within the given parent
|
||||
* connection group, regardless of whether they are readable by any
|
||||
* particular user. 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
|
||||
* selectReadableIdentifiersWithin() instead.
|
||||
*
|
||||
* @param parentIdentifier
|
||||
* The identifier of the parent connection group, or null if the root
|
||||
* connection group is to be queried.
|
||||
*
|
||||
* @return
|
||||
* A Set containing all identifiers of all objects.
|
||||
*/
|
||||
Set<String> selectIdentifiersWithin(@Param("parentIdentifier") String parentIdentifier);
|
||||
|
||||
/**
|
||||
* Selects the identifiers of all connections within the given parent
|
||||
* connection group that 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 selectIdentifiersWithin()
|
||||
* instead.
|
||||
*
|
||||
* @param user
|
||||
* The user whose permissions should determine whether an identifier
|
||||
* is returned.
|
||||
*
|
||||
* @param parentIdentifier
|
||||
* The identifier of the parent connection group, or null if the root
|
||||
* connection group is to be queried.
|
||||
*
|
||||
* @return
|
||||
* A Set containing all identifiers of all readable objects.
|
||||
*/
|
||||
Set<String> selectReadableIdentifiersWithin(@Param("user") UserModel user,
|
||||
@Param("parentIdentifier") String parentIdentifier);
|
||||
|
||||
/**
|
||||
* Selects the connection within the given parent group and having the
|
||||
* given name. If no such connection exists, null is returned.
|
||||
*
|
||||
* @param parentIdentifier
|
||||
* The identifier of the parent group to search within.
|
||||
*
|
||||
* @param name
|
||||
* The name of the connection to find.
|
||||
*
|
||||
* @return
|
||||
* The connection having the given name within the given parent group,
|
||||
* or null if no such connection exists.
|
||||
*/
|
||||
ConnectionModel selectOneByName(@Param("parentIdentifier") String parentIdentifier,
|
||||
@Param("name") String name);
|
||||
|
||||
}
|
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.connection;
|
||||
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.ObjectModel;
|
||||
|
||||
/**
|
||||
* Object representation of a Guacamole connection, as represented in the
|
||||
* database.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ConnectionModel extends ObjectModel {
|
||||
|
||||
/**
|
||||
* The identifier of the parent connection group in the database, or null
|
||||
* if the parent connection group is the root group.
|
||||
*/
|
||||
private String parentIdentifier;
|
||||
|
||||
/**
|
||||
* The human-readable name associated with this connection.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The name of the protocol to use when connecting to this connection.
|
||||
*/
|
||||
private String protocol;
|
||||
|
||||
/**
|
||||
* Creates a new, empty connection.
|
||||
*/
|
||||
public ConnectionModel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name associated with this connection.
|
||||
*
|
||||
* @return
|
||||
* The name associated with this connection.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name associated with this connection.
|
||||
*
|
||||
* @param name
|
||||
* The name to associate with this connection.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the protocol to use when connecting to this
|
||||
* connection.
|
||||
*
|
||||
* @return
|
||||
* The name of the protocol to use when connecting to this connection.
|
||||
*/
|
||||
public String getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the protocol to use when connecting to this connection.
|
||||
*
|
||||
* @param protocol
|
||||
* The name of the protocol to use when connecting to this connection.
|
||||
*/
|
||||
public void setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
|
||||
// If no associated ID, then no associated identifier
|
||||
Integer id = getObjectID();
|
||||
if (id == null)
|
||||
return null;
|
||||
|
||||
// Otherwise, the identifier is the ID as a string
|
||||
return id.toString();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(String identifier) {
|
||||
throw new UnsupportedOperationException("Connection identifiers are derived from IDs. They cannot be set.");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.connection;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* Mapper for connection record objects.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface ConnectionRecordMapper {
|
||||
|
||||
/**
|
||||
* Returns a collection of all connection records associated with the
|
||||
* connection having the given identifier.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the connection whose records are to be retrieved.
|
||||
*
|
||||
* @return
|
||||
* A collection of all connection records associated with the
|
||||
* connection having the given identifier. This collection will be
|
||||
* empty if no such connection exists.
|
||||
*/
|
||||
List<ConnectionRecordModel> select(@Param("identifier") String identifier);
|
||||
|
||||
/**
|
||||
* Inserts the given connection record.
|
||||
*
|
||||
* @param record
|
||||
* The connection record to insert.
|
||||
*
|
||||
* @return
|
||||
* The number of rows inserted.
|
||||
*/
|
||||
int insert(@Param("record") ConnectionRecordModel record);
|
||||
|
||||
}
|
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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.connection;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* A single connection record representing a past usage of a particular
|
||||
* connection.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ConnectionRecordModel {
|
||||
|
||||
/**
|
||||
* The identifier of the connection associated with this connection record.
|
||||
*/
|
||||
private String connectionIdentifier;
|
||||
|
||||
/**
|
||||
* The database ID of the user associated with this connection record.
|
||||
*/
|
||||
private Integer userID;
|
||||
|
||||
/**
|
||||
* The username of the user associated with this connection record.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* The time the connection was initiated by the associated user.
|
||||
*/
|
||||
private Date startDate;
|
||||
|
||||
/**
|
||||
* The time the connection ended, or null if the end time is not known or
|
||||
* the connection is still running.
|
||||
*/
|
||||
private Date endDate;
|
||||
|
||||
/**
|
||||
* Returns the identifier of the connection associated with this connection
|
||||
* record.
|
||||
*
|
||||
* @return
|
||||
* The identifier of the connection associated with this connection
|
||||
* record.
|
||||
*/
|
||||
public String getConnectionIdentifier() {
|
||||
return connectionIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the identifier of the connection associated with this connection
|
||||
* record.
|
||||
*
|
||||
* @param connectionIdentifier
|
||||
* The identifier of the connection to associate with this connection
|
||||
* record.
|
||||
*/
|
||||
public void setConnectionIdentifier(String connectionIdentifier) {
|
||||
this.connectionIdentifier = connectionIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database ID of the user associated with this connection
|
||||
* record.
|
||||
*
|
||||
* @return
|
||||
* The database ID of the user associated with this connection record.
|
||||
*/
|
||||
public Integer getUserID() {
|
||||
return userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database ID of the user associated with this connection record.
|
||||
*
|
||||
* @param userID
|
||||
* The database ID of the user to associate with this connection
|
||||
* record.
|
||||
*/
|
||||
public void setUserID(Integer userID) {
|
||||
this.userID = userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the username of the user associated with this connection record.
|
||||
*
|
||||
* @return
|
||||
* The username of the user associated with this connection record.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the username of the user associated with this connection record.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user to associate with this connection record.
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date that the associated connection was established.
|
||||
*
|
||||
* @return
|
||||
* The date the associated connection was established.
|
||||
*/
|
||||
public Date getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date that the associated connection was established.
|
||||
*
|
||||
* @param startDate
|
||||
* The date that the associated connection was established.
|
||||
*/
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date that the associated connection ended, or null if no
|
||||
* end date was recorded. The lack of an end date does not necessarily
|
||||
* mean that the connection is still active.
|
||||
*
|
||||
* @return
|
||||
* The date the associated connection ended, or null if no end date was
|
||||
* recorded.
|
||||
*/
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date that the associated connection ended.
|
||||
*
|
||||
* @param endDate
|
||||
* The date that the associated connection ended.
|
||||
*/
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.connection;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
|
||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleSecurityException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionPermissionMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
|
||||
import org.glyptodon.guacamole.net.GuacamoleSocket;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* manipulating connections.
|
||||
*
|
||||
* @author Michael Jumper, James Muehlner
|
||||
*/
|
||||
public class ConnectionService extends DirectoryObjectService<ModeledConnection, Connection, ConnectionModel> {
|
||||
|
||||
/**
|
||||
* Mapper for accessing connections.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionMapper connectionMapper;
|
||||
|
||||
/**
|
||||
* Mapper for manipulating connection permissions.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionPermissionMapper connectionPermissionMapper;
|
||||
|
||||
/**
|
||||
* Mapper for accessing connection parameters.
|
||||
*/
|
||||
@Inject
|
||||
private ParameterMapper parameterMapper;
|
||||
|
||||
/**
|
||||
* Mapper for accessing connection history.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionRecordMapper connectionRecordMapper;
|
||||
|
||||
/**
|
||||
* Provider for creating connections.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<ModeledConnection> connectionProvider;
|
||||
|
||||
/**
|
||||
* Service for creating and tracking sockets.
|
||||
*/
|
||||
@Inject
|
||||
private GuacamoleSocketService socketService;
|
||||
|
||||
@Override
|
||||
protected DirectoryObjectMapper<ConnectionModel> getObjectMapper() {
|
||||
return connectionMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionMapper getPermissionMapper() {
|
||||
return connectionPermissionMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ModeledConnection getObjectInstance(AuthenticatedUser currentUser,
|
||||
ConnectionModel model) {
|
||||
ModeledConnection connection = connectionProvider.get();
|
||||
connection.init(currentUser, model);
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionModel getModelInstance(AuthenticatedUser currentUser,
|
||||
final Connection object) {
|
||||
|
||||
// Create new ModeledConnection backed by blank model
|
||||
ConnectionModel model = new ConnectionModel();
|
||||
ModeledConnection connection = getObjectInstance(currentUser, model);
|
||||
|
||||
// Set model contents through ModeledConnection, copying the provided connection
|
||||
connection.setParentIdentifier(object.getParentIdentifier());
|
||||
connection.setName(object.getName());
|
||||
connection.setConfiguration(object.getConfiguration());
|
||||
|
||||
return model;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasCreatePermission(AuthenticatedUser user)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Return whether user has explicit connection creation permission
|
||||
SystemPermissionSet permissionSet = user.getUser().getSystemPermissions();
|
||||
return permissionSet.hasPermission(SystemPermission.Type.CREATE_CONNECTION);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionSet getPermissionSet(AuthenticatedUser user)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Return permissions related to connections
|
||||
return user.getUser().getConnectionPermissions();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateNewModel(AuthenticatedUser user,
|
||||
ConnectionModel model) throws GuacamoleException {
|
||||
|
||||
// Name must not be blank
|
||||
if (model.getName().trim().isEmpty())
|
||||
throw new GuacamoleClientException("Connection names must not be blank.");
|
||||
|
||||
// Do not attempt to create duplicate connections
|
||||
ConnectionModel existing = connectionMapper.selectOneByName(model.getParentIdentifier(), model.getName());
|
||||
if (existing != null)
|
||||
throw new GuacamoleClientException("The connection \"" + model.getName() + "\" already exists.");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateExistingModel(AuthenticatedUser user,
|
||||
ConnectionModel model) throws GuacamoleException {
|
||||
|
||||
// Name must not be blank
|
||||
if (model.getName().trim().isEmpty())
|
||||
throw new GuacamoleClientException("Connection names must not be blank.");
|
||||
|
||||
// Check whether such a connection is already present
|
||||
ConnectionModel existing = connectionMapper.selectOneByName(model.getParentIdentifier(), model.getName());
|
||||
if (existing != null) {
|
||||
|
||||
// If the specified name matches a DIFFERENT existing connection, the update cannot continue
|
||||
if (!existing.getObjectID().equals(model.getObjectID()))
|
||||
throw new GuacamoleClientException("The connection \"" + model.getName() + "\" already exists.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an arbitrary Guacamole connection, produces a collection of
|
||||
* parameter model objects containing the name/value pairs of that
|
||||
* connection's parameters.
|
||||
*
|
||||
* @param connection
|
||||
* The connection whose configuration should be used to produce the
|
||||
* collection of parameter models.
|
||||
*
|
||||
* @return
|
||||
* A collection of parameter models containing the name/value pairs
|
||||
* of the given connection's parameters.
|
||||
*/
|
||||
private Collection<ParameterModel> getParameterModels(ModeledConnection connection) {
|
||||
|
||||
Map<String, String> parameters = connection.getConfiguration().getParameters();
|
||||
|
||||
// Convert parameters to model objects
|
||||
Collection<ParameterModel> parameterModels = new ArrayList(parameters.size());
|
||||
for (Map.Entry<String, String> parameterEntry : parameters.entrySet()) {
|
||||
|
||||
// Get parameter name and value
|
||||
String name = parameterEntry.getKey();
|
||||
String value = parameterEntry.getValue();
|
||||
|
||||
// There is no need to insert empty parameters
|
||||
if (value.isEmpty())
|
||||
continue;
|
||||
|
||||
// Produce model object from parameter
|
||||
ParameterModel model = new ParameterModel();
|
||||
model.setConnectionIdentifier(connection.getIdentifier());
|
||||
model.setName(name);
|
||||
model.setValue(value);
|
||||
|
||||
// Add model to list
|
||||
parameterModels.add(model);
|
||||
|
||||
}
|
||||
|
||||
return parameterModels;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModeledConnection createObject(AuthenticatedUser user, Connection object)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Create connection
|
||||
ModeledConnection connection = super.createObject(user, object);
|
||||
connection.setConfiguration(object.getConfiguration());
|
||||
|
||||
// Insert new parameters, if any
|
||||
Collection<ParameterModel> parameterModels = getParameterModels(connection);
|
||||
if (!parameterModels.isEmpty())
|
||||
parameterMapper.insert(parameterModels);
|
||||
|
||||
return connection;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateObject(AuthenticatedUser user, ModeledConnection object)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Update connection
|
||||
super.updateObject(user, object);
|
||||
|
||||
// Replace existing parameters with new parameters, if any
|
||||
Collection<ParameterModel> parameterModels = getParameterModels(object);
|
||||
parameterMapper.delete(object.getIdentifier());
|
||||
if (!parameterModels.isEmpty())
|
||||
parameterMapper.insert(parameterModels);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of all identifiers for all connections within the
|
||||
* connection group having the given identifier. Only connections that the
|
||||
* user has read access to will be returned.
|
||||
*
|
||||
* Permission to read the connection group having the given identifier is
|
||||
* NOT checked.
|
||||
*
|
||||
* @param user
|
||||
* The user retrieving the identifiers.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the parent connection group, or null to check the
|
||||
* root connection group.
|
||||
*
|
||||
* @return
|
||||
* The set of all identifiers for all connections in the connection
|
||||
* group having the given identifier that the user has read access to.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while reading identifiers.
|
||||
*/
|
||||
public Set<String> getIdentifiersWithin(AuthenticatedUser user,
|
||||
String identifier)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Bypass permission checks if the user is a system admin
|
||||
if (user.getUser().isAdministrator())
|
||||
return connectionMapper.selectIdentifiersWithin(identifier);
|
||||
|
||||
// Otherwise only return explicitly readable identifiers
|
||||
else
|
||||
return connectionMapper.selectReadableIdentifiersWithin(user.getUser().getModel(), identifier);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all parameters visible to the given user and associated with
|
||||
* the connection having the given identifier. If the given user has no
|
||||
* access to such parameters, or no such connection exists, the returned
|
||||
* map will be empty.
|
||||
*
|
||||
* @param user
|
||||
* The user retrieving connection parameters.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the connection whose parameters are being
|
||||
* retrieved.
|
||||
*
|
||||
* @return
|
||||
* A new map of all parameter name/value pairs that the given user has
|
||||
* access to.
|
||||
*/
|
||||
public Map<String, String> retrieveParameters(AuthenticatedUser user,
|
||||
String identifier) {
|
||||
|
||||
Map<String, String> parameterMap = new HashMap<String, String>();
|
||||
|
||||
// Determine whether we have permission to read parameters
|
||||
boolean canRetrieveParameters;
|
||||
try {
|
||||
canRetrieveParameters = hasObjectPermission(user, identifier,
|
||||
ObjectPermission.Type.UPDATE);
|
||||
}
|
||||
|
||||
// Provide empty (but mutable) map if unable to check permissions
|
||||
catch (GuacamoleException e) {
|
||||
return parameterMap;
|
||||
}
|
||||
|
||||
// Populate parameter map if we have permission to do so
|
||||
if (canRetrieveParameters) {
|
||||
for (ParameterModel parameter : parameterMapper.select(identifier))
|
||||
parameterMap.put(parameter.getName(), parameter.getValue());
|
||||
}
|
||||
|
||||
return parameterMap;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the connection history of the given connection, including any
|
||||
* active connections.
|
||||
*
|
||||
* @param user
|
||||
* The user retrieving the connection history.
|
||||
*
|
||||
* @param connection
|
||||
* The connection whose history is being retrieved.
|
||||
*
|
||||
* @return
|
||||
* The connection history of the given connection, including any
|
||||
* active connections.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If permission to read the connection history is denied.
|
||||
*/
|
||||
public List<ConnectionRecord> retrieveHistory(AuthenticatedUser user,
|
||||
ModeledConnection connection) throws GuacamoleException {
|
||||
|
||||
String identifier = connection.getIdentifier();
|
||||
|
||||
// Retrieve history only if READ permission is granted
|
||||
if (hasObjectPermission(user, identifier, ObjectPermission.Type.READ)) {
|
||||
|
||||
// Retrieve history
|
||||
List<ConnectionRecordModel> models = connectionRecordMapper.select(identifier);
|
||||
|
||||
// Get currently-active connections
|
||||
List<ConnectionRecord> records = new ArrayList<ConnectionRecord>(socketService.getActiveConnections(connection));
|
||||
|
||||
// Add past connections from model objects
|
||||
for (ConnectionRecordModel model : models)
|
||||
records.add(new ModeledConnectionRecord(model));
|
||||
|
||||
// Return converted history list
|
||||
return records;
|
||||
|
||||
}
|
||||
|
||||
// The user does not have permission to read the history
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the given connection as the given user, using the given
|
||||
* client information. If the user does not have permission to read the
|
||||
* connection, permission will be denied.
|
||||
*
|
||||
* @param user
|
||||
* The user connecting to the connection.
|
||||
*
|
||||
* @param connection
|
||||
* The connection being connected to.
|
||||
*
|
||||
* @param info
|
||||
* Information associated with the connecting client.
|
||||
*
|
||||
* @return
|
||||
* A connected GuacamoleSocket associated with a newly-established
|
||||
* connection.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If permission to connect to this connection is denied.
|
||||
*/
|
||||
public GuacamoleSocket connect(AuthenticatedUser user,
|
||||
ModeledConnection connection, GuacamoleClientInformation info)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Connect only if READ permission is granted
|
||||
if (hasObjectPermission(user, connection.getIdentifier(), ObjectPermission.Type.READ))
|
||||
return socketService.getGuacamoleSocket(user, connection, info);
|
||||
|
||||
// The user does not have permission to connect
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.connection;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import java.util.List;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObject;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.RootConnectionGroup;
|
||||
import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.GuacamoleSocket;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
|
||||
|
||||
/**
|
||||
* An implementation of the Connection object which is backed by a database
|
||||
* model.
|
||||
*
|
||||
* @author James Muehlner
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ModeledConnection extends DirectoryObject<ConnectionModel>
|
||||
implements Connection {
|
||||
|
||||
/**
|
||||
* Service for managing connections.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionService connectionService;
|
||||
|
||||
/**
|
||||
* Service for creating and tracking sockets.
|
||||
*/
|
||||
@Inject
|
||||
private GuacamoleSocketService socketService;
|
||||
|
||||
/**
|
||||
* Provider for lazy-loaded, permission-controlled configurations.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<ModeledGuacamoleConfiguration> configProvider;
|
||||
|
||||
/**
|
||||
* The manually-set GuacamoleConfiguration, if any.
|
||||
*/
|
||||
private GuacamoleConfiguration config = null;
|
||||
|
||||
/**
|
||||
* Creates a new, empty ModeledConnection.
|
||||
*/
|
||||
public ModeledConnection() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getModel().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
getModel().setName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParentIdentifier() {
|
||||
|
||||
// Translate null parent to proper identifier
|
||||
String parentIdentifier = getModel().getParentIdentifier();
|
||||
if (parentIdentifier == null)
|
||||
return RootConnectionGroup.IDENTIFIER;
|
||||
|
||||
return parentIdentifier;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParentIdentifier(String parentIdentifier) {
|
||||
|
||||
// Translate root identifier back into null
|
||||
if (parentIdentifier != null
|
||||
&& parentIdentifier.equals(RootConnectionGroup.IDENTIFIER))
|
||||
parentIdentifier = null;
|
||||
|
||||
getModel().setParentIdentifier(parentIdentifier);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleConfiguration getConfiguration() {
|
||||
|
||||
// If configuration has been manually set, return that
|
||||
if (config != null)
|
||||
return config;
|
||||
|
||||
// Otherwise, return permission-controlled configuration
|
||||
ModeledGuacamoleConfiguration restrictedConfig = configProvider.get();
|
||||
restrictedConfig.init(getCurrentUser(), getModel());
|
||||
return restrictedConfig;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfiguration(GuacamoleConfiguration config) {
|
||||
|
||||
// Store manually-set configuration internally
|
||||
this.config = config;
|
||||
|
||||
// Update model
|
||||
getModel().setProtocol(config.getProtocol());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends ConnectionRecord> getHistory() throws GuacamoleException {
|
||||
return connectionService.retrieveHistory(getCurrentUser(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleSocket connect(GuacamoleClientInformation info) throws GuacamoleException {
|
||||
return connectionService.connect(getCurrentUser(), this, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActiveConnections() {
|
||||
return socketService.getActiveConnections(this).size();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.connection;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
|
||||
|
||||
/**
|
||||
* A ConnectionRecord which is backed by a database model.
|
||||
*
|
||||
* @author James Muehlner
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ModeledConnectionRecord implements ConnectionRecord {
|
||||
|
||||
/**
|
||||
* The model object backing this connection record.
|
||||
*/
|
||||
private final ConnectionRecordModel model;
|
||||
|
||||
/**
|
||||
* Creates a new ModeledConnectionRecord backed by the given model object.
|
||||
* Changes to this record will affect the backing model object, and changes
|
||||
* to the backing model object will affect this record.
|
||||
*
|
||||
* @param model
|
||||
* The model object to use to back this connection record.
|
||||
*/
|
||||
public ModeledConnectionRecord(ConnectionRecordModel model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getStartDate() {
|
||||
return model.getStartDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getEndDate() {
|
||||
return model.getEndDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return model.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.connection;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Map;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
|
||||
|
||||
/**
|
||||
* Implementation of GuacamoleConfiguration which loads parameter values only
|
||||
* if necessary, and only if allowed.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ModeledGuacamoleConfiguration extends GuacamoleConfiguration {
|
||||
|
||||
/**
|
||||
* The user this configuration belongs to. Access is based on his/her
|
||||
* permission settings.
|
||||
*/
|
||||
private AuthenticatedUser currentUser;
|
||||
|
||||
/**
|
||||
* The internal model object containing the values which represent the
|
||||
* connection associated with this configuration.
|
||||
*/
|
||||
private ConnectionModel connectionModel;
|
||||
|
||||
/**
|
||||
* Service for managing connection parameters.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionService connectionService;
|
||||
|
||||
/**
|
||||
* The manually-set parameter map, if any.
|
||||
*/
|
||||
private Map<String, String> parameters = null;
|
||||
|
||||
/**
|
||||
* Creates a new, empty ModelGuacamoleConfiguration.
|
||||
*/
|
||||
public ModeledGuacamoleConfiguration() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this configuration, 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 configuration.
|
||||
*
|
||||
* @param connectionModel
|
||||
* The model object backing this configuration.
|
||||
*/
|
||||
public void init(AuthenticatedUser currentUser, ConnectionModel connectionModel) {
|
||||
this.currentUser = currentUser;
|
||||
this.connectionModel = connectionModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol() {
|
||||
return connectionModel.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProtocol(String protocol) {
|
||||
super.setProtocol(protocol);
|
||||
connectionModel.setProtocol(protocol);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setParameters(Map<String, String> parameters) {
|
||||
this.parameters = parameters;
|
||||
super.setParameters(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getParameters() {
|
||||
|
||||
// Retrieve visible parameters, if not overridden by setParameters()
|
||||
if (parameters == null) {
|
||||
|
||||
// Retrieve all visible parameters
|
||||
Map<String, String> visibleParameters =
|
||||
connectionService.retrieveParameters(currentUser, connectionModel.getIdentifier());
|
||||
|
||||
// Use retrieved parameters to back future operations
|
||||
super.setParameters(visibleParameters);
|
||||
|
||||
}
|
||||
|
||||
return super.getParameters();
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.connection;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* Mapper for connection parameter objects.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface ParameterMapper {
|
||||
|
||||
/**
|
||||
* Returns a collection of all parameters associated with the connection
|
||||
* having the given identifier.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the connection whose parameters are to be
|
||||
* retrieved.
|
||||
*
|
||||
* @return
|
||||
* A collection of all parameters associated with the connection
|
||||
* having the given identifier. This collection will be empty if no
|
||||
* such connection exists.
|
||||
*/
|
||||
Collection<ParameterModel> select(@Param("identifier") String identifier);
|
||||
|
||||
/**
|
||||
* Inserts each of the parameter model objects in the given collection as
|
||||
* new connection parameters.
|
||||
*
|
||||
* @param parameters
|
||||
* The connection parameters to insert.
|
||||
*
|
||||
* @return
|
||||
* The number of rows inserted.
|
||||
*/
|
||||
int insert(@Param("parameters") Collection<ParameterModel> parameters);
|
||||
|
||||
/**
|
||||
* Deletes all parameters associated with the connection having the given
|
||||
* identifier.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the connection whose parameters should be
|
||||
* deleted.
|
||||
*
|
||||
* @return
|
||||
* The number of rows deleted.
|
||||
*/
|
||||
int delete(@Param("identifier") String identifier);
|
||||
|
||||
}
|
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.connection;
|
||||
|
||||
/**
|
||||
* A single parameter name/value pair belonging to a connection.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ParameterModel {
|
||||
|
||||
/**
|
||||
* The identifier of the connection associated with this parameter.
|
||||
*/
|
||||
private String connectionIdentifier;
|
||||
|
||||
/**
|
||||
* The name of the parameter.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The value the parameter is set to.
|
||||
*/
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* Returns the identifier of the connection associated with this parameter.
|
||||
*
|
||||
* @return
|
||||
* The identifier of the connection associated with this parameter.
|
||||
*/
|
||||
public String getConnectionIdentifier() {
|
||||
return connectionIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the identifier of the connection associated with this parameter.
|
||||
*
|
||||
* @param connectionIdentifier
|
||||
* The identifier of the connection to associate with this parameter.
|
||||
*/
|
||||
public void setConnectionIdentifier(String connectionIdentifier) {
|
||||
this.connectionIdentifier = connectionIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this parameter.
|
||||
*
|
||||
* @return
|
||||
* The name of this parameter.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of this parameter.
|
||||
*
|
||||
* @param name
|
||||
* The name of this parameter.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of this parameter.
|
||||
*
|
||||
* @return
|
||||
* The value of this parameter.
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this parameter.
|
||||
*
|
||||
* @param value
|
||||
* The value of this parameter.
|
||||
*/
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
* 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
|
||||
@@ -21,8 +21,6 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service classes which help fill the needs of the MySQL authentication
|
||||
* provider.
|
||||
* Classes related to connections and their parameters and history.
|
||||
*/
|
||||
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||
|
||||
package org.glyptodon.guacamole.auth.jdbc.connection;
|
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.connectiongroup;
|
||||
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.RestrictedObject;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.mybatis.guice.transactional.Transactional;
|
||||
|
||||
/**
|
||||
* Implementation of the ConnectionGroup Directory which is driven by an
|
||||
* underlying, arbitrary database.
|
||||
*
|
||||
* @author James Muehlner
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ConnectionGroupDirectory extends RestrictedObject
|
||||
implements Directory<ConnectionGroup> {
|
||||
|
||||
/**
|
||||
* Service for managing connection group objects.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupService connectionGroupService;
|
||||
|
||||
@Override
|
||||
public ConnectionGroup get(String identifier) throws GuacamoleException {
|
||||
return connectionGroupService.retrieveObject(getCurrentUser(), identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Collection<ConnectionGroup> getAll(Collection<String> identifiers) throws GuacamoleException {
|
||||
Collection<ModeledConnectionGroup> objects = connectionGroupService.retrieveObjects(getCurrentUser(), identifiers);
|
||||
return Collections.<ConnectionGroup>unmodifiableCollection(objects);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Set<String> getIdentifiers() throws GuacamoleException {
|
||||
return connectionGroupService.getIdentifiers(getCurrentUser());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void add(ConnectionGroup object) throws GuacamoleException {
|
||||
connectionGroupService.createObject(getCurrentUser(), object);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void update(ConnectionGroup object) throws GuacamoleException {
|
||||
ModeledConnectionGroup connectionGroup = (ModeledConnectionGroup) object;
|
||||
connectionGroupService.updateObject(getCurrentUser(), connectionGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void remove(String identifier) throws GuacamoleException {
|
||||
connectionGroupService.deleteObject(getCurrentUser(), identifier);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.connectiongroup;
|
||||
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* Mapper for connection group objects.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface ConnectionGroupMapper extends DirectoryObjectMapper<ConnectionGroupModel> {
|
||||
|
||||
/**
|
||||
* Selects the identifiers of all connection groups within the given parent
|
||||
* connection group, regardless of whether they are readable by any
|
||||
* particular user. 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
|
||||
* selectReadableIdentifiersWithin() instead.
|
||||
*
|
||||
* @param parentIdentifier
|
||||
* The identifier of the parent connection group, or null if the root
|
||||
* connection group is to be queried.
|
||||
*
|
||||
* @return
|
||||
* A Set containing all identifiers of all objects.
|
||||
*/
|
||||
Set<String> selectIdentifiersWithin(@Param("parentIdentifier") String parentIdentifier);
|
||||
|
||||
/**
|
||||
* Selects the identifiers of all connection groups within the given parent
|
||||
* connection group that 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 selectIdentifiersWithin()
|
||||
* instead.
|
||||
*
|
||||
* @param user
|
||||
* The user whose permissions should determine whether an identifier
|
||||
* is returned.
|
||||
*
|
||||
* @param parentIdentifier
|
||||
* The identifier of the parent connection group, or null if the root
|
||||
* connection group is to be queried.
|
||||
*
|
||||
* @return
|
||||
* A Set containing all identifiers of all readable objects.
|
||||
*/
|
||||
Set<String> selectReadableIdentifiersWithin(@Param("user") UserModel user,
|
||||
@Param("parentIdentifier") String parentIdentifier);
|
||||
|
||||
/**
|
||||
* Selects the connection group within the given parent group and having
|
||||
* the given name. If no such connection group exists, null is returned.
|
||||
*
|
||||
* @param parentIdentifier
|
||||
* The identifier of the parent group to search within.
|
||||
*
|
||||
* @param name
|
||||
* The name of the connection group to find.
|
||||
*
|
||||
* @return
|
||||
* The connection group having the given name within the given parent
|
||||
* group, or null if no such connection group exists.
|
||||
*/
|
||||
ConnectionGroupModel selectOneByName(@Param("parentIdentifier") String parentIdentifier,
|
||||
@Param("name") String name);
|
||||
|
||||
}
|
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.connectiongroup;
|
||||
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.ObjectModel;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
|
||||
/**
|
||||
* Object representation of a Guacamole connection group, as represented in the
|
||||
* database.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ConnectionGroupModel extends ObjectModel {
|
||||
|
||||
/**
|
||||
* The identifier of the parent connection group in the database, or null
|
||||
* if the parent connection group is the root group.
|
||||
*/
|
||||
private String parentIdentifier;
|
||||
|
||||
/**
|
||||
* The human-readable name associated with this connection group.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The type of this connection group, such as organizational or balancing.
|
||||
*/
|
||||
private ConnectionGroup.Type type;
|
||||
|
||||
/**
|
||||
* Creates a new, empty connection group.
|
||||
*/
|
||||
public ConnectionGroupModel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name associated with this connection group.
|
||||
*
|
||||
* @return
|
||||
* The name associated with this connection group.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name associated with this connection group.
|
||||
*
|
||||
* @param name
|
||||
* The name to associate with this connection group.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this connection group, such as organizational or
|
||||
* balancing.
|
||||
*
|
||||
* @return
|
||||
* The type of this connection group.
|
||||
*/
|
||||
public ConnectionGroup.Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of this connection group, such as organizational or
|
||||
* balancing.
|
||||
*
|
||||
* @param type
|
||||
* The type of this connection group.
|
||||
*/
|
||||
public void setType(ConnectionGroup.Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
|
||||
// If no associated ID, then no associated identifier
|
||||
Integer id = getObjectID();
|
||||
if (id == null)
|
||||
return null;
|
||||
|
||||
// Otherwise, the identifier is the ID as a string
|
||||
return id.toString();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(String identifier) {
|
||||
throw new UnsupportedOperationException("Connection group identifiers are derived from IDs. They cannot be set.");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.connectiongroup;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
|
||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleSecurityException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionGroupPermissionMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
|
||||
import org.glyptodon.guacamole.net.GuacamoleSocket;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* manipulating connection groups.
|
||||
*
|
||||
* @author Michael Jumper, James Muehlner
|
||||
*/
|
||||
public class ConnectionGroupService extends DirectoryObjectService<ModeledConnectionGroup,
|
||||
ConnectionGroup, ConnectionGroupModel> {
|
||||
|
||||
/**
|
||||
* Mapper for accessing connection groups.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupMapper connectionGroupMapper;
|
||||
|
||||
/**
|
||||
* Mapper for manipulating connection group permissions.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupPermissionMapper connectionGroupPermissionMapper;
|
||||
|
||||
/**
|
||||
* Provider for creating connection groups.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<ModeledConnectionGroup> connectionGroupProvider;
|
||||
|
||||
/**
|
||||
* Service for creating and tracking sockets.
|
||||
*/
|
||||
@Inject
|
||||
private GuacamoleSocketService socketService;
|
||||
|
||||
@Override
|
||||
protected DirectoryObjectMapper<ConnectionGroupModel> getObjectMapper() {
|
||||
return connectionGroupMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionMapper getPermissionMapper() {
|
||||
return connectionGroupPermissionMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ModeledConnectionGroup getObjectInstance(AuthenticatedUser currentUser,
|
||||
ConnectionGroupModel model) {
|
||||
ModeledConnectionGroup connectionGroup = connectionGroupProvider.get();
|
||||
connectionGroup.init(currentUser, model);
|
||||
return connectionGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConnectionGroupModel getModelInstance(AuthenticatedUser currentUser,
|
||||
final ConnectionGroup object) {
|
||||
|
||||
// Create new ModeledConnectionGroup backed by blank model
|
||||
ConnectionGroupModel model = new ConnectionGroupModel();
|
||||
ModeledConnectionGroup connectionGroup = getObjectInstance(currentUser, model);
|
||||
|
||||
// Set model contents through ModeledConnectionGroup, copying the provided connection group
|
||||
connectionGroup.setParentIdentifier(object.getParentIdentifier());
|
||||
connectionGroup.setName(object.getName());
|
||||
connectionGroup.setType(object.getType());
|
||||
|
||||
return model;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasCreatePermission(AuthenticatedUser user)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Return whether user has explicit connection group creation permission
|
||||
SystemPermissionSet permissionSet = user.getUser().getSystemPermissions();
|
||||
return permissionSet.hasPermission(SystemPermission.Type.CREATE_CONNECTION_GROUP);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionSet getPermissionSet(AuthenticatedUser user)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Return permissions related to connection groups
|
||||
return user.getUser().getConnectionGroupPermissions();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateNewModel(AuthenticatedUser user,
|
||||
ConnectionGroupModel model) throws GuacamoleException {
|
||||
|
||||
// Name must not be blank
|
||||
if (model.getName().trim().isEmpty())
|
||||
throw new GuacamoleClientException("Connection group names must not be blank.");
|
||||
|
||||
// Do not attempt to create duplicate connection groups
|
||||
ConnectionGroupModel existing = connectionGroupMapper.selectOneByName(model.getParentIdentifier(), model.getName());
|
||||
if (existing != null)
|
||||
throw new GuacamoleClientException("The connection group \"" + model.getName() + "\" already exists.");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateExistingModel(AuthenticatedUser user,
|
||||
ConnectionGroupModel model) throws GuacamoleException {
|
||||
|
||||
// Name must not be blank
|
||||
if (model.getName().trim().isEmpty())
|
||||
throw new GuacamoleClientException("Connection group names must not be blank.");
|
||||
|
||||
// Check whether such a connection group is already present
|
||||
ConnectionGroupModel existing = connectionGroupMapper.selectOneByName(model.getParentIdentifier(), model.getName());
|
||||
if (existing != null) {
|
||||
|
||||
// If the specified name matches a DIFFERENT existing connection group, the update cannot continue
|
||||
if (!existing.getObjectID().equals(model.getObjectID()))
|
||||
throw new GuacamoleClientException("The connection group \"" + model.getName() + "\" already exists.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of all identifiers for all connection groups within the
|
||||
* connection group having the given identifier. Only connection groups
|
||||
* that the user has read access to will be returned.
|
||||
*
|
||||
* Permission to read the connection group having the given identifier is
|
||||
* NOT checked.
|
||||
*
|
||||
* @param user
|
||||
* The user retrieving the identifiers.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the parent connection group, or null to check the
|
||||
* root connection group.
|
||||
*
|
||||
* @return
|
||||
* The set of all identifiers for all connection groups in the
|
||||
* connection group having the given identifier that the user has read
|
||||
* access to.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while reading identifiers.
|
||||
*/
|
||||
public Set<String> getIdentifiersWithin(AuthenticatedUser user,
|
||||
String identifier)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Bypass permission checks if the user is a system admin
|
||||
if (user.getUser().isAdministrator())
|
||||
return connectionGroupMapper.selectIdentifiersWithin(identifier);
|
||||
|
||||
// Otherwise only return explicitly readable identifiers
|
||||
else
|
||||
return connectionGroupMapper.selectReadableIdentifiersWithin(user.getUser().getModel(), identifier);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the given connection group as the given user, using the
|
||||
* given client information. If the user does not have permission to read
|
||||
* the connection group, permission will be denied.
|
||||
*
|
||||
* @param user
|
||||
* The user connecting to the connection group.
|
||||
*
|
||||
* @param connectionGroup
|
||||
* The connectionGroup being connected to.
|
||||
*
|
||||
* @param info
|
||||
* Information associated with the connecting client.
|
||||
*
|
||||
* @return
|
||||
* A connected GuacamoleSocket associated with a newly-established
|
||||
* connection.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If permission to connect to this connection is denied.
|
||||
*/
|
||||
public GuacamoleSocket connect(AuthenticatedUser user,
|
||||
ModeledConnectionGroup connectionGroup, GuacamoleClientInformation info)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Connect only if READ permission is granted
|
||||
if (hasObjectPermission(user, connectionGroup.getIdentifier(), ObjectPermission.Type.READ))
|
||||
return socketService.getGuacamoleSocket(user, connectionGroup, info);
|
||||
|
||||
// The user does not have permission to connect
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.connectiongroup;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObject;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.GuacamoleSocket;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
|
||||
|
||||
/**
|
||||
* An implementation of the ConnectionGroup object which is backed by a
|
||||
* database model.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class ModeledConnectionGroup extends DirectoryObject<ConnectionGroupModel>
|
||||
implements ConnectionGroup {
|
||||
|
||||
/**
|
||||
* Service for managing connections.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionService connectionService;
|
||||
|
||||
/**
|
||||
* Service for managing connection groups.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupService connectionGroupService;
|
||||
|
||||
/**
|
||||
* Service for creating and tracking sockets.
|
||||
*/
|
||||
@Inject
|
||||
private GuacamoleSocketService socketService;
|
||||
|
||||
/**
|
||||
* Creates a new, empty ModeledConnectionGroup.
|
||||
*/
|
||||
public ModeledConnectionGroup() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return getModel().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
getModel().setName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParentIdentifier() {
|
||||
|
||||
// Translate null parent to proper identifier
|
||||
String parentIdentifier = getModel().getParentIdentifier();
|
||||
if (parentIdentifier == null)
|
||||
return RootConnectionGroup.IDENTIFIER;
|
||||
|
||||
return parentIdentifier;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParentIdentifier(String parentIdentifier) {
|
||||
|
||||
// Translate root identifier back into null
|
||||
if (parentIdentifier != null
|
||||
&& parentIdentifier.equals(RootConnectionGroup.IDENTIFIER))
|
||||
parentIdentifier = null;
|
||||
|
||||
getModel().setParentIdentifier(parentIdentifier);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleSocket connect(GuacamoleClientInformation info)
|
||||
throws GuacamoleException {
|
||||
return connectionGroupService.connect(getCurrentUser(), this, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActiveConnections() {
|
||||
return socketService.getActiveConnections(this).size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(Type type) {
|
||||
getModel().setType(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return getModel().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getConnectionIdentifiers()
|
||||
throws GuacamoleException {
|
||||
return connectionService.getIdentifiersWithin(getCurrentUser(), getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getConnectionGroupIdentifiers()
|
||||
throws GuacamoleException {
|
||||
return connectionGroupService.getIdentifiersWithin(getCurrentUser(), getIdentifier());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.connectiongroup;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionService;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleSecurityException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.RestrictedObject;
|
||||
import org.glyptodon.guacamole.net.GuacamoleSocket;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
|
||||
|
||||
/**
|
||||
* The root connection group, here represented as its own dedicated object as
|
||||
* the database does not contain an actual root group.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class RootConnectionGroup extends RestrictedObject
|
||||
implements ConnectionGroup {
|
||||
|
||||
/**
|
||||
* The identifier used to represent the root connection group. There is no
|
||||
* corresponding entry in the database, thus a reserved identifier that
|
||||
* cannot collide with database-generated identifiers is needed.
|
||||
*/
|
||||
public static final String IDENTIFIER = "ROOT";
|
||||
|
||||
/**
|
||||
* The human-readable name of this connection group. The name of the root
|
||||
* group is not normally visible, and may even be replaced by the web
|
||||
* interface for the sake of translation.
|
||||
*/
|
||||
public static final String NAME = "ROOT";
|
||||
|
||||
/**
|
||||
* Service for managing connection objects.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionService connectionService;
|
||||
|
||||
/**
|
||||
* Service for managing connection group objects.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupService connectionGroupService;
|
||||
|
||||
/**
|
||||
* Creates a new, empty RootConnectionGroup.
|
||||
*/
|
||||
public RootConnectionGroup() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
throw new UnsupportedOperationException("The root connection group cannot be modified.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParentIdentifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParentIdentifier(String parentIdentifier) {
|
||||
throw new UnsupportedOperationException("The root connection group cannot be modified.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return ConnectionGroup.Type.ORGANIZATIONAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(Type type) {
|
||||
throw new UnsupportedOperationException("The root connection group cannot be modified.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getConnectionIdentifiers() throws GuacamoleException {
|
||||
return connectionService.getIdentifiersWithin(getCurrentUser(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getConnectionGroupIdentifiers()
|
||||
throws GuacamoleException {
|
||||
return connectionGroupService.getIdentifiersWithin(getCurrentUser(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return IDENTIFIER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifier(String identifier) {
|
||||
throw new UnsupportedOperationException("The root connection group cannot be modified.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleSocket connect(GuacamoleClientInformation info)
|
||||
throws GuacamoleException {
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActiveConnections() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Glyptodon LLC
|
||||
* 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
|
||||
@@ -21,8 +21,6 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Properties which control the configuration of the MySQL authentication
|
||||
* provider.
|
||||
* Classes related to connection groups.
|
||||
*/
|
||||
package net.sourceforge.guacamole.net.auth.mysql.properties;
|
||||
|
||||
package org.glyptodon.guacamole.auth.jdbc.connectiongroup;
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The base JDBC authentication provider. This authentication provider serves
|
||||
* as a basis for other JDBC authentication provider implementations which are
|
||||
* driven by relatively-common schemas. The only difference between such
|
||||
* implementations are maintained within database-specific MyBatis mappings.
|
||||
*/
|
||||
package org.glyptodon.guacamole.auth.jdbc;
|
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Mapper for connection group permissions.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface ConnectionGroupPermissionMapper extends ObjectPermissionMapper {}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* deleting connection group permissions. This service will automatically
|
||||
* enforce the permissions of the current user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ConnectionGroupPermissionService extends ObjectPermissionService {
|
||||
|
||||
/**
|
||||
* Mapper for connection group permissions.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupPermissionMapper connectionGroupPermissionMapper;
|
||||
|
||||
/**
|
||||
* Provider for connection group permission sets.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<ConnectionGroupPermissionSet> connectionGroupPermissionSetProvider;
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionMapper getPermissionMapper() {
|
||||
return connectionGroupPermissionMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPermissionSet getPermissionSet(AuthenticatedUser user,
|
||||
ModeledUser targetUser) throws GuacamoleException {
|
||||
|
||||
// Create permission set for requested user
|
||||
ObjectPermissionSet permissionSet = connectionGroupPermissionSetProvider.get();
|
||||
permissionSet.init(user, targetUser);
|
||||
|
||||
return permissionSet;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* A database implementation of ObjectPermissionSet which uses an injected
|
||||
* service to query and manipulate the connection group permissions associated
|
||||
* with a particular user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ConnectionGroupPermissionSet extends ObjectPermissionSet {
|
||||
|
||||
/**
|
||||
* Service for querying and manipulating connection group permissions.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupPermissionService connectionGroupPermissionService;
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionService getObjectPermissionService() {
|
||||
return connectionGroupPermissionService;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Mapper for connection permissions.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface ConnectionPermissionMapper extends ObjectPermissionMapper {}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.permission;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* deleting connection permissions. This service will automatically enforce the
|
||||
* permissions of the current user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ConnectionPermissionService extends ObjectPermissionService {
|
||||
|
||||
/**
|
||||
* Mapper for connection permissions.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionPermissionMapper connectionPermissionMapper;
|
||||
|
||||
/**
|
||||
* Provider for connection permission sets.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<ConnectionPermissionSet> connectionPermissionSetProvider;
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionMapper getPermissionMapper() {
|
||||
return connectionPermissionMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPermissionSet getPermissionSet(AuthenticatedUser user,
|
||||
ModeledUser targetUser) throws GuacamoleException {
|
||||
|
||||
// Create permission set for requested user
|
||||
ObjectPermissionSet permissionSet = connectionPermissionSetProvider.get();
|
||||
permissionSet.init(user, targetUser);
|
||||
|
||||
return permissionSet;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* A database implementation of ObjectPermissionSet which uses an injected
|
||||
* service to query and manipulate the connection permissions associated with
|
||||
* a particular user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ConnectionPermissionSet extends ObjectPermissionSet {
|
||||
|
||||
/**
|
||||
* Service for querying and manipulating connection permissions.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionPermissionService connectionPermissionService;
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionService getObjectPermissionService() {
|
||||
return connectionPermissionService;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
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<ObjectPermissionModel> {
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Retrieves the subset of the given identifiers for which the given user
|
||||
* has at least one of the given permissions.
|
||||
*
|
||||
* @param user
|
||||
* The user to check permissions of.
|
||||
*
|
||||
* @param permissions
|
||||
* The permissions to check. An identifier will be included in the
|
||||
* resulting collection if at least one of these permissions is granted
|
||||
* for the associated object
|
||||
*
|
||||
* @param identifiers
|
||||
* The identifiers of the objects affected by the permissions being
|
||||
* checked.
|
||||
*
|
||||
* @return
|
||||
* A collection containing the subset of identifiers for which at least
|
||||
* one of the specified permissions is granted.
|
||||
*/
|
||||
Collection<String> selectAccessibleIdentifiers(@Param("user") UserModel user,
|
||||
@Param("permissions") Collection<ObjectPermission.Type> permissions,
|
||||
@Param("identifiers") Collection<String> identifiers);
|
||||
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.net.auth.permission.ObjectPermission;
|
||||
|
||||
/**
|
||||
* Object representation of an object-related Guacamole permission, as
|
||||
* represented in the database.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ObjectPermissionModel extends PermissionModel<ObjectPermission.Type> {
|
||||
|
||||
/**
|
||||
* The unique identifier of the object affected by this permission.
|
||||
*/
|
||||
private String objectIdentifier;
|
||||
|
||||
/**
|
||||
* Creates a new, empty object permission.
|
||||
*/
|
||||
public ObjectPermissionModel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique identifier of the object affected by this permission.
|
||||
*
|
||||
* @return
|
||||
* The unique identifier of the object affected by this permission.
|
||||
*/
|
||||
public String getObjectIdentifier() {
|
||||
return objectIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the unique identifier of the object affected by this permission.
|
||||
*
|
||||
* @param objectIdentifier
|
||||
* The unique identifier of the object affected by this permission.
|
||||
*/
|
||||
public void setObjectIdentifier(String objectIdentifier) {
|
||||
this.objectIdentifier = objectIdentifier;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.permission;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleSecurityException;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* deleting object permissions. This service will automatically enforce the
|
||||
* permissions of the current user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public abstract class ObjectPermissionService
|
||||
extends PermissionService<ObjectPermissionSet, ObjectPermission, ObjectPermissionModel> {
|
||||
|
||||
@Override
|
||||
protected abstract ObjectPermissionMapper getPermissionMapper();
|
||||
|
||||
@Override
|
||||
protected ObjectPermission getPermissionInstance(ObjectPermissionModel model) {
|
||||
return new ObjectPermission(model.getType(), model.getObjectIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionModel getModelInstance(ModeledUser targetUser,
|
||||
ObjectPermission permission) {
|
||||
|
||||
ObjectPermissionModel model = new ObjectPermissionModel();
|
||||
|
||||
// Populate model object with data from user and permission
|
||||
model.setUserID(targetUser.getModel().getObjectID());
|
||||
model.setUsername(targetUser.getModel().getIdentifier());
|
||||
model.setType(permission.getType());
|
||||
model.setObjectIdentifier(permission.getObjectIdentifier());
|
||||
|
||||
return model;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the current user has permission to update the given
|
||||
* target user, adding or removing the given permissions. Such permission
|
||||
* depends on whether the current user is a system administrator, whether
|
||||
* they have explicit UPDATE permission on the target user, and whether
|
||||
* they have explicit ADMINISTER permission on all affected objects.
|
||||
*
|
||||
* @param user
|
||||
* The user who is changing permissions.
|
||||
*
|
||||
* @param targetUser
|
||||
* The user whose permissions are being changed.
|
||||
*
|
||||
* @param permissions
|
||||
* The permissions that are being added or removed from the target
|
||||
* user.
|
||||
*
|
||||
* @return
|
||||
* true if the user has permission to change the target users
|
||||
* permissions as specified, false otherwise.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while checking permission status, or if
|
||||
* permission is denied to read the current user's permissions.
|
||||
*/
|
||||
protected boolean canAlterPermissions(AuthenticatedUser user, ModeledUser targetUser,
|
||||
Collection<ObjectPermission> permissions)
|
||||
throws GuacamoleException {
|
||||
|
||||
// A system adminstrator can do anything
|
||||
if (user.getUser().isAdministrator())
|
||||
return true;
|
||||
|
||||
// Verify user has update permission on the target user
|
||||
ObjectPermissionSet userPermissionSet = user.getUser().getUserPermissions();
|
||||
if (!userPermissionSet.hasPermission(ObjectPermission.Type.UPDATE, targetUser.getIdentifier()))
|
||||
return false;
|
||||
|
||||
// Produce collection of affected identifiers
|
||||
Collection<String> affectedIdentifiers = new HashSet(permissions.size());
|
||||
for (ObjectPermission permission : permissions)
|
||||
affectedIdentifiers.add(permission.getObjectIdentifier());
|
||||
|
||||
// Determine subset of affected identifiers that we have admin access to
|
||||
ObjectPermissionSet affectedPermissionSet = getPermissionSet(user, user.getUser());
|
||||
Collection<String> allowedSubset = affectedPermissionSet.getAccessibleObjects(
|
||||
Collections.singleton(ObjectPermission.Type.ADMINISTER),
|
||||
affectedIdentifiers
|
||||
);
|
||||
|
||||
// The permissions can be altered if and only if the set of objects we
|
||||
// are allowed to administer is equal to the set of objects we will be
|
||||
// affecting.
|
||||
|
||||
return affectedIdentifiers.size() == allowedSubset.size();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createPermissions(AuthenticatedUser user, ModeledUser targetUser,
|
||||
Collection<ObjectPermission> permissions)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Create permissions only if user has permission to do so
|
||||
if (canAlterPermissions(user, targetUser, permissions)) {
|
||||
Collection<ObjectPermissionModel> models = getModelInstances(targetUser, permissions);
|
||||
getPermissionMapper().insert(models);
|
||||
return;
|
||||
}
|
||||
|
||||
// User lacks permission to create object permissions
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePermissions(AuthenticatedUser user, ModeledUser targetUser,
|
||||
Collection<ObjectPermission> permissions)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Delete permissions only if user has permission to do so
|
||||
if (canAlterPermissions(user, targetUser, permissions)) {
|
||||
Collection<ObjectPermissionModel> models = getModelInstances(targetUser, permissions);
|
||||
getPermissionMapper().delete(models);
|
||||
return;
|
||||
}
|
||||
|
||||
// User lacks permission to delete object permissions
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the subset of the given identifiers for which the given user
|
||||
* has at least one of the given permissions.
|
||||
*
|
||||
* @param user
|
||||
* The user checking the permissions.
|
||||
*
|
||||
* @param targetUser
|
||||
* The user to check permissions of.
|
||||
*
|
||||
* @param permissions
|
||||
* The permissions to check. An identifier will be included in the
|
||||
* resulting collection if at least one of these permissions is granted
|
||||
* for the associated object
|
||||
*
|
||||
* @param identifiers
|
||||
* The identifiers of the objects affected by the permissions being
|
||||
* checked.
|
||||
*
|
||||
* @return
|
||||
* A collection containing the subset of identifiers for which at least
|
||||
* one of the specified permissions is granted.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving permissions.
|
||||
*/
|
||||
public Collection<String> retrieveAccessibleIdentifiers(AuthenticatedUser user,
|
||||
ModeledUser targetUser, Collection<ObjectPermission.Type> permissions,
|
||||
Collection<String> identifiers) throws GuacamoleException {
|
||||
|
||||
// Nothing is always accessible
|
||||
if (identifiers.isEmpty())
|
||||
return identifiers;
|
||||
|
||||
// Determine whether the user is an admin
|
||||
boolean isAdmin = user.getUser().isAdministrator();
|
||||
|
||||
// Only an admin can read permissions that aren't his own
|
||||
if (isAdmin || user.getUser().getIdentifier().equals(targetUser.getIdentifier())) {
|
||||
|
||||
// If user is an admin, everything is accessible
|
||||
if (isAdmin)
|
||||
return identifiers;
|
||||
|
||||
// Otherwise, return explicitly-retrievable identifiers
|
||||
return getPermissionMapper().selectAccessibleIdentifiers(targetUser.getModel(), permissions, identifiers);
|
||||
|
||||
}
|
||||
|
||||
// User cannot read this user's permissions
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.auth.jdbc.base.RestrictedObject;
|
||||
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 extends RestrictedObject
|
||||
implements org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet {
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
super.init(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<ObjectPermission> getPermissions() throws GuacamoleException {
|
||||
return getObjectPermissionService().retrievePermissions(getCurrentUser(), user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(ObjectPermission.Type permission,
|
||||
String identifier) throws GuacamoleException {
|
||||
return getObjectPermissionService().retrievePermission(getCurrentUser(), 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<String> getAccessibleObjects(Collection<ObjectPermission.Type> permissions,
|
||||
Collection<String> identifiers) throws GuacamoleException {
|
||||
return getObjectPermissionService().retrieveAccessibleIdentifiers(getCurrentUser(), user, permissions, identifiers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPermissions(Set<ObjectPermission> permissions)
|
||||
throws GuacamoleException {
|
||||
getObjectPermissionService().createPermissions(getCurrentUser(), user, permissions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePermissions(Set<ObjectPermission> permissions)
|
||||
throws GuacamoleException {
|
||||
getObjectPermissionService().deletePermissions(getCurrentUser(), user, permissions);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* Generic base for mappers which handle permissions.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
* @param <PermissionType>
|
||||
* The type of permission model object handled by this mapper.
|
||||
*/
|
||||
public interface PermissionMapper<PermissionType> {
|
||||
|
||||
/**
|
||||
* Retrieves all permissions associated with the given user.
|
||||
*
|
||||
* @param user
|
||||
* The user to retrieve permissions for.
|
||||
*
|
||||
* @return
|
||||
* All permissions associated with the given user.
|
||||
*/
|
||||
Collection<PermissionType> select(@Param("user") UserModel user);
|
||||
|
||||
/**
|
||||
* Inserts the given permissions into the database. If any permissions
|
||||
* already exist, they will be ignored.
|
||||
*
|
||||
* @param permissions
|
||||
* The permissions to insert.
|
||||
*
|
||||
* @return
|
||||
* The number of rows inserted.
|
||||
*/
|
||||
int insert(@Param("permissions") Collection<PermissionType> permissions);
|
||||
|
||||
/**
|
||||
* Deletes the given permissions from the database. If any permissions do
|
||||
* not exist, they will be ignored.
|
||||
*
|
||||
* @param permissions
|
||||
* The permissions to delete.
|
||||
*
|
||||
* @return
|
||||
* The number of rows deleted.
|
||||
*/
|
||||
int delete(@Param("permissions") Collection<PermissionType> permissions);
|
||||
|
||||
}
|
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Generic base permission model which grants a permission of a particular type
|
||||
* to a specific user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
* @param <PermissionType>
|
||||
* The type of permissions allowed within this model.
|
||||
*/
|
||||
public abstract class PermissionModel<PermissionType> {
|
||||
|
||||
/**
|
||||
* The database ID of the user to whom this permission is granted.
|
||||
*/
|
||||
private Integer userID;
|
||||
|
||||
/**
|
||||
* The username of the user to whom this permission is granted.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* The type of action granted by this permission.
|
||||
*/
|
||||
private PermissionType type;
|
||||
|
||||
/**
|
||||
* Returns the database ID of the user to whom this permission is granted.
|
||||
*
|
||||
* @return
|
||||
* The database ID of the user to whom this permission is granted.
|
||||
*/
|
||||
public Integer getUserID() {
|
||||
return userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database ID of the user to whom this permission is granted.
|
||||
*
|
||||
* @param userID
|
||||
* The database ID of the user to whom this permission is granted.
|
||||
*/
|
||||
public void setUserID(Integer userID) {
|
||||
this.userID = userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the username of the user to whom this permission is granted.
|
||||
*
|
||||
* @return
|
||||
* The username of the user to whom this permission is granted.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the username of the user to whom this permission is granted.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user to whom this permission is granted.
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of action granted by this permission.
|
||||
*
|
||||
* @return
|
||||
* The type of action granted by this permission.
|
||||
*/
|
||||
public PermissionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of action granted by this permission.
|
||||
*
|
||||
* @param type
|
||||
* The type of action granted by this permission.
|
||||
*/
|
||||
public void setType(PermissionType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.permission;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleSecurityException;
|
||||
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.PermissionSet;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* deleting permissions, and for obtaining the permission sets that contain
|
||||
* these permissions. This service will automatically enforce the permissions
|
||||
* of the current user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
* @param <PermissionSetType>
|
||||
* The type of permission sets this service provides access to.
|
||||
*
|
||||
* @param <PermissionType>
|
||||
* The type of permission this service provides access to.
|
||||
*
|
||||
* @param <ModelType>
|
||||
* The underlying model object used to represent PermissionType in the
|
||||
* database.
|
||||
*/
|
||||
public abstract class PermissionService<PermissionSetType extends PermissionSet<PermissionType>,
|
||||
PermissionType extends Permission, ModelType> {
|
||||
|
||||
/**
|
||||
* Returns an instance of a mapper for the type of permission used by this
|
||||
* service.
|
||||
*
|
||||
* @return
|
||||
* A mapper which provides access to the model objects associated with
|
||||
* the permissions used by this service.
|
||||
*/
|
||||
protected abstract PermissionMapper<ModelType> getPermissionMapper();
|
||||
|
||||
/**
|
||||
* Returns an instance of a permission which is based on the given model
|
||||
* object.
|
||||
*
|
||||
* @param model
|
||||
* The model object to use to produce the returned permission.
|
||||
*
|
||||
* @return
|
||||
* A permission which is based on the given model object.
|
||||
*/
|
||||
protected abstract PermissionType getPermissionInstance(ModelType model);
|
||||
|
||||
/**
|
||||
* Returns a collection of permissions which are based on the models in
|
||||
* the given collection.
|
||||
*
|
||||
* @param models
|
||||
* The model objects to use to produce the permissions within the
|
||||
* returned set.
|
||||
*
|
||||
* @return
|
||||
* A set of permissions which are based on the models in the given
|
||||
* collection.
|
||||
*/
|
||||
protected Set<PermissionType> getPermissionInstances(Collection<ModelType> models) {
|
||||
|
||||
// Create new collection of permissions by manually converting each model
|
||||
Set<PermissionType> permissions = new HashSet<PermissionType>(models.size());
|
||||
for (ModelType model : models)
|
||||
permissions.add(getPermissionInstance(model));
|
||||
|
||||
return permissions;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of a model object which is based on the given
|
||||
* permission and target user.
|
||||
*
|
||||
* @param targetUser
|
||||
* The user to whom this permission is granted.
|
||||
*
|
||||
* @param permission
|
||||
* The permission to use to produce the returned model object.
|
||||
*
|
||||
* @return
|
||||
* A model object which is based on the given permission and target
|
||||
* user.
|
||||
*/
|
||||
protected abstract ModelType getModelInstance(ModeledUser targetUser,
|
||||
PermissionType permission);
|
||||
|
||||
/**
|
||||
* Returns a collection of model objects which are based on the given
|
||||
* permissions and target user.
|
||||
*
|
||||
* @param targetUser
|
||||
* The user to whom this permission is granted.
|
||||
*
|
||||
* @param permissions
|
||||
* The permissions to use to produce the returned model objects.
|
||||
*
|
||||
* @return
|
||||
* A collection of model objects which are based on the given
|
||||
* permissions and target user.
|
||||
*/
|
||||
protected Collection<ModelType> getModelInstances(ModeledUser targetUser,
|
||||
Collection<PermissionType> permissions) {
|
||||
|
||||
// Create new collection of models by manually converting each permission
|
||||
Collection<ModelType> models = new ArrayList<ModelType>(permissions.size());
|
||||
for (PermissionType permission : permissions)
|
||||
models.add(getModelInstance(targetUser, permission));
|
||||
|
||||
return models;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a permission set that can be used to retrieve and manipulate the
|
||||
* permissions of the given user.
|
||||
*
|
||||
* @param user
|
||||
* The user who will be retrieving or manipulating permissions through
|
||||
* the returned permission set.
|
||||
*
|
||||
* @param targetUser
|
||||
* The user to whom the permissions in the returned permission set are
|
||||
* granted.
|
||||
*
|
||||
* @return
|
||||
* A permission set that contains all permissions associated with the
|
||||
* given user, and can be used to manipulate that user's permissions.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the permissions of the given
|
||||
* user, or if permission to retrieve the permissions of the given
|
||||
* user is denied.
|
||||
*/
|
||||
public abstract PermissionSetType getPermissionSet(AuthenticatedUser user,
|
||||
ModeledUser targetUser) throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* Retrieves all permissions associated with the given user.
|
||||
*
|
||||
* @param user
|
||||
* The user retrieving the permissions.
|
||||
*
|
||||
* @param targetUser
|
||||
* The user associated with the permissions to be retrieved.
|
||||
*
|
||||
* @return
|
||||
* The permissions associated with the given user.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the requested permissions.
|
||||
*/
|
||||
public Set<PermissionType> retrievePermissions(AuthenticatedUser user,
|
||||
ModeledUser targetUser) throws GuacamoleException {
|
||||
|
||||
// Only an admin can read permissions that aren't his own
|
||||
if (user.getUser().getIdentifier().equals(targetUser.getIdentifier())
|
||||
|| user.getUser().isAdministrator())
|
||||
return getPermissionInstances(getPermissionMapper().select(targetUser.getModel()));
|
||||
|
||||
// User cannot read this user's permissions
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the given permissions within the database. If any permissions
|
||||
* already exist, they will be ignored.
|
||||
*
|
||||
* @param user
|
||||
* The user creating the permissions.
|
||||
*
|
||||
* @param targetUser
|
||||
* The user associated with the permissions to be created.
|
||||
*
|
||||
* @param permissions
|
||||
* The permissions to create.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the user lacks permission to create the permissions, or an error
|
||||
* occurs while creating the permissions.
|
||||
*/
|
||||
public abstract void createPermissions(AuthenticatedUser user,
|
||||
ModeledUser targetUser,
|
||||
Collection<PermissionType> permissions) throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* Deletes the given permissions. If any permissions do not exist, they
|
||||
* will be ignored.
|
||||
*
|
||||
* @param user
|
||||
* The user deleting the permissions.
|
||||
*
|
||||
* @param targetUser
|
||||
* The user associated with the permissions to be deleted.
|
||||
*
|
||||
* @param permissions
|
||||
* The permissions to delete.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the user lacks permission to delete the permissions, or an error
|
||||
* occurs while deleting the permissions.
|
||||
*/
|
||||
public abstract void deletePermissions(AuthenticatedUser user,
|
||||
ModeledUser targetUser,
|
||||
Collection<PermissionType> permissions) throws GuacamoleException;
|
||||
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.UserModel;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
|
||||
/**
|
||||
* Mapper for system-level permissions.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface SystemPermissionMapper extends PermissionMapper<SystemPermissionModel> {
|
||||
|
||||
/**
|
||||
* Retrieve the permission of the given type associated with the given
|
||||
* user, 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.
|
||||
*
|
||||
* @return
|
||||
* The requested permission, or null if no such permission is granted
|
||||
* to the given user.
|
||||
*/
|
||||
SystemPermissionModel selectOne(@Param("user") UserModel user,
|
||||
@Param("type") SystemPermission.Type type);
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.net.auth.permission.SystemPermission;
|
||||
|
||||
/**
|
||||
* Object representation of an system-level Guacamole permission, as
|
||||
* represented in the database.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class SystemPermissionModel extends PermissionModel<SystemPermission.Type> {
|
||||
|
||||
/**
|
||||
* Creates a new, empty System permission.
|
||||
*/
|
||||
public SystemPermissionModel() {
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.permission;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import java.util.Collection;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleSecurityException;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* deleting system permissions. This service will automatically enforce
|
||||
* the permissions of the current user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class SystemPermissionService
|
||||
extends PermissionService<SystemPermissionSet, SystemPermission, SystemPermissionModel> {
|
||||
|
||||
/**
|
||||
* Mapper for system-level permissions.
|
||||
*/
|
||||
@Inject
|
||||
private SystemPermissionMapper systemPermissionMapper;
|
||||
|
||||
/**
|
||||
* Provider for creating system permission sets.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<SystemPermissionSet> systemPermissionSetProvider;
|
||||
|
||||
@Override
|
||||
protected SystemPermissionMapper getPermissionMapper() {
|
||||
return systemPermissionMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SystemPermission getPermissionInstance(SystemPermissionModel model) {
|
||||
return new SystemPermission(model.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SystemPermissionModel getModelInstance(final ModeledUser targetUser,
|
||||
final SystemPermission permission) {
|
||||
|
||||
SystemPermissionModel model = new SystemPermissionModel();
|
||||
|
||||
// Populate model object with data from user and permission
|
||||
model.setUserID(targetUser.getModel().getObjectID());
|
||||
model.setUsername(targetUser.getModel().getIdentifier());
|
||||
model.setType(permission.getType());
|
||||
|
||||
return model;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SystemPermissionSet getPermissionSet(AuthenticatedUser user,
|
||||
ModeledUser targetUser) throws GuacamoleException {
|
||||
|
||||
// Create permission set for requested user
|
||||
SystemPermissionSet permissionSet = systemPermissionSetProvider.get();
|
||||
permissionSet.init(user, targetUser);
|
||||
|
||||
return permissionSet;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createPermissions(AuthenticatedUser user, ModeledUser targetUser,
|
||||
Collection<SystemPermission> permissions) throws GuacamoleException {
|
||||
|
||||
// Only an admin can create system permissions
|
||||
if (user.getUser().isAdministrator()) {
|
||||
Collection<SystemPermissionModel> models = getModelInstances(targetUser, permissions);
|
||||
systemPermissionMapper.insert(models);
|
||||
return;
|
||||
}
|
||||
|
||||
// User lacks permission to create system permissions
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePermissions(AuthenticatedUser user, ModeledUser targetUser,
|
||||
Collection<SystemPermission> permissions) throws GuacamoleException {
|
||||
|
||||
// Only an admin can delete system permissions
|
||||
if (user.getUser().isAdministrator()) {
|
||||
Collection<SystemPermissionModel> models = getModelInstances(targetUser, permissions);
|
||||
systemPermissionMapper.delete(models);
|
||||
return;
|
||||
}
|
||||
|
||||
// User lacks permission to delete system permissions
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the permission of the given type associated with the given
|
||||
* user, if it exists. If no such permission exists, null is returned.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return
|
||||
* The permission of the given type associated with the given user, or
|
||||
* null if no such permission exists.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the requested permission.
|
||||
*/
|
||||
public SystemPermission retrievePermission(AuthenticatedUser user,
|
||||
ModeledUser targetUser, SystemPermission.Type type) 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
|
||||
SystemPermissionModel model = getPermissionMapper().selectOne(targetUser.getModel(), type);
|
||||
if (model == null)
|
||||
return null;
|
||||
|
||||
return getPermissionInstance(model);
|
||||
|
||||
}
|
||||
|
||||
// User cannot read this user's permissions
|
||||
throw new GuacamoleSecurityException("Permission denied.");
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 com.google.inject.Inject;
|
||||
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.auth.jdbc.base.RestrictedObject;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
|
||||
/**
|
||||
* A database implementation of SystemPermissionSet which uses an injected
|
||||
* service to query and manipulate the system permissions associated with a
|
||||
* particular user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class SystemPermissionSet extends RestrictedObject
|
||||
implements org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet {
|
||||
|
||||
/**
|
||||
* The user associated with this permission set. Each of the permissions in
|
||||
* this permission set is granted to this user.
|
||||
*/
|
||||
private ModeledUser user;
|
||||
|
||||
/**
|
||||
* Service for reading and manipulating system permissions.
|
||||
*/
|
||||
@Inject
|
||||
private SystemPermissionService systemPermissionService;
|
||||
|
||||
/**
|
||||
* Creates a new SystemPermissionSet. 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 SystemPermissionSet() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
super.init(currentUser);
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SystemPermission> getPermissions() throws GuacamoleException {
|
||||
return systemPermissionService.retrievePermissions(getCurrentUser(), user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(SystemPermission.Type permission)
|
||||
throws GuacamoleException {
|
||||
return systemPermissionService.retrievePermission(getCurrentUser(), user, permission) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPermission(SystemPermission.Type permission)
|
||||
throws GuacamoleException {
|
||||
addPermissions(Collections.singleton(new SystemPermission(permission)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePermission(SystemPermission.Type permission)
|
||||
throws GuacamoleException {
|
||||
removePermissions(Collections.singleton(new SystemPermission(permission)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPermissions(Set<SystemPermission> permissions)
|
||||
throws GuacamoleException {
|
||||
systemPermissionService.createPermissions(getCurrentUser(), user, permissions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePermissions(Set<SystemPermission> permissions)
|
||||
throws GuacamoleException {
|
||||
systemPermissionService.deletePermissions(getCurrentUser(), user, permissions);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Mapper for user permissions.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface UserPermissionMapper extends ObjectPermissionMapper {}
|
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.permission;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.ModeledUser;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* deleting user permissions. This service will automatically enforce the
|
||||
* permissions of the current user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class UserPermissionService extends ObjectPermissionService {
|
||||
|
||||
/**
|
||||
* Mapper for user permissions.
|
||||
*/
|
||||
@Inject
|
||||
private UserPermissionMapper userPermissionMapper;
|
||||
|
||||
/**
|
||||
* Provider for user permission sets.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<UserPermissionSet> userPermissionSetProvider;
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionMapper getPermissionMapper() {
|
||||
return userPermissionMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPermissionSet getPermissionSet(AuthenticatedUser user,
|
||||
ModeledUser targetUser) throws GuacamoleException {
|
||||
|
||||
// Create permission set for requested user
|
||||
ObjectPermissionSet permissionSet = userPermissionSetProvider.get();
|
||||
permissionSet.init(user, targetUser);
|
||||
|
||||
return permissionSet;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* A database implementation of ObjectPermissionSet which uses an injected
|
||||
* service to query and manipulate the user permissions associated with a
|
||||
* particular user.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class UserPermissionSet extends ObjectPermissionSet {
|
||||
|
||||
/**
|
||||
* Service for querying and manipulating user permissions.
|
||||
*/
|
||||
@Inject
|
||||
private UserPermissionService userPermissionService;
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionService getObjectPermissionService() {
|
||||
return userPermissionService;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes related to object- and system-level permissions.
|
||||
*/
|
||||
package org.glyptodon.guacamole.auth.jdbc.permission;
|
@@ -20,8 +20,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||
|
||||
package org.glyptodon.guacamole.auth.jdbc.security;
|
||||
|
||||
/**
|
||||
* A service to perform password encryption and checking.
|
||||
@@ -29,20 +28,6 @@ package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||
*/
|
||||
public interface PasswordEncryptionService {
|
||||
|
||||
/**
|
||||
* Checks whether the provided, unhashed password matches the given
|
||||
* hash/salt pair.
|
||||
*
|
||||
* @param password The unhashed password to validate.
|
||||
* @param hashedPassword The hashed password to compare the given password
|
||||
* against.
|
||||
* @param salt The salt used when the hashed password given was created.
|
||||
* @return true if the provided credentials match the values given, false
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean checkPassword(String password, byte[] hashedPassword,
|
||||
byte[] salt);
|
||||
|
||||
/**
|
||||
* Creates a password hash based on the provided username, password, and
|
||||
* salt.
|
||||
@@ -52,4 +37,5 @@ public interface PasswordEncryptionService {
|
||||
* @return The generated password hash.
|
||||
*/
|
||||
public byte[] createPasswordHash(String password, byte[] salt);
|
||||
|
||||
}
|
@@ -20,12 +20,11 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||
package org.glyptodon.guacamole.auth.jdbc.security;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
/**
|
||||
@@ -34,16 +33,6 @@ import javax.xml.bind.DatatypeConverter;
|
||||
*/
|
||||
public class SHA256PasswordEncryptionService implements PasswordEncryptionService {
|
||||
|
||||
@Override
|
||||
public boolean checkPassword(String password, byte[] hashedPassword,
|
||||
byte[] salt) {
|
||||
|
||||
// Compare bytes of password in credentials against hashed password
|
||||
byte[] passwordBytes = createPasswordHash(password, salt);
|
||||
return Arrays.equals(passwordBytes, hashedPassword);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] createPasswordHash(String password, byte[] salt) {
|
||||
|
||||
@@ -72,4 +61,5 @@ public class SHA256PasswordEncryptionService implements PasswordEncryptionServic
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -20,7 +20,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||
package org.glyptodon.guacamole.auth.jdbc.security;
|
||||
|
||||
/**
|
||||
* A service to generate password salts.
|
@@ -20,7 +20,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.sourceforge.guacamole.net.auth.mysql.service;
|
||||
package org.glyptodon.guacamole.auth.jdbc.security;
|
||||
|
||||
|
||||
import java.security.SecureRandom;
|
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes related to hashing or encryption.
|
||||
*/
|
||||
package org.glyptodon.guacamole.auth.jdbc.security;
|
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* 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.socket;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionRecordMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ParameterMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionModel;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionRecordModel;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ParameterModel;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.environment.Environment;
|
||||
import org.glyptodon.guacamole.net.GuacamoleSocket;
|
||||
import org.glyptodon.guacamole.net.InetGuacamoleSocket;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
|
||||
import org.glyptodon.guacamole.protocol.ConfiguredGuacamoleSocket;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
|
||||
import org.glyptodon.guacamole.token.StandardTokens;
|
||||
import org.glyptodon.guacamole.token.TokenFilter;
|
||||
|
||||
|
||||
/**
|
||||
* Base implementation of the GuacamoleSocketService, handling retrieval of
|
||||
* connection parameters, load balancing, and connection usage counts. The
|
||||
* implementation of concurrency rules is up to policy-specific subclasses.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public abstract class AbstractGuacamoleSocketService implements GuacamoleSocketService {
|
||||
|
||||
/**
|
||||
* The environment of the Guacamole server.
|
||||
*/
|
||||
@Inject
|
||||
private Environment environment;
|
||||
|
||||
/**
|
||||
* Mapper for accessing connection parameters.
|
||||
*/
|
||||
@Inject
|
||||
private ParameterMapper parameterMapper;
|
||||
|
||||
/**
|
||||
* Mapper for accessing connection history.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionRecordMapper connectionRecordMapper;
|
||||
|
||||
/**
|
||||
* The current number of concurrent uses of the connection having a given
|
||||
* identifier.
|
||||
*/
|
||||
private final Map<String, LinkedList<ConnectionRecord>> activeConnections =
|
||||
new HashMap<String, LinkedList<ConnectionRecord>>();
|
||||
|
||||
/**
|
||||
* Atomically increments the current usage count for the given connection.
|
||||
*
|
||||
* @param connection
|
||||
* The connection which is being used.
|
||||
*/
|
||||
private void addActiveConnection(Connection connection, ConnectionRecord record) {
|
||||
synchronized (activeConnections) {
|
||||
|
||||
String identifier = connection.getIdentifier();
|
||||
|
||||
// Get set of active connection records, creating if necessary
|
||||
LinkedList<ConnectionRecord> connections = activeConnections.get(identifier);
|
||||
if (connections == null) {
|
||||
connections = new LinkedList<ConnectionRecord>();
|
||||
activeConnections.put(identifier, connections);
|
||||
}
|
||||
|
||||
// Add active connection
|
||||
connections.addFirst(record);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically decrements the current usage count for the given connection.
|
||||
* If a combination of incrementUsage() and decrementUsage() calls result
|
||||
* in the usage counter being reduced to zero, it is guaranteed that one
|
||||
* of those decrementUsage() calls will remove the value from the map.
|
||||
*
|
||||
* @param connection
|
||||
* The connection which is no longer being used.
|
||||
*/
|
||||
private void removeActiveConnection(Connection connection, ConnectionRecord record) {
|
||||
synchronized (activeConnections) {
|
||||
|
||||
String identifier = connection.getIdentifier();
|
||||
|
||||
// Get set of active connection records
|
||||
LinkedList<ConnectionRecord> connections = activeConnections.get(identifier);
|
||||
assert(connections != null);
|
||||
|
||||
// Remove old record
|
||||
connections.remove(record);
|
||||
|
||||
// If now empty, clean the tracking entry
|
||||
if (connections.isEmpty())
|
||||
activeConnections.remove(identifier);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires possibly-exclusive access to the given connection on behalf of
|
||||
* the given user. If access is denied for any reason, an exception is
|
||||
* thrown.
|
||||
*
|
||||
* @param user
|
||||
* The user acquiring access.
|
||||
*
|
||||
* @param connection
|
||||
* The connection being accessed.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If access is denied to the given user for any reason.
|
||||
*/
|
||||
protected abstract void acquire(AuthenticatedUser user,
|
||||
ModeledConnection connection) throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* Releases possibly-exclusive access to the given connection on behalf of
|
||||
* the given user. If the given user did not already have access, the
|
||||
* behavior of this function is undefined.
|
||||
*
|
||||
* @param user
|
||||
* The user releasing access.
|
||||
*
|
||||
* @param connection
|
||||
* The connection being released.
|
||||
*/
|
||||
protected abstract void release(AuthenticatedUser user,
|
||||
ModeledConnection connection);
|
||||
|
||||
@Override
|
||||
public GuacamoleSocket getGuacamoleSocket(final AuthenticatedUser user,
|
||||
final ModeledConnection connection, GuacamoleClientInformation info)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Create record for active connection
|
||||
final ActiveConnectionRecord activeConnection = new ActiveConnectionRecord(user);
|
||||
|
||||
// Generate configuration from available data
|
||||
GuacamoleConfiguration config = new GuacamoleConfiguration();
|
||||
|
||||
// Set protocol from connection
|
||||
ConnectionModel model = connection.getModel();
|
||||
config.setProtocol(model.getProtocol());
|
||||
|
||||
// Set parameters from associated data
|
||||
Collection<ParameterModel> parameters = parameterMapper.select(connection.getIdentifier());
|
||||
for (ParameterModel parameter : parameters)
|
||||
config.setParameter(parameter.getName(), parameter.getValue());
|
||||
|
||||
// Build token filter containing credential tokens
|
||||
TokenFilter tokenFilter = new TokenFilter();
|
||||
StandardTokens.addStandardTokens(tokenFilter, user.getCredentials());
|
||||
|
||||
// Filter the configuration
|
||||
tokenFilter.filterValues(config.getParameters());
|
||||
|
||||
// Return new socket
|
||||
try {
|
||||
|
||||
// Atomically gain access to connection
|
||||
acquire(user, connection);
|
||||
addActiveConnection(connection, activeConnection);
|
||||
|
||||
// Return newly-reserved connection
|
||||
return new ConfiguredGuacamoleSocket(
|
||||
new InetGuacamoleSocket(
|
||||
environment.getRequiredProperty(Environment.GUACD_HOSTNAME),
|
||||
environment.getRequiredProperty(Environment.GUACD_PORT)
|
||||
),
|
||||
config
|
||||
) {
|
||||
|
||||
@Override
|
||||
public void close() throws GuacamoleException {
|
||||
|
||||
// Attempt to close connection
|
||||
super.close();
|
||||
|
||||
// Release connection upon close
|
||||
removeActiveConnection(connection, activeConnection);
|
||||
release(user, connection);
|
||||
|
||||
UserModel userModel = user.getUser().getModel();
|
||||
ConnectionRecordModel recordModel = new ConnectionRecordModel();
|
||||
|
||||
// Copy user information and timestamps into new record
|
||||
recordModel.setUserID(userModel.getObjectID());
|
||||
recordModel.setUsername(userModel.getIdentifier());
|
||||
recordModel.setConnectionIdentifier(connection.getIdentifier());
|
||||
recordModel.setStartDate(activeConnection.getStartDate());
|
||||
recordModel.setEndDate(new Date());
|
||||
|
||||
// Insert connection record
|
||||
connectionRecordMapper.insert(recordModel);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Release connection in case of error
|
||||
catch (GuacamoleException e) {
|
||||
|
||||
// Atomically release access to connection
|
||||
removeActiveConnection(connection, activeConnection);
|
||||
release(user, connection);
|
||||
|
||||
throw e;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConnectionRecord> getActiveConnections(Connection connection) {
|
||||
synchronized (activeConnections) {
|
||||
|
||||
String identifier = connection.getIdentifier();
|
||||
|
||||
// Get set of active connection records
|
||||
LinkedList<ConnectionRecord> connections = activeConnections.get(identifier);
|
||||
if (connections != null)
|
||||
return Collections.unmodifiableList(connections);
|
||||
|
||||
return Collections.EMPTY_LIST;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuacamoleSocket getGuacamoleSocket(AuthenticatedUser user,
|
||||
ModeledConnectionGroup connectionGroup,
|
||||
GuacamoleClientInformation info) throws GuacamoleException {
|
||||
// STUB
|
||||
throw new UnsupportedOperationException("STUB");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConnectionRecord> getActiveConnections(ConnectionGroup connectionGroup) {
|
||||
// STUB
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.socket;
|
||||
|
||||
import java.util.Date;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
|
||||
|
||||
|
||||
/**
|
||||
* A connection record implementation that describes an active connection. As
|
||||
* the associated connection has not yet ended, getEndDate() will always return
|
||||
* null, and isActive() will always return true. The associated start date will
|
||||
* be the time of this objects creation.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ActiveConnectionRecord implements ConnectionRecord {
|
||||
|
||||
/**
|
||||
* The user that connected to the connection associated with this connection
|
||||
* record.
|
||||
*/
|
||||
private final AuthenticatedUser user;
|
||||
|
||||
/**
|
||||
* The time this connection record was created.
|
||||
*/
|
||||
private final Date startDate = new Date();
|
||||
|
||||
/**
|
||||
* Creates a new connection record associated with the given user. The
|
||||
* start date of this connection record will be the time of its creation.
|
||||
*
|
||||
* @param user
|
||||
* The user that connected to the connection associated with this
|
||||
* connection record.
|
||||
*/
|
||||
public ActiveConnectionRecord(AuthenticatedUser user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getEndDate() {
|
||||
|
||||
// Active connections have not yet ended
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return user.getUser().getIdentifier();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
|
||||
// Active connections are active by definition
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.socket;
|
||||
|
||||
import java.util.List;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.GuacamoleSocket;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleClientInformation;
|
||||
|
||||
|
||||
/**
|
||||
* Service which creates pre-configured GuacamoleSocket instances for
|
||||
* connections and balancing groups, applying concurrent usage rules.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface GuacamoleSocketService {
|
||||
|
||||
/**
|
||||
* Creates a socket for the given user which connects to the given
|
||||
* connection. The given client information will be passed to guacd when
|
||||
* the connection is established. This function will apply any concurrent
|
||||
* usage rules in effect, but will NOT test object- or system-level
|
||||
* permissions.
|
||||
*
|
||||
* @param user
|
||||
* The user for whom the connection is being established.
|
||||
*
|
||||
* @param connection
|
||||
* The connection the user is connecting to.
|
||||
*
|
||||
* @param info
|
||||
* Information describing the Guacamole client connecting to the given
|
||||
* connection.
|
||||
*
|
||||
* @return
|
||||
* A new GuacamoleSocket which is configured and connected to the given
|
||||
* connection.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the connection cannot be established due to concurrent usage
|
||||
* rules.
|
||||
*/
|
||||
GuacamoleSocket getGuacamoleSocket(AuthenticatedUser user,
|
||||
ModeledConnection connection, GuacamoleClientInformation info)
|
||||
throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* Returns a list containing connection records representing all currently-
|
||||
* active connections using the given connection. These records will have
|
||||
* usernames and start dates, but no end date.
|
||||
*
|
||||
* @param connection
|
||||
* The connection to check.
|
||||
*
|
||||
* @return
|
||||
* A list containing connection records representing all currently-
|
||||
* active connections.
|
||||
*/
|
||||
public List<ConnectionRecord> getActiveConnections(Connection connection);
|
||||
|
||||
/**
|
||||
* Creates a socket for the given user which connects to the given
|
||||
* connection group. The given client information will be passed to guacd
|
||||
* when the connection is established. This function will apply any
|
||||
* concurrent usage rules in effect, but will NOT test object- or
|
||||
* system-level permissions.
|
||||
*
|
||||
* @param user
|
||||
* The user for whom the connection is being established.
|
||||
*
|
||||
* @param connectionGroup
|
||||
* The connection group the user is connecting to.
|
||||
*
|
||||
* @param info
|
||||
* Information describing the Guacamole client connecting to the given
|
||||
* connection group.
|
||||
*
|
||||
* @return
|
||||
* A new GuacamoleSocket which is configured and connected to the given
|
||||
* connection group.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If the connection cannot be established due to concurrent usage
|
||||
* rules, or if the connection group is not balancing.
|
||||
*/
|
||||
GuacamoleSocket getGuacamoleSocket(AuthenticatedUser user,
|
||||
ModeledConnectionGroup connectionGroup,
|
||||
GuacamoleClientInformation info)
|
||||
throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* Returns a list containing connection records representing all currently-
|
||||
* active connections using the given connection group. These records will
|
||||
* have usernames and start dates, but no end date.
|
||||
*
|
||||
* @param connectionGroup
|
||||
* The connection group to check.
|
||||
*
|
||||
* @return
|
||||
* A list containing connection records representing all currently-
|
||||
* active connections.
|
||||
*/
|
||||
public List<ConnectionRecord> getActiveConnections(ConnectionGroup connectionGroup);
|
||||
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.socket;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.AuthenticatedUser;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ModeledConnection;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
|
||||
|
||||
/**
|
||||
* GuacamoleSocketService implementation which imposes no restrictions
|
||||
* whatsoever on the number of concurrent or duplicate connections.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
@Singleton
|
||||
public class UnrestrictedGuacamoleSocketService
|
||||
extends AbstractGuacamoleSocketService {
|
||||
|
||||
@Override
|
||||
protected void acquire(AuthenticatedUser user, ModeledConnection connection)
|
||||
throws GuacamoleException {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void release(AuthenticatedUser user, ModeledConnection connection) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes related to obtaining/configuring Guacamole sockets, and restricting
|
||||
* access to those sockets.
|
||||
*/
|
||||
package org.glyptodon.guacamole.auth.jdbc.socket;
|
@@ -20,22 +20,21 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.sourceforge.guacamole.net.auth.mysql;
|
||||
package org.glyptodon.guacamole.auth.jdbc.user;
|
||||
|
||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||
|
||||
/**
|
||||
* Represents an authenticated user via their database ID and corresponding
|
||||
* credentials.
|
||||
* Associates a user with the credentials they used to authenticate.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class AuthenticatedUser {
|
||||
|
||||
/**
|
||||
* The database ID of this user.
|
||||
* The user that authenticated.
|
||||
*/
|
||||
private final int userID;
|
||||
private final ModeledUser user;
|
||||
|
||||
/**
|
||||
* The credentials given when this user authenticated.
|
||||
@@ -43,28 +42,28 @@ public class AuthenticatedUser {
|
||||
private final Credentials credentials;
|
||||
|
||||
/**
|
||||
* Creates a new AuthenticatedUser associated with the given database ID
|
||||
* and credentials.
|
||||
* Creates a new AuthenticatedUser associating the given user with their
|
||||
* corresponding credentials.
|
||||
*
|
||||
* @param userID
|
||||
* The database ID of the user this object should represent.
|
||||
* @param user
|
||||
* The user this object should represent.
|
||||
*
|
||||
* @param credentials
|
||||
* The credentials given by the user when they authenticated.
|
||||
*/
|
||||
public AuthenticatedUser(int userID, Credentials credentials) {
|
||||
this.userID = userID;
|
||||
public AuthenticatedUser(ModeledUser user, Credentials credentials) {
|
||||
this.user = user;
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of this user.
|
||||
* Returns the user that authenticated.
|
||||
*
|
||||
* @return
|
||||
* The ID of this user.
|
||||
* The user that authenticated.
|
||||
*/
|
||||
public int getUserID() {
|
||||
return userID;
|
||||
public ModeledUser getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.user;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObject;
|
||||
import org.glyptodon.guacamole.auth.jdbc.security.PasswordEncryptionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.security.SaltService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.SystemPermissionService;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionGroupPermissionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ConnectionPermissionService;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionService;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
|
||||
|
||||
/**
|
||||
* An implementation of the User object which is backed by a database model.
|
||||
*
|
||||
* @author James Muehlner
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class ModeledUser extends DirectoryObject<UserModel> implements User {
|
||||
|
||||
/**
|
||||
* Service for hashing passwords.
|
||||
*/
|
||||
@Inject
|
||||
private PasswordEncryptionService encryptionService;
|
||||
|
||||
/**
|
||||
* Service for providing secure, random salts.
|
||||
*/
|
||||
@Inject
|
||||
private SaltService saltService;
|
||||
|
||||
/**
|
||||
* Service for retrieving system permissions.
|
||||
*/
|
||||
@Inject
|
||||
private SystemPermissionService systemPermissionService;
|
||||
|
||||
/**
|
||||
* Service for retrieving connection permissions.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionPermissionService connectionPermissionService;
|
||||
|
||||
/**
|
||||
* Service for retrieving connection group permissions.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupPermissionService connectionGroupPermissionService;
|
||||
|
||||
/**
|
||||
* Service for retrieving user permissions.
|
||||
*/
|
||||
@Inject
|
||||
private UserPermissionService userPermissionService;
|
||||
|
||||
/**
|
||||
* The plaintext password previously set by a call to setPassword(), if
|
||||
* any. The password of a user cannot be retrieved once saved into the
|
||||
* database, so this serves to ensure getPassword() returns a reasonable
|
||||
* value if setPassword() is called. If no password has been set, or the
|
||||
* user was retrieved from the database, this will be null.
|
||||
*/
|
||||
private String password = null;
|
||||
|
||||
/**
|
||||
* Creates a new, empty ModeledUser.
|
||||
*/
|
||||
public ModeledUser() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPassword(String password) {
|
||||
|
||||
UserModel userModel = getModel();
|
||||
|
||||
// Store plaintext password internally
|
||||
this.password = password;
|
||||
|
||||
// If no password provided, clear password salt and hash
|
||||
if (password == null) {
|
||||
userModel.setPasswordSalt(null);
|
||||
userModel.setPasswordHash(null);
|
||||
}
|
||||
|
||||
// Otherwise generate new salt and hash given password using newly-generated salt
|
||||
else {
|
||||
byte[] salt = saltService.generateSalt();
|
||||
byte[] hash = encryptionService.createPasswordHash(password, salt);
|
||||
|
||||
// Set stored salt and hash
|
||||
userModel.setPasswordSalt(salt);
|
||||
userModel.setPasswordHash(hash);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this user is a system administrator, and thus is not
|
||||
* restricted by permissions.
|
||||
*
|
||||
* @return
|
||||
* true if this user is a system administrator, false otherwise.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while determining the user's system administrator
|
||||
* status.
|
||||
*/
|
||||
public boolean isAdministrator() throws GuacamoleException {
|
||||
SystemPermissionSet systemPermissionSet = getSystemPermissions();
|
||||
return systemPermissionSet.hasPermission(SystemPermission.Type.ADMINISTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SystemPermissionSet getSystemPermissions()
|
||||
throws GuacamoleException {
|
||||
return systemPermissionService.getPermissionSet(getCurrentUser(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPermissionSet getConnectionPermissions()
|
||||
throws GuacamoleException {
|
||||
return connectionPermissionService.getPermissionSet(getCurrentUser(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPermissionSet getConnectionGroupPermissions()
|
||||
throws GuacamoleException {
|
||||
return connectionGroupPermissionService.getPermissionSet(getCurrentUser(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectPermissionSet getUserPermissions()
|
||||
throws GuacamoleException {
|
||||
return userPermissionService.getPermissionSet(getCurrentUser(), this);
|
||||
}
|
||||
|
||||
}
|
@@ -20,29 +20,30 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.sourceforge.guacamole.net.auth.mysql;
|
||||
package org.glyptodon.guacamole.auth.jdbc.user;
|
||||
|
||||
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.RootConnectionGroup;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupDirectory;
|
||||
import org.glyptodon.guacamole.auth.jdbc.connection.ConnectionDirectory;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.RestrictedObject;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.service.UserService;
|
||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||
|
||||
/**
|
||||
* The MySQL representation of a UserContext.
|
||||
* UserContext implementation which is driven by an arbitrary, underlying
|
||||
* database.
|
||||
*
|
||||
* @author James Muehlner
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class MySQLUserContext implements UserContext {
|
||||
|
||||
/**
|
||||
* The the user owning this context. The permissions of this user dictate
|
||||
* the access given via the user and connection directories.
|
||||
*/
|
||||
private AuthenticatedUser currentUser;
|
||||
public class UserContext extends RestrictedObject
|
||||
implements org.glyptodon.guacamole.net.auth.UserContext {
|
||||
|
||||
/**
|
||||
* User directory restricted by the permissions of the user associated
|
||||
@@ -52,45 +53,65 @@ public class MySQLUserContext implements UserContext {
|
||||
private UserDirectory userDirectory;
|
||||
|
||||
/**
|
||||
* The root connection group.
|
||||
* Connection directory restricted by the permissions of the user
|
||||
* associated with this context.
|
||||
*/
|
||||
@Inject
|
||||
private MySQLConnectionGroup rootConnectionGroup;
|
||||
private ConnectionDirectory connectionDirectory;
|
||||
|
||||
/**
|
||||
* Service for accessing users.
|
||||
* Connection group directory restricted by the permissions of the user
|
||||
* associated with this context.
|
||||
*/
|
||||
@Inject
|
||||
private UserService userService;
|
||||
private ConnectionGroupDirectory connectionGroupDirectory;
|
||||
|
||||
/**
|
||||
* Initializes the user and directories associated with this context.
|
||||
*
|
||||
* @param currentUser
|
||||
* The user owning this context.
|
||||
* Provider for creating the root group.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<RootConnectionGroup> rootGroupProvider;
|
||||
|
||||
@Override
|
||||
public void init(AuthenticatedUser currentUser) {
|
||||
this.currentUser = currentUser;
|
||||
|
||||
super.init(currentUser);
|
||||
|
||||
// Init directories
|
||||
userDirectory.init(currentUser);
|
||||
rootConnectionGroup.init(null, null,
|
||||
MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER,
|
||||
MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER,
|
||||
ConnectionGroup.Type.ORGANIZATIONAL, currentUser);
|
||||
connectionDirectory.init(currentUser);
|
||||
connectionGroupDirectory.init(currentUser);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public User self() {
|
||||
return userService.retrieveUser(currentUser.getUserID());
|
||||
return getCurrentUser().getUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Directory<String, User> getUserDirectory() throws GuacamoleException {
|
||||
public Directory<User> getUserDirectory() throws GuacamoleException {
|
||||
return userDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Directory<Connection> getConnectionDirectory() throws GuacamoleException {
|
||||
return connectionDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Directory<ConnectionGroup> getConnectionGroupDirectory() throws GuacamoleException {
|
||||
return connectionGroupDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionGroup getRootConnectionGroup() throws GuacamoleException {
|
||||
return rootConnectionGroup;
|
||||
|
||||
// Build and return a root group for the current user
|
||||
RootConnectionGroup rootGroup = rootGroupProvider.get();
|
||||
rootGroup.init(getCurrentUser());
|
||||
return rootGroup;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.user;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||
|
||||
/**
|
||||
* Service which creates new UserContext instances for valid users based on
|
||||
* credentials.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class UserContextService {
|
||||
|
||||
/**
|
||||
* Service for accessing users.
|
||||
*/
|
||||
@Inject
|
||||
private UserService userService;
|
||||
|
||||
/**
|
||||
* Provider for retrieving UserContext instances.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<UserContext> userContextProvider;
|
||||
|
||||
/**
|
||||
* Authenticates the user having the given credentials, returning a new
|
||||
* UserContext instance if the credentials are valid.
|
||||
*
|
||||
* @param credentials
|
||||
* The credentials to use to produce the UserContext.
|
||||
*
|
||||
* @return
|
||||
* A new UserContext instance for the user identified by the given
|
||||
* credentials, or null if the credentials are not valid.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs during authentication.
|
||||
*/
|
||||
public org.glyptodon.guacamole.net.auth.UserContext
|
||||
getUserContext(Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Authenticate user
|
||||
ModeledUser user = userService.retrieveUser(credentials);
|
||||
if (user != null) {
|
||||
|
||||
// Upon successful authentication, return new user context
|
||||
UserContext context = userContextProvider.get();
|
||||
context.init(user.getCurrentUser());
|
||||
return context;
|
||||
|
||||
}
|
||||
|
||||
// Otherwise, unauthorized
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.user;
|
||||
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.RestrictedObject;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
import org.mybatis.guice.transactional.Transactional;
|
||||
|
||||
/**
|
||||
* Implementation of the User Directory which is driven by an underlying,
|
||||
* arbitrary database.
|
||||
*
|
||||
* @author James Muehlner
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class UserDirectory extends RestrictedObject
|
||||
implements Directory<User> {
|
||||
|
||||
/**
|
||||
* Service for managing user objects.
|
||||
*/
|
||||
@Inject
|
||||
private UserService userService;
|
||||
|
||||
@Override
|
||||
public User get(String identifier) throws GuacamoleException {
|
||||
return userService.retrieveObject(getCurrentUser(), identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Collection<User> getAll(Collection<String> identifiers) throws GuacamoleException {
|
||||
Collection<ModeledUser> objects = userService.retrieveObjects(getCurrentUser(), identifiers);
|
||||
return Collections.<User>unmodifiableCollection(objects);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Set<String> getIdentifiers() throws GuacamoleException {
|
||||
return userService.getIdentifiers(getCurrentUser());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void add(User object) throws GuacamoleException {
|
||||
userService.createObject(getCurrentUser(), object);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void update(User object) throws GuacamoleException {
|
||||
ModeledUser user = (ModeledUser) object;
|
||||
userService.updateObject(getCurrentUser(), user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void remove(String identifier) throws GuacamoleException {
|
||||
userService.deleteObject(getCurrentUser(), identifier);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.user;
|
||||
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* Mapper for user objects.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public interface UserMapper extends DirectoryObjectMapper<UserModel> {
|
||||
|
||||
/**
|
||||
* Returns the user having the given username and password, if any. If no
|
||||
* such user exists, null is returned.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user to return.
|
||||
*
|
||||
* @param password
|
||||
* The password of the user to return.
|
||||
*
|
||||
* @return
|
||||
* The user having the given username and password, or null if no such
|
||||
* user exists.
|
||||
*/
|
||||
UserModel selectOneByCredentials(@Param("username") String username,
|
||||
@Param("password") String password);
|
||||
|
||||
/**
|
||||
* Returns the user having the given username, if any. If no such user
|
||||
* exists, null is returned.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user to return.
|
||||
*
|
||||
* @return
|
||||
* The user having the given username, or null if no such user exists.
|
||||
*/
|
||||
UserModel selectOne(@Param("username") String username);
|
||||
|
||||
}
|
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.user;
|
||||
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.ObjectModel;
|
||||
|
||||
/**
|
||||
* Object representation of a Guacamole user, as represented in the database.
|
||||
*
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class UserModel extends ObjectModel {
|
||||
|
||||
/**
|
||||
* The SHA-256 hash of the password and salt.
|
||||
*/
|
||||
private byte[] passwordHash;
|
||||
|
||||
/**
|
||||
* The 32-byte random binary password salt that was appended to the
|
||||
* password prior to hashing.
|
||||
*/
|
||||
private byte[] passwordSalt;
|
||||
|
||||
/**
|
||||
* Creates a new, empty user.
|
||||
*/
|
||||
public UserModel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash of this user's password and password salt. This may be
|
||||
* null if the user was not retrieved from the database, and setPassword()
|
||||
* has not yet been called.
|
||||
*
|
||||
* @return
|
||||
* The hash of this user's password and password salt.
|
||||
*/
|
||||
public byte[] getPasswordHash() {
|
||||
return passwordHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the hash of this user's password and password salt. This is
|
||||
* normally only set upon retrieval from the database, or through a call
|
||||
* to the higher-level setPassword() function.
|
||||
*
|
||||
* @param passwordHash
|
||||
* The hash of this user's password and password salt.
|
||||
*/
|
||||
public void setPasswordHash(byte[] passwordHash) {
|
||||
this.passwordHash = passwordHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the random salt that was used when generating this user's
|
||||
* password hash. This may be null if the user was not retrieved from the
|
||||
* database, and setPassword() has not yet been called.
|
||||
*
|
||||
* @return
|
||||
* The random salt that was used when generating this user's password
|
||||
* hash.
|
||||
*/
|
||||
public byte[] getPasswordSalt() {
|
||||
return passwordSalt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the random salt that was used when generating this user's password
|
||||
* hash. This is normally only set upon retrieval from the database, or
|
||||
* through a call to the higher-level setPassword() function.
|
||||
*
|
||||
* @param passwordSalt
|
||||
* The random salt used when generating this user's password hash.
|
||||
*/
|
||||
public void setPasswordSalt(byte[] passwordSalt) {
|
||||
this.passwordSalt = passwordSalt;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* 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 org.glyptodon.guacamole.auth.jdbc.user;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.base.DirectoryObjectService;
|
||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
|
||||
import org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionMapper;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
|
||||
|
||||
/**
|
||||
* Service which provides convenience methods for creating, retrieving, and
|
||||
* manipulating users.
|
||||
*
|
||||
* @author Michael Jumper, James Muehlner
|
||||
*/
|
||||
public class UserService extends DirectoryObjectService<ModeledUser, User, UserModel> {
|
||||
|
||||
/**
|
||||
* Mapper for accessing users.
|
||||
*/
|
||||
@Inject
|
||||
private UserMapper userMapper;
|
||||
|
||||
/**
|
||||
* Mapper for manipulating user permissions.
|
||||
*/
|
||||
@Inject
|
||||
private UserPermissionMapper userPermissionMapper;
|
||||
|
||||
/**
|
||||
* Provider for creating users.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<ModeledUser> userProvider;
|
||||
|
||||
@Override
|
||||
protected DirectoryObjectMapper<UserModel> getObjectMapper() {
|
||||
return userMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionMapper getPermissionMapper() {
|
||||
return userPermissionMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ModeledUser getObjectInstance(AuthenticatedUser currentUser,
|
||||
UserModel model) {
|
||||
ModeledUser user = userProvider.get();
|
||||
user.init(currentUser, model);
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UserModel getModelInstance(AuthenticatedUser currentUser,
|
||||
final User object) {
|
||||
|
||||
// Create new ModeledUser backed by blank model
|
||||
UserModel model = new UserModel();
|
||||
ModeledUser user = getObjectInstance(currentUser, model);
|
||||
|
||||
// Set model contents through ModeledUser, copying the provided user
|
||||
user.setIdentifier(object.getIdentifier());
|
||||
user.setPassword(object.getPassword());
|
||||
|
||||
return model;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasCreatePermission(AuthenticatedUser user)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Return whether user has explicit user creation permission
|
||||
SystemPermissionSet permissionSet = user.getUser().getSystemPermissions();
|
||||
return permissionSet.hasPermission(SystemPermission.Type.CREATE_USER);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ObjectPermissionSet getPermissionSet(AuthenticatedUser user)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Return permissions related to users
|
||||
return user.getUser().getUserPermissions();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateNewModel(AuthenticatedUser user, UserModel model)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Username must not be blank
|
||||
if (model.getIdentifier().trim().isEmpty())
|
||||
throw new GuacamoleClientException("The username must not be blank.");
|
||||
|
||||
// Do not create duplicate users
|
||||
Collection<UserModel> existing = userMapper.select(Collections.singleton(model.getIdentifier()));
|
||||
if (!existing.isEmpty())
|
||||
throw new GuacamoleClientException("User \"" + model.getIdentifier() + "\" already exists.");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateExistingModel(AuthenticatedUser user,
|
||||
UserModel model) throws GuacamoleException {
|
||||
|
||||
// Username must not be blank
|
||||
if (model.getIdentifier().trim().isEmpty())
|
||||
throw new GuacamoleClientException("The username must not be blank.");
|
||||
|
||||
// Check whether such a user is already present
|
||||
UserModel existing = userMapper.selectOne(model.getIdentifier());
|
||||
if (existing != null) {
|
||||
|
||||
// Do not rename to existing user
|
||||
if (!existing.getObjectID().equals(model.getObjectID()))
|
||||
throw new GuacamoleClientException("User \"" + model.getIdentifier() + "\" already exists.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the user corresponding to the given credentials from the
|
||||
* database.
|
||||
*
|
||||
* @param credentials
|
||||
* The credentials to use when locating the user.
|
||||
*
|
||||
* @return
|
||||
* The existing ModeledUser object if the credentials given are valid,
|
||||
* null otherwise.
|
||||
*/
|
||||
public ModeledUser retrieveUser(Credentials credentials) {
|
||||
|
||||
// Get username and password
|
||||
String username = credentials.getUsername();
|
||||
String password = credentials.getPassword();
|
||||
|
||||
// Retrieve user model, if the user exists
|
||||
UserModel userModel = userMapper.selectOneByCredentials(username, password);
|
||||
if (userModel == null)
|
||||
return null;
|
||||
|
||||
// Return corresponding user, set up cyclic reference
|
||||
ModeledUser user = getObjectInstance(null, userModel);
|
||||
user.setCurrentUser(new AuthenticatedUser(user, credentials));
|
||||
return user;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Classes related to Guacamole users.
|
||||
*/
|
||||
package org.glyptodon.guacamole.auth.jdbc.user;
|
2
extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/.gitignore
vendored
Normal file
2
extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
target/
|
||||
*~
|
@@ -0,0 +1,78 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-auth-jdbc-mysql</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>guacamole-auth-jdbc-mysql</name>
|
||||
<url>http://guac-dev.org/</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-auth-jdbc</artifactId>
|
||||
<version>0.9.5</version>
|
||||
<relativePath>../../</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<!-- Written for 1.6 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Assembly plugin - for easy distribution -->
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.2-beta-5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>jar-with-dependencies</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<finalName>extension/${project.artifactId}-${project.version}</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Guacamole Extension API -->
|
||||
<dependency>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-ext</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Guacamole JDBC Authentication -->
|
||||
<dependency>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-auth-jdbc-base</artifactId>
|
||||
<version>0.9.5</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import org.glyptodon.guacamole.auth.jdbc.JDBCAuthenticationProviderModule;
|
||||
import org.glyptodon.guacamole.auth.jdbc.user.UserContextService;
|
||||
import org.glyptodon.guacamole.environment.Environment;
|
||||
import org.glyptodon.guacamole.environment.LocalEnvironment;
|
||||
|
||||
/**
|
||||
* Provides a MySQL based implementation of the AuthenticationProvider
|
||||
* functionality.
|
||||
*
|
||||
* @author James Muehlner
|
||||
* @author Michael Jumper
|
||||
*/
|
||||
public class MySQLAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
/**
|
||||
* Injector which will manage the object graph of this authentication
|
||||
* provider.
|
||||
*/
|
||||
private final Injector injector;
|
||||
|
||||
/**
|
||||
* Creates a new MySQLAuthenticationProvider that reads and writes
|
||||
* authentication data to a MySQL database defined by properties in
|
||||
* guacamole.properties.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If a required property is missing, or an error occurs while parsing
|
||||
* a property.
|
||||
*/
|
||||
public MySQLAuthenticationProvider() throws GuacamoleException {
|
||||
|
||||
// Get local environment
|
||||
Environment environment = new LocalEnvironment();
|
||||
|
||||
// Set up Guice injector.
|
||||
injector = Guice.createInjector(
|
||||
|
||||
// Configure MySQL-specific authentication
|
||||
new MySQLAuthenticationProviderModule(environment),
|
||||
|
||||
// Configure JDBC authentication core
|
||||
new JDBCAuthenticationProviderModule(environment)
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext getUserContext(Credentials credentials)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Create UserContext based on credentials, if valid
|
||||
UserContextService userContextService = injector.getInstance(UserContextService.class);
|
||||
return userContextService.getUserContext(credentials);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserContext updateUserContext(UserContext context,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
|
||||
// No need to update the context
|
||||
return context;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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 net.sourceforge.guacamole.net.auth.mysql;
|
||||
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.name.Names;
|
||||
import java.util.Properties;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.environment.Environment;
|
||||
import org.mybatis.guice.datasource.helper.JdbcHelper;
|
||||
|
||||
/**
|
||||
* Guice module which configures MySQL-specific injections.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class MySQLAuthenticationProviderModule implements Module {
|
||||
|
||||
/**
|
||||
* MyBatis-specific configuration properties.
|
||||
*/
|
||||
private final Properties myBatisProperties = new Properties();
|
||||
|
||||
/**
|
||||
* MySQL-specific driver configuration properties.
|
||||
*/
|
||||
private final Properties driverProperties = new Properties();
|
||||
|
||||
/**
|
||||
* Creates a new MySQL authentication provider module that configures
|
||||
* driver and MyBatis properties using the given environment.
|
||||
*
|
||||
* @param environment
|
||||
* The environment to use when configuring MyBatis and the underlying
|
||||
* JDBC driver.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If a required property is missing, or an error occurs while parsing
|
||||
* a property.
|
||||
*/
|
||||
public MySQLAuthenticationProviderModule(Environment environment)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Set the MySQL-specific properties for MyBatis.
|
||||
myBatisProperties.setProperty("mybatis.environment.id", "guacamole");
|
||||
myBatisProperties.setProperty("JDBC.host", environment.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_HOSTNAME));
|
||||
myBatisProperties.setProperty("JDBC.port", String.valueOf(environment.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_PORT)));
|
||||
myBatisProperties.setProperty("JDBC.schema", environment.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_DATABASE));
|
||||
myBatisProperties.setProperty("JDBC.username", environment.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_USERNAME));
|
||||
myBatisProperties.setProperty("JDBC.password", environment.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_PASSWORD));
|
||||
myBatisProperties.setProperty("JDBC.autoCommit", "false");
|
||||
myBatisProperties.setProperty("mybatis.pooled.pingEnabled", "true");
|
||||
myBatisProperties.setProperty("mybatis.pooled.pingQuery", "SELECT 1");
|
||||
|
||||
// Use UTF-8 in database
|
||||
driverProperties.setProperty("characterEncoding","UTF-8");
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Binder binder) {
|
||||
|
||||
// Bind MySQL-specific properties
|
||||
JdbcHelper.MySQL.configure(binder);
|
||||
|
||||
// Bind MyBatis properties
|
||||
Names.bindProperties(binder, myBatisProperties);
|
||||
|
||||
// Bing JDBC driver properties
|
||||
binder.bind(Properties.class)
|
||||
.annotatedWith(Names.named("JDBC.driverProperties"))
|
||||
.toInstance(driverProperties);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -20,7 +20,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package net.sourceforge.guacamole.net.auth.mysql.properties;
|
||||
package net.sourceforge.guacamole.net.auth.mysql;
|
||||
|
||||
import org.glyptodon.guacamole.properties.BooleanGuacamoleProperty;
|
||||
import org.glyptodon.guacamole.properties.IntegerGuacamoleProperty;
|
@@ -21,8 +21,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base classes which support the MySQL authentication provider, including
|
||||
* the authentication provider itself.
|
||||
* The MySQL authentication provider. This package exists outside of
|
||||
* org.glyptodon for backwards-compatibility.
|
||||
*/
|
||||
package net.sourceforge.guacamole.net.auth.mysql;
|
||||
|
@@ -0,0 +1,158 @@
|
||||
<?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="org.glyptodon.guacamole.auth.jdbc.connection.ConnectionMapper" >
|
||||
|
||||
<!-- Result mapper for connection objects -->
|
||||
<resultMap id="ConnectionResultMap" type="org.glyptodon.guacamole.auth.jdbc.connection.ConnectionModel" >
|
||||
<id column="connection_id" property="objectID" jdbcType="INTEGER"/>
|
||||
<result column="connection_name" property="name" jdbcType="VARCHAR"/>
|
||||
<result column="parent_id" property="parentIdentifier" jdbcType="INTEGER"/>
|
||||
<result column="protocol" property="protocol" jdbcType="VARCHAR"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- Select all connection identifiers -->
|
||||
<select id="selectIdentifiers" resultType="string">
|
||||
SELECT connection_id
|
||||
FROM guacamole_connection
|
||||
</select>
|
||||
|
||||
<!-- Select identifiers of all readable connections -->
|
||||
<select id="selectReadableIdentifiers" resultType="string">
|
||||
SELECT connection_id
|
||||
FROM guacamole_connection_permission
|
||||
WHERE
|
||||
user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = 'READ'
|
||||
</select>
|
||||
|
||||
<!-- Select all connection identifiers within a particular connection group -->
|
||||
<select id="selectIdentifiersWithin" resultType="string">
|
||||
SELECT connection_id
|
||||
FROM guacamole_connection
|
||||
WHERE
|
||||
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=VARCHAR}</if>
|
||||
<if test="parentIdentifier == null">parent_id IS NULL</if>
|
||||
</select>
|
||||
|
||||
<!-- Select identifiers of all readable connections within a particular connection group -->
|
||||
<select id="selectReadableIdentifiersWithin" resultType="string">
|
||||
SELECT guacamole_connection.connection_id
|
||||
FROM guacamole_connection
|
||||
JOIN guacamole_connection_permission ON guacamole_connection_permission.connection_id = guacamole_connection.connection_id
|
||||
WHERE
|
||||
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=VARCHAR}</if>
|
||||
<if test="parentIdentifier == null">parent_id IS NULL</if>
|
||||
AND user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = 'READ'
|
||||
</select>
|
||||
|
||||
<!-- Select multiple connections by identifier -->
|
||||
<select id="select" resultMap="ConnectionResultMap">
|
||||
|
||||
SELECT
|
||||
connection_id,
|
||||
connection_name,
|
||||
parent_id,
|
||||
protocol
|
||||
FROM guacamole_connection
|
||||
WHERE connection_id IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select multiple connections by identifier only if readable -->
|
||||
<select id="selectReadable" resultMap="ConnectionResultMap">
|
||||
|
||||
SELECT
|
||||
guacamole_connection.connection_id,
|
||||
connection_name,
|
||||
parent_id,
|
||||
protocol
|
||||
FROM guacamole_connection
|
||||
JOIN guacamole_connection_permission ON guacamole_connection_permission.connection_id = guacamole_connection.connection_id
|
||||
WHERE guacamole_connection.connection_id IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
AND user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = 'READ'
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select single connection by name -->
|
||||
<select id="selectOneByName" resultMap="ConnectionResultMap">
|
||||
|
||||
SELECT
|
||||
connection_id,
|
||||
connection_name,
|
||||
parent_id,
|
||||
protocol
|
||||
FROM guacamole_connection
|
||||
WHERE
|
||||
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=VARCHAR}</if>
|
||||
<if test="parentIdentifier == null">parent_id IS NULL</if>
|
||||
AND connection_name = #{name,jdbcType=VARCHAR}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Delete single connection by identifier -->
|
||||
<delete id="delete">
|
||||
DELETE FROM guacamole_connection
|
||||
WHERE connection_id = #{identifier,jdbcType=VARCHAR}
|
||||
</delete>
|
||||
|
||||
<!-- Insert single connection -->
|
||||
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
|
||||
parameterType="org.glyptodon.guacamole.auth.jdbc.connection.ConnectionModel">
|
||||
|
||||
INSERT INTO guacamole_connection (
|
||||
connection_name,
|
||||
parent_id,
|
||||
protocol
|
||||
)
|
||||
VALUES (
|
||||
#{object.name,jdbcType=VARCHAR},
|
||||
#{object.parentIdentifier,jdbcType=VARCHAR},
|
||||
#{object.protocol,jdbcType=VARCHAR}
|
||||
)
|
||||
|
||||
</insert>
|
||||
|
||||
<!-- Update single connection -->
|
||||
<update id="update" parameterType="org.glyptodon.guacamole.auth.jdbc.connection.ConnectionModel">
|
||||
UPDATE guacamole_connection
|
||||
SET connection_name = #{object.name,jdbcType=VARCHAR},
|
||||
parent_id = #{object.parentIdentifier,jdbcType=VARCHAR},
|
||||
protocol = #{object.protocol,jdbcType=VARCHAR}
|
||||
WHERE connection_id = #{object.objectID,jdbcType=INTEGER}
|
||||
</update>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,75 @@
|
||||
<?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="org.glyptodon.guacamole.auth.jdbc.connection.ConnectionRecordMapper" >
|
||||
|
||||
<!-- Result mapper for system permissions -->
|
||||
<resultMap id="ConnectionRecordResultMap" type="org.glyptodon.guacamole.auth.jdbc.connection.ConnectionRecordModel">
|
||||
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
|
||||
<result column="user_id" property="userID" jdbcType="INTEGER"/>
|
||||
<result column="username" property="username" jdbcType="VARCHAR"/>
|
||||
<result column="start_date" property="startDate" jdbcType="TIMESTAMP"/>
|
||||
<result column="end_date" property="endDate" jdbcType="TIMESTAMP"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- Select all connection records from a given connection -->
|
||||
<select id="select" resultMap="ConnectionRecordResultMap">
|
||||
|
||||
SELECT
|
||||
connection_id,
|
||||
guacamole_connection_history.user_id,
|
||||
username,
|
||||
start_date,
|
||||
end_date
|
||||
FROM guacamole_connection_history
|
||||
JOIN guacamole_user ON guacamole_connection_history.user_id = guacamole_user.user_id
|
||||
WHERE
|
||||
connection_id = #{identifier,jdbcType=VARCHAR}
|
||||
ORDER BY
|
||||
start_date DESC,
|
||||
end_date DESC
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Insert the given connection record -->
|
||||
<insert id="insert" parameterType="org.glyptodon.guacamole.auth.jdbc.connection.ConnectionRecordModel">
|
||||
|
||||
INSERT INTO guacamole_connection_history (
|
||||
connection_id,
|
||||
user_id,
|
||||
start_date,
|
||||
end_date
|
||||
)
|
||||
VALUES (
|
||||
#{record.connectionIdentifier,jdbcType=VARCHAR},
|
||||
#{record.userID,jdbcType=INTEGER},
|
||||
#{record.startDate,jdbcType=TIMESTAMP},
|
||||
#{record.endDate,jdbcType=TIMESTAMP}
|
||||
)
|
||||
|
||||
</insert>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,71 @@
|
||||
<?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="org.glyptodon.guacamole.auth.jdbc.connection.ParameterMapper">
|
||||
|
||||
<!-- Result mapper for connection parameters -->
|
||||
<resultMap id="ParameterResultMap" type="org.glyptodon.guacamole.auth.jdbc.connection.ParameterModel">
|
||||
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
|
||||
<result column="parameter_name" property="name" jdbcType="VARCHAR"/>
|
||||
<result column="parameter_value" property="value" jdbcType="VARCHAR"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- Select all parameters of a given connection -->
|
||||
<select id="select" resultMap="ParameterResultMap">
|
||||
SELECT
|
||||
connection_id,
|
||||
parameter_name,
|
||||
parameter_value
|
||||
FROM guacamole_connection_parameter
|
||||
WHERE
|
||||
connection_id = #{identifier,jdbcType=VARCHAR}
|
||||
</select>
|
||||
|
||||
<!-- Delete all parameters of a given connection -->
|
||||
<delete id="delete">
|
||||
DELETE FROM guacamole_connection_parameter
|
||||
WHERE connection_id = #{identifier,jdbcType=VARCHAR}
|
||||
</delete>
|
||||
|
||||
<!-- Insert all given parameters -->
|
||||
<insert id="insert" parameterType="org.glyptodon.guacamole.auth.jdbc.connection.ParameterModel">
|
||||
|
||||
INSERT INTO guacamole_connection_parameter (
|
||||
connection_id,
|
||||
parameter_name,
|
||||
parameter_value
|
||||
)
|
||||
VALUES
|
||||
<foreach collection="parameters" item="parameter" separator=",">
|
||||
(#{parameter.connectionIdentifier,jdbcType=VARCHAR},
|
||||
#{parameter.name,jdbcType=VARCHAR},
|
||||
#{parameter.value,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
|
||||
</insert>
|
||||
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,159 @@
|
||||
<?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="org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupMapper" >
|
||||
|
||||
<!-- Result mapper for connection objects -->
|
||||
<resultMap id="ConnectionGroupResultMap" type="org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel" >
|
||||
<id column="connection_group_id" property="objectID" jdbcType="INTEGER"/>
|
||||
<result column="connection_group_name" property="name" jdbcType="VARCHAR"/>
|
||||
<result column="parent_id" property="parentIdentifier" jdbcType="INTEGER"/>
|
||||
<result column="type" property="type" jdbcType="VARCHAR"
|
||||
javaType="org.glyptodon.guacamole.net.auth.ConnectionGroup$Type"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- Select all connection group identifiers -->
|
||||
<select id="selectIdentifiers" resultType="string">
|
||||
SELECT connection_group_id
|
||||
FROM guacamole_connection_group
|
||||
</select>
|
||||
|
||||
<!-- Select identifiers of all readable connection groups -->
|
||||
<select id="selectReadableIdentifiers" resultType="string">
|
||||
SELECT connection_group_id
|
||||
FROM guacamole_connection_group_permission
|
||||
WHERE
|
||||
user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = 'READ'
|
||||
</select>
|
||||
|
||||
<!-- Select all connection identifiers within a particular connection group -->
|
||||
<select id="selectIdentifiersWithin" resultType="string">
|
||||
SELECT connection_group_id
|
||||
FROM guacamole_connection_group
|
||||
WHERE
|
||||
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=VARCHAR}</if>
|
||||
<if test="parentIdentifier == null">parent_id IS NULL</if>
|
||||
</select>
|
||||
|
||||
<!-- Select identifiers of all readable connection groups within a particular connection group -->
|
||||
<select id="selectReadableIdentifiersWithin" resultType="string">
|
||||
SELECT guacamole_connection_group.connection_group_id
|
||||
FROM guacamole_connection_group
|
||||
JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group.connection_group_id
|
||||
WHERE
|
||||
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=VARCHAR}</if>
|
||||
<if test="parentIdentifier == null">parent_id IS NULL</if>
|
||||
AND user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = 'READ'
|
||||
</select>
|
||||
|
||||
<!-- Select multiple connection groups by identifier -->
|
||||
<select id="select" resultMap="ConnectionGroupResultMap">
|
||||
|
||||
SELECT
|
||||
connection_group_id,
|
||||
connection_group_name,
|
||||
parent_id,
|
||||
type
|
||||
FROM guacamole_connection_group
|
||||
WHERE connection_group_id IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select multiple connection groups by identifier only if readable -->
|
||||
<select id="selectReadable" resultMap="ConnectionGroupResultMap">
|
||||
|
||||
SELECT
|
||||
guacamole_connection_group.connection_group_id,
|
||||
connection_group_name,
|
||||
parent_id,
|
||||
type
|
||||
FROM guacamole_connection_group
|
||||
JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group.connection_group_id
|
||||
WHERE guacamole_connection_group.connection_group_id IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
AND user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = 'READ'
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select single connection group by name -->
|
||||
<select id="selectOneByName" resultMap="ConnectionGroupResultMap">
|
||||
|
||||
SELECT
|
||||
connection_group_id,
|
||||
connection_group_name,
|
||||
parent_id,
|
||||
type
|
||||
FROM guacamole_connection_group
|
||||
WHERE
|
||||
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=VARCHAR}</if>
|
||||
<if test="parentIdentifier == null">parent_id IS NULL</if>
|
||||
AND connection_group_name = #{name,jdbcType=VARCHAR}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Delete single connection group by identifier -->
|
||||
<delete id="delete">
|
||||
DELETE FROM guacamole_connection_group
|
||||
WHERE connection_group_id = #{identifier,jdbcType=VARCHAR}
|
||||
</delete>
|
||||
|
||||
<!-- Insert single connection -->
|
||||
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
|
||||
parameterType="org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel">
|
||||
|
||||
INSERT INTO guacamole_connection_group (
|
||||
connection_group_name,
|
||||
parent_id,
|
||||
type
|
||||
)
|
||||
VALUES (
|
||||
#{object.name,jdbcType=VARCHAR},
|
||||
#{object.parentIdentifier,jdbcType=VARCHAR},
|
||||
#{object.type,jdbcType=VARCHAR}
|
||||
)
|
||||
|
||||
</insert>
|
||||
|
||||
<!-- Update single connection group -->
|
||||
<update id="update" parameterType="org.glyptodon.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel">
|
||||
UPDATE guacamole_connection_group
|
||||
SET connection_group_name = #{object.name,jdbcType=VARCHAR},
|
||||
parent_id = #{object.parentIdentifier,jdbcType=VARCHAR},
|
||||
type = #{object.type,jdbcType=VARCHAR}
|
||||
WHERE connection_group_id = #{object.objectID,jdbcType=INTEGER}
|
||||
</update>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,120 @@
|
||||
<?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="org.glyptodon.guacamole.auth.jdbc.permission.ConnectionGroupPermissionMapper" >
|
||||
|
||||
<!-- Result mapper for connection permissions -->
|
||||
<resultMap id="ConnectionGroupPermissionResultMap" type="org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionModel">
|
||||
<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.ObjectPermission$Type"/>
|
||||
<result column="connection_group_id" property="objectIdentifier" jdbcType="INTEGER"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- Select all permissions for a given user -->
|
||||
<select id="select" resultMap="ConnectionGroupPermissionResultMap">
|
||||
|
||||
SELECT
|
||||
guacamole_connection_group_permission.user_id,
|
||||
username,
|
||||
permission,
|
||||
connection_group_id
|
||||
FROM guacamole_connection_group_permission
|
||||
JOIN guacamole_user ON guacamole_connection_group_permission.user_id = guacamole_user.user_id
|
||||
WHERE guacamole_connection_group_permission.user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select the single permission matching the given criteria -->
|
||||
<select id="selectOne" resultMap="ConnectionGroupPermissionResultMap">
|
||||
|
||||
SELECT
|
||||
guacamole_connection_group_permission.user_id,
|
||||
username,
|
||||
permission,
|
||||
connection_group_id
|
||||
FROM guacamole_connection_group_permission
|
||||
JOIN guacamole_user ON guacamole_connection_group_permission.user_id = guacamole_user.user_id
|
||||
WHERE
|
||||
guacamole_connection_group_permission.user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = #{type,jdbcType=VARCHAR}
|
||||
AND connection_group_id = #{identifier,jdbcType=VARCHAR}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select identifiers accessible by the given user for the given permissions -->
|
||||
<select id="selectAccessibleIdentifiers" resultType="string">
|
||||
|
||||
SELECT DISTINCT connection_group_id
|
||||
FROM guacamole_connection_group_permission
|
||||
WHERE
|
||||
user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND connection_group_id IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
AND permission IN
|
||||
<foreach collection="permissions" item="permission"
|
||||
open="(" separator="," close=")">
|
||||
#{permission,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Delete all given permissions -->
|
||||
<delete id="delete" parameterType="org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionModel">
|
||||
|
||||
DELETE FROM guacamole_connection_group_permission
|
||||
WHERE (user_id, permission, connection_group_id) IN
|
||||
<foreach collection="permissions" item="permission"
|
||||
open="(" separator="," close=")">
|
||||
(#{permission.userID,jdbcType=INTEGER},
|
||||
#{permission.type,jdbcType=VARCHAR},
|
||||
#{permission.objectIdentifier,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
|
||||
</delete>
|
||||
|
||||
<!-- Insert all given permissions -->
|
||||
<insert id="insert" parameterType="org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionModel">
|
||||
|
||||
INSERT IGNORE INTO guacamole_connection_group_permission (
|
||||
user_id,
|
||||
permission,
|
||||
connection_group_id
|
||||
)
|
||||
VALUES
|
||||
<foreach collection="permissions" item="permission" separator=",">
|
||||
(#{permission.userID,jdbcType=INTEGER},
|
||||
#{permission.type,jdbcType=VARCHAR},
|
||||
#{permission.objectIdentifier,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
|
||||
</insert>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,120 @@
|
||||
<?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="org.glyptodon.guacamole.auth.jdbc.permission.ConnectionPermissionMapper" >
|
||||
|
||||
<!-- Result mapper for connection permissions -->
|
||||
<resultMap id="ConnectionPermissionResultMap" type="org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionModel">
|
||||
<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.ObjectPermission$Type"/>
|
||||
<result column="connection_id" property="objectIdentifier" jdbcType="INTEGER"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- Select all permissions for a given user -->
|
||||
<select id="select" resultMap="ConnectionPermissionResultMap">
|
||||
|
||||
SELECT
|
||||
guacamole_connection_permission.user_id,
|
||||
username,
|
||||
permission,
|
||||
connection_id
|
||||
FROM guacamole_connection_permission
|
||||
JOIN guacamole_user ON guacamole_connection_permission.user_id = guacamole_user.user_id
|
||||
WHERE guacamole_connection_permission.user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select the single permission matching the given criteria -->
|
||||
<select id="selectOne" resultMap="ConnectionPermissionResultMap">
|
||||
|
||||
SELECT
|
||||
guacamole_connection_permission.user_id,
|
||||
username,
|
||||
permission,
|
||||
connection_id
|
||||
FROM guacamole_connection_permission
|
||||
JOIN guacamole_user ON guacamole_connection_permission.user_id = guacamole_user.user_id
|
||||
WHERE
|
||||
guacamole_connection_permission.user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = #{type,jdbcType=VARCHAR}
|
||||
AND connection_id = #{identifier,jdbcType=VARCHAR}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select identifiers accessible by the given user for the given permissions -->
|
||||
<select id="selectAccessibleIdentifiers" resultType="string">
|
||||
|
||||
SELECT DISTINCT connection_id
|
||||
FROM guacamole_connection_permission
|
||||
WHERE
|
||||
user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND connection_id IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
AND permission IN
|
||||
<foreach collection="permissions" item="permission"
|
||||
open="(" separator="," close=")">
|
||||
#{permission,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Delete all given permissions -->
|
||||
<delete id="delete" parameterType="org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionModel">
|
||||
|
||||
DELETE FROM guacamole_connection_permission
|
||||
WHERE (user_id, permission, connection_id) IN
|
||||
<foreach collection="permissions" item="permission"
|
||||
open="(" separator="," close=")">
|
||||
(#{permission.userID,jdbcType=INTEGER},
|
||||
#{permission.type,jdbcType=VARCHAR},
|
||||
#{permission.objectIdentifier,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
|
||||
</delete>
|
||||
|
||||
<!-- Insert all given permissions -->
|
||||
<insert id="insert" parameterType="org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionModel">
|
||||
|
||||
INSERT IGNORE INTO guacamole_connection_permission (
|
||||
user_id,
|
||||
permission,
|
||||
connection_id
|
||||
)
|
||||
VALUES
|
||||
<foreach collection="permissions" item="permission" separator=",">
|
||||
(#{permission.userID,jdbcType=INTEGER},
|
||||
#{permission.type,jdbcType=VARCHAR},
|
||||
#{permission.objectIdentifier,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
|
||||
</insert>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,93 @@
|
||||
<?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="org.glyptodon.guacamole.auth.jdbc.permission.SystemPermissionMapper" >
|
||||
|
||||
<!-- Result mapper for system permissions -->
|
||||
<resultMap id="SystemPermissionResultMap" type="org.glyptodon.guacamole.auth.jdbc.permission.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.objectID,jdbcType=INTEGER}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select the single permission matching the given criteria -->
|
||||
<select id="selectOne" 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.objectID,jdbcType=INTEGER}
|
||||
AND permission = #{type,jdbcType=VARCHAR}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Delete all given permissions -->
|
||||
<delete id="delete" parameterType="org.glyptodon.guacamole.auth.jdbc.permission.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="org.glyptodon.guacamole.auth.jdbc.permission.SystemPermissionModel">
|
||||
|
||||
INSERT IGNORE INTO guacamole_system_permission (
|
||||
user_id,
|
||||
permission
|
||||
)
|
||||
VALUES
|
||||
<foreach collection="permissions" item="permission" separator=",">
|
||||
(#{permission.userID,jdbcType=INTEGER},
|
||||
#{permission.type,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
|
||||
</insert>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,129 @@
|
||||
<?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="org.glyptodon.guacamole.auth.jdbc.permission.UserPermissionMapper" >
|
||||
|
||||
<!-- Result mapper for user permissions -->
|
||||
<resultMap id="UserPermissionResultMap" type="org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionModel">
|
||||
<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.ObjectPermission$Type"/>
|
||||
<result column="affected_username" property="objectIdentifier" jdbcType="INTEGER"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- Select all permissions for a given user -->
|
||||
<select id="select" resultMap="UserPermissionResultMap">
|
||||
|
||||
SELECT
|
||||
guacamole_user_permission.user_id,
|
||||
guacamole_user.username,
|
||||
permission,
|
||||
affected.username AS affected_username
|
||||
FROM guacamole_user_permission
|
||||
JOIN guacamole_user ON guacamole_user_permission.user_id = guacamole_user.user_id
|
||||
JOIN guacamole_user affected ON guacamole_user_permission.affected_user_id = affected.user_id
|
||||
WHERE guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select the single permission matching the given criteria -->
|
||||
<select id="selectOne" resultMap="UserPermissionResultMap">
|
||||
|
||||
SELECT
|
||||
guacamole_user_permission.user_id,
|
||||
guacamole_user.username,
|
||||
permission,
|
||||
affected.username AS affected_username
|
||||
FROM guacamole_user_permission
|
||||
JOIN guacamole_user ON guacamole_user_permission.user_id = guacamole_user.user_id
|
||||
JOIN guacamole_user affected ON guacamole_user_permission.affected_user_id = affected.user_id
|
||||
WHERE
|
||||
guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = #{type,jdbcType=VARCHAR}
|
||||
AND affected.username = #{identifier,jdbcType=VARCHAR}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select identifiers accessible by the given user for the given permissions -->
|
||||
<select id="selectAccessibleIdentifiers" resultType="string">
|
||||
|
||||
SELECT DISTINCT username
|
||||
FROM guacamole_user_permission
|
||||
JOIN guacamole_user ON guacamole_user_permission.affected_user_id = guacamole_user.user_id
|
||||
WHERE
|
||||
guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND username IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
AND permission IN
|
||||
<foreach collection="permissions" item="permission"
|
||||
open="(" separator="," close=")">
|
||||
#{permission,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Delete all given permissions -->
|
||||
<delete id="delete" parameterType="org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionModel">
|
||||
|
||||
DELETE FROM guacamole_user_permission
|
||||
USING guacamole_user_permission
|
||||
JOIN guacamole_user affected ON guacamole_user_permission.affected_user_id = affected.user_id
|
||||
WHERE
|
||||
(guacamole_user_permission.user_id, permission, affected.username) IN
|
||||
<foreach collection="permissions" item="permission"
|
||||
open="(" separator="," close=")">
|
||||
(#{permission.userID,jdbcType=INTEGER},
|
||||
#{permission.type,jdbcType=VARCHAR},
|
||||
#{permission.objectIdentifier,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
|
||||
</delete>
|
||||
|
||||
<!-- Insert all given permissions -->
|
||||
<insert id="insert" parameterType="org.glyptodon.guacamole.auth.jdbc.permission.ObjectPermissionModel">
|
||||
|
||||
INSERT IGNORE INTO guacamole_user_permission (
|
||||
user_id,
|
||||
permission,
|
||||
affected_user_id
|
||||
)
|
||||
SELECT permissions.user_id, permissions.permission, guacamole_user.user_id FROM
|
||||
<foreach collection="permissions" item="permission"
|
||||
open="(" separator="UNION ALL" close=")">
|
||||
SELECT #{permission.userID,jdbcType=INTEGER} AS user_id,
|
||||
#{permission.type,jdbcType=VARCHAR} AS permission,
|
||||
#{permission.objectIdentifier,jdbcType=VARCHAR} AS username
|
||||
</foreach>
|
||||
AS permissions
|
||||
JOIN guacamole_user ON guacamole_user.username = permissions.username;
|
||||
|
||||
</insert>
|
||||
|
||||
</mapper>
|
@@ -0,0 +1,148 @@
|
||||
<?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="org.glyptodon.guacamole.auth.jdbc.user.UserMapper" >
|
||||
|
||||
<!-- Result mapper for user objects -->
|
||||
<resultMap id="UserResultMap" type="org.glyptodon.guacamole.auth.jdbc.user.UserModel" >
|
||||
<id column="user_id" property="objectID" jdbcType="INTEGER"/>
|
||||
<result column="username" property="identifier" jdbcType="VARCHAR"/>
|
||||
<result column="password_hash" property="passwordHash" jdbcType="BINARY"/>
|
||||
<result column="password_salt" property="passwordSalt" jdbcType="BINARY"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- Select all usernames -->
|
||||
<select id="selectIdentifiers" resultType="string">
|
||||
SELECT username
|
||||
FROM guacamole_user
|
||||
</select>
|
||||
|
||||
<!-- Select usernames of all readable users -->
|
||||
<select id="selectReadableIdentifiers" resultType="string">
|
||||
SELECT username
|
||||
FROM guacamole_user
|
||||
JOIN guacamole_user_permission ON affected_user_id = guacamole_user.user_id
|
||||
WHERE
|
||||
guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = 'read'
|
||||
</select>
|
||||
|
||||
<!-- Select multiple users by username -->
|
||||
<select id="select" resultMap="UserResultMap">
|
||||
|
||||
SELECT
|
||||
user_id,
|
||||
username,
|
||||
password_hash,
|
||||
password_salt
|
||||
FROM guacamole_user
|
||||
WHERE username IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select multiple users by username only if readable -->
|
||||
<select id="selectReadable" resultMap="UserResultMap">
|
||||
|
||||
SELECT
|
||||
guacamole_user.user_id,
|
||||
username,
|
||||
password_hash,
|
||||
password_salt
|
||||
FROM guacamole_user
|
||||
JOIN guacamole_user_permission ON affected_user_id = guacamole_user.user_id
|
||||
WHERE username IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
AND guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = 'read'
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Select single user by credentials -->
|
||||
<select id="selectOneByCredentials" resultMap="UserResultMap">
|
||||
SELECT
|
||||
user_id,
|
||||
username,
|
||||
password_hash,
|
||||
password_salt
|
||||
FROM guacamole_user
|
||||
WHERE
|
||||
username = #{username,jdbcType=VARCHAR}
|
||||
AND password_hash = UNHEX(SHA2(CONCAT(#{password,jdbcType=VARCHAR}, HEX(password_salt)), 256))
|
||||
</select>
|
||||
|
||||
<!-- Select single user by username -->
|
||||
<select id="selectOne" resultMap="UserResultMap">
|
||||
|
||||
SELECT
|
||||
user_id,
|
||||
username,
|
||||
password_hash,
|
||||
password_salt
|
||||
FROM guacamole_user
|
||||
WHERE
|
||||
username = #{identifier,jdbcType=VARCHAR}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Delete single user by username -->
|
||||
<delete id="delete">
|
||||
DELETE FROM guacamole_user
|
||||
WHERE username = #{identifier,jdbcType=VARCHAR}
|
||||
</delete>
|
||||
|
||||
<!-- Insert single user -->
|
||||
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
|
||||
parameterType="org.glyptodon.guacamole.auth.jdbc.user.UserModel">
|
||||
|
||||
INSERT INTO guacamole_user (
|
||||
username,
|
||||
password_hash,
|
||||
password_salt
|
||||
)
|
||||
VALUES (
|
||||
#{object.identifier,jdbcType=VARCHAR},
|
||||
#{object.passwordHash,jdbcType=BINARY},
|
||||
#{object.passwordSalt,jdbcType=BINARY}
|
||||
)
|
||||
|
||||
</insert>
|
||||
|
||||
<!-- Update single user -->
|
||||
<update id="update" parameterType="org.glyptodon.guacamole.auth.jdbc.user.UserModel">
|
||||
UPDATE guacamole_user
|
||||
SET password_hash = #{object.passwordHash,jdbcType=BINARY},
|
||||
password_salt = #{object.passwordSalt,jdbcType=BINARY}
|
||||
WHERE user_id = #{object.objectID,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
||||
</mapper>
|
71
extensions/guacamole-auth-jdbc/pom.xml
Normal file
71
extensions/guacamole-auth-jdbc/pom.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-auth-jdbc</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>0.9.5</version>
|
||||
<name>guacamole-auth-jdbc</name>
|
||||
<url>http://guac-dev.org/</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<modules>
|
||||
|
||||
<!-- Base JDBC classes -->
|
||||
<module>modules/guacamole-auth-jdbc-base</module>
|
||||
|
||||
<!-- MySQL authentication -->
|
||||
<module>modules/guacamole-auth-jdbc-mysql</module>
|
||||
|
||||
</modules>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<!-- Assembly plugin - for easy distribution -->
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.2-beta-5</version>
|
||||
<inherited>false</inherited>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-dist-archive</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/dist.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<!-- Guacamole Extension API -->
|
||||
<dependency>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-ext</artifactId>
|
||||
<version>0.9.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
</project>
|
32
extensions/guacamole-auth-jdbc/src/main/assembly/dist.xml
Normal file
32
extensions/guacamole-auth-jdbc/src/main/assembly/dist.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<assembly
|
||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||
|
||||
<id>dist</id>
|
||||
<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
|
||||
|
||||
<!-- Output tar.gz -->
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
</formats>
|
||||
|
||||
<!-- Include all implementations -->
|
||||
<fileSets>
|
||||
|
||||
<!-- MySQL implementation -->
|
||||
<fileSet>
|
||||
<outputDirectory>/mysql/schema</outputDirectory>
|
||||
<directory>modules/guacamole-auth-jdbc-mysql/schema</directory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>modules/guacamole-auth-jdbc-mysql/target/extension</directory>
|
||||
<outputDirectory>/mysql</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
|
||||
</fileSets>
|
||||
|
||||
</assembly>
|
@@ -1,171 +0,0 @@
|
||||
|
||||
------------------------------------------------------------
|
||||
About this README
|
||||
------------------------------------------------------------
|
||||
|
||||
This README is intended to provide quick and to-the-point documentation for
|
||||
technical users intending to compile parts of Guacamole themselves.
|
||||
|
||||
Distribution-specific packages are available from the files section of the main
|
||||
project page:
|
||||
|
||||
http://sourceforge.net/projects/guacamole/files/
|
||||
|
||||
Distribution-specific documentation is provided on the Guacamole wiki:
|
||||
|
||||
http://guac-dev.org/
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
What is guacamole-auth-mysql?
|
||||
------------------------------------------------------------
|
||||
|
||||
guacamole-auth-ldap is a Java library for use with the Guacamole web
|
||||
application to provide MySQL based authentication.
|
||||
|
||||
guacamole-auth-mysql provides an authentication provider which can be
|
||||
set in guacamole.properties to allow MySQL authentication of Guacamole
|
||||
users. Additional properties are required to configure the mysql
|
||||
connection parameters.
|
||||
|
||||
A schema file are provided to create the required tables in your
|
||||
mysql database.
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
Compiling and installing guacamole-auth-mysql
|
||||
------------------------------------------------------------
|
||||
|
||||
guacamole-auth-mysql is built using Maven. Building guacamole-auth-mysql
|
||||
compiles all classes and packages them into a redistributable .jar file. This
|
||||
.jar file can be installed in the library directory configured in
|
||||
guacamole.properties such that the authentication provider is available.
|
||||
|
||||
1) Set up a MySQL database with the Guacamole schema.
|
||||
|
||||
When guacamole-auth-mysql is compiling, it needs to generate source
|
||||
based on a database schema. Because the source generator uses a
|
||||
connection to an actual database to do this, you must have a MySQL
|
||||
database running with the Guacamole schema set up.
|
||||
|
||||
First, create a database. For the sake of these instructions, we will
|
||||
call the database "guacamole", and will run all scripts as the root user:
|
||||
|
||||
$ mysql -u root -p
|
||||
Enter password:
|
||||
mysql> CREATE DATABASE guacamole;
|
||||
Query OK, 1 row affected (0.00 sec)
|
||||
|
||||
mysql> exit
|
||||
Bye
|
||||
|
||||
The schema files are in the schema/ subdirectory of the source. If run
|
||||
in order, they will create the schema and a default user:
|
||||
|
||||
$ cat schema/*.sql | mysql -u root -p guacamole
|
||||
|
||||
2) Set up your ~/.m2/settings.xml
|
||||
|
||||
Once the database is set up, Maven will need to have the credentials
|
||||
required to connect to it and query the schema. This information is
|
||||
specified in properties inside your ~/.m2/settings.xml file. If this
|
||||
file does not exist yet, simply create it.
|
||||
|
||||
For ease of compilation, we've included an example settings.xml
|
||||
defining the required properties in doc/example/settings.xml. You can
|
||||
simply copy this file into ~/.m2 and edit as necessary.
|
||||
|
||||
If you wish to write the file yourself, the file should look like this in
|
||||
general:
|
||||
|
||||
<settings>
|
||||
<profiles>
|
||||
...profiles...
|
||||
</profiles>
|
||||
</settings>
|
||||
|
||||
We need to add a profile which defines the required properties by
|
||||
placing a section like the following within the "profiles" section of your
|
||||
settings.xml:
|
||||
|
||||
<profile>
|
||||
<id>guacamole-mybatis</id>
|
||||
<properties>
|
||||
<guacamole.database.catalog>DATABASE</guacamole.database.catalog>
|
||||
<guacamole.database.user>USERNAME</guacamole.database.user>
|
||||
<guacamole.database.password>PASSWORD</guacamole.database.password>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
Obviously, the DATABASE, USERNAME, and PASSWORD placeholders above must
|
||||
be replaced with the appropriate values for your system.
|
||||
|
||||
Finally, to make the profile available to the build, it must be activated.
|
||||
Place a section like the following at the bottom of your settings.xml,
|
||||
right after the profiles section:
|
||||
|
||||
<activeProfiles>
|
||||
<activeProfile>guacamole-mybatis</activeProfile>
|
||||
</activeProfiles>
|
||||
|
||||
Maven's documentation has more details on writing the settings.xml file
|
||||
if you have different needs or the above directions are not clear.
|
||||
|
||||
3) Run mvn package
|
||||
|
||||
$ mvn package
|
||||
|
||||
Maven will download any needed dependencies for building the .jar file.
|
||||
Once all dependencies have been downloaded, the .jar file will be
|
||||
created in the target/ subdirectory of the current directory.
|
||||
|
||||
If this process fails, check the build errors, and verify that the
|
||||
contents of your settings.xml file is correct.
|
||||
|
||||
4) Extract the .tar.gz file now present in the target/ directory, and
|
||||
place the .jar files in the extracted lib/ subdirectory in the library
|
||||
directory specified in guacamole.properties.
|
||||
|
||||
You will likely need to do this as root.
|
||||
|
||||
If you do not have a library directory configured in your
|
||||
guacamole.properties, you will need to specify one. The directory
|
||||
is specified using the "lib-directory" property.
|
||||
|
||||
5) Set up your MySQL database to authenticate Guacamole users
|
||||
|
||||
A schema file is provided in the schema directory for creating
|
||||
the guacamole authentication tables in your MySQL database.
|
||||
|
||||
Additionally, a script is provided to create a default admin user
|
||||
with username 'guacadmin' and password 'guacadmin'. This user can
|
||||
be used to set up any other connections and users.
|
||||
|
||||
6) Configure guacamole.properties for MySQL
|
||||
|
||||
There are additional properties required by the MySQL JDBC driver
|
||||
which must be added/changed in your guacamole.properties:
|
||||
|
||||
# Configuration for MySQL connection
|
||||
mysql-hostname: mysql.host.name
|
||||
mysql-port: 3306
|
||||
mysql-database: guacamole.database.name
|
||||
mysql-username: user
|
||||
mysql-password: pass
|
||||
|
||||
Optionally, the authentication provider can be configured
|
||||
not to allow multiple users to use the same connection
|
||||
at the same time:
|
||||
|
||||
mysql-disallow-simultaneous-connections: true
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
Reporting problems
|
||||
------------------------------------------------------------
|
||||
|
||||
Please report any bugs encountered by opening a new ticket at the Trac system
|
||||
hosted at:
|
||||
|
||||
http://guac-dev.org/trac/
|
||||
|
@@ -1,21 +0,0 @@
|
||||
<settings>
|
||||
|
||||
<!-- Profile defining the properties required for a MyBatis build -->
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>guacamole-mybatis</id>
|
||||
<properties>
|
||||
<guacamole.database.catalog>SCHEMA</guacamole.database.catalog>
|
||||
<guacamole.database.schema>DATABASE</guacamole.database.schema>
|
||||
<guacamole.database.user>USER</guacamole.database.user>
|
||||
<guacamole.database.password>PASS</guacamole.database.password>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<!-- Activate by default -->
|
||||
<activeProfiles>
|
||||
<activeProfile>guacamole-mybatis</activeProfile>
|
||||
</activeProfiles>
|
||||
|
||||
</settings>
|
@@ -1,125 +0,0 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-auth-mysql</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<version>0.9.5</version>
|
||||
<name>guacamole-auth-mysql</name>
|
||||
<url>http://guac-dev.org/</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<!-- Written for 1.6 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Assembly plugin - for easy distribution -->
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.2-beta-5</version>
|
||||
<configuration>
|
||||
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/dist.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-dist-archive</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- MyBatis Generator plugin -->
|
||||
<plugin>
|
||||
<groupId>org.mybatis.generator</groupId>
|
||||
<artifactId>mybatis-generator-maven-plugin</artifactId>
|
||||
<version>1.3.2</version>
|
||||
|
||||
<executions>
|
||||
<execution>
|
||||
<id>Generate MyBatis Artifacts</id>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
|
||||
<!-- MySQL Connector -->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>5.1.23</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Guacamole Java API -->
|
||||
<dependency>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-common</artifactId>
|
||||
<version>0.9.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Guacamole Extension API -->
|
||||
<dependency>
|
||||
<groupId>org.glyptodon.guacamole</groupId>
|
||||
<artifactId>guacamole-ext</artifactId>
|
||||
<version>0.9.5</version>
|
||||
</dependency>
|
||||
|
||||
<!-- SLF4J - logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.7</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MyBatis -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
<version>3.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MyBatis Guice -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-guice</artifactId>
|
||||
<version>3.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Google Collections -->
|
||||
<dependency>
|
||||
<groupId>com.google.collections</groupId>
|
||||
<artifactId>google-collections</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -1,54 +0,0 @@
|
||||
<assembly
|
||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||
|
||||
<id>dist</id>
|
||||
<baseDirectory>${project.artifactId}-${project.version}</baseDirectory>
|
||||
|
||||
<!-- Output tar.gz -->
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
</formats>
|
||||
|
||||
<!-- Include docs and schema -->
|
||||
<fileSets>
|
||||
|
||||
<!-- Include docs -->
|
||||
<fileSet>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<directory>doc</directory>
|
||||
</fileSet>
|
||||
|
||||
<!-- Include schema -->
|
||||
<fileSet>
|
||||
<outputDirectory>/schema</outputDirectory>
|
||||
<directory>schema</directory>
|
||||
</fileSet>
|
||||
|
||||
</fileSets>
|
||||
|
||||
<!-- Include self and all dependencies except guacamole-common
|
||||
and guacamole-ext -->
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
|
||||
<outputDirectory>/lib</outputDirectory>
|
||||
<scope>runtime</scope>
|
||||
<unpack>false</unpack>
|
||||
<useProjectArtifact>true</useProjectArtifact>
|
||||
<useTransitiveFiltering>true</useTransitiveFiltering>
|
||||
|
||||
<excludes>
|
||||
|
||||
<!-- Do not include guacamole-common -->
|
||||
<exclude>org.glyptodon.guacamole:guacamole-common</exclude>
|
||||
|
||||
<!-- Do not include guacamole-ext -->
|
||||
<exclude>org.glyptodon.guacamole:guacamole-ext</exclude>
|
||||
|
||||
</excludes>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
|
||||
</assembly>
|
@@ -1,502 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionHistoryMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionHistory;
|
||||
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
||||
|
||||
/**
|
||||
* Represents the map of currently active Connections to the count of the number
|
||||
* of current users. Whenever a socket is opened, the connection count should be
|
||||
* incremented, and whenever a socket is closed, the connection count should be
|
||||
* decremented.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class ActiveConnectionMap {
|
||||
|
||||
/**
|
||||
* Represents the count of users currently using a MySQL connection.
|
||||
*/
|
||||
public class Connection {
|
||||
|
||||
/**
|
||||
* The ID of the MySQL connection that this Connection represents.
|
||||
*/
|
||||
private int connectionID;
|
||||
|
||||
/**
|
||||
* The number of users currently using this connection.
|
||||
*/
|
||||
private int currentUserCount;
|
||||
|
||||
/**
|
||||
* Returns the ID of the MySQL connection that this Connection
|
||||
* represents.
|
||||
*
|
||||
* @return the ID of the MySQL connection that this Connection
|
||||
* represents.
|
||||
*/
|
||||
public int getConnectionID() {
|
||||
return connectionID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of users currently using this connection.
|
||||
*
|
||||
* @return the number of users currently using this connection.
|
||||
*/
|
||||
public int getCurrentUserCount() {
|
||||
return currentUserCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current user count for this connection.
|
||||
*
|
||||
* @param currentUserCount The new user count for this Connection.
|
||||
*/
|
||||
public void setCurrentUserCount(int currentUserCount) {
|
||||
this.currentUserCount = currentUserCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Connection for the given connectionID with a zero
|
||||
* current user count.
|
||||
*
|
||||
* @param connectionID The ID of the MySQL connection that this
|
||||
* Connection represents.
|
||||
*/
|
||||
public Connection(int connectionID) {
|
||||
this.connectionID = connectionID;
|
||||
this.currentUserCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Represents a user connected to a connection or BALANCING connection group.
|
||||
*/
|
||||
public class ConnectionUser {
|
||||
/**
|
||||
* The ID of the connection or connection group that this ConnectionUser refers to.
|
||||
*/
|
||||
private int identifier;
|
||||
|
||||
/**
|
||||
* The user that this ConnectionUser refers to.
|
||||
*/
|
||||
private int userID;
|
||||
|
||||
/**
|
||||
* Returns ID of the connection or connection group that this ConnectionUser refers to.
|
||||
* @return ID of the connection or connection group that this ConnectionUser refers to.
|
||||
*/
|
||||
public int getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user ID that this ConnectionUser refers to.
|
||||
* @return the user ID that this ConnectionUser refers to.
|
||||
*/
|
||||
public int getUserID() {
|
||||
return userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ConnectionUser with the given connection or connection group
|
||||
* ID and user ID.
|
||||
*
|
||||
* @param identifier The connection or connection group ID that this
|
||||
* ConnectionUser refers to.
|
||||
* @param userID The user ID that this ConnectionUser refers to.
|
||||
*/
|
||||
public ConnectionUser(int identifier, int userID) {
|
||||
this.identifier = identifier;
|
||||
this.userID = userID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
|
||||
// Only another ConnectionUser can equal this ConnectionUser
|
||||
if(!(other instanceof ConnectionUser))
|
||||
return false;
|
||||
|
||||
ConnectionUser otherConnectionGroupUser =
|
||||
(ConnectionUser)other;
|
||||
|
||||
/*
|
||||
* Two ConnectionGroupUsers are equal iff they represent the exact
|
||||
* same pairing of connection or connection group and user.
|
||||
*/
|
||||
return this.identifier == otherConnectionGroupUser.identifier
|
||||
&& this.userID == otherConnectionGroupUser.userID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 23 * hash + this.identifier;
|
||||
hash = 23 * hash + this.userID;
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DAO for accessing connection history.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionHistoryMapper connectionHistoryDAO;
|
||||
|
||||
/**
|
||||
* Map of all the connections that are currently active to the
|
||||
* count of current users.
|
||||
*/
|
||||
private Map<Integer, Connection> activeConnectionMap =
|
||||
new HashMap<Integer, Connection>();
|
||||
|
||||
/**
|
||||
* Map of all the connection group users to the count of current usages.
|
||||
*/
|
||||
private Map<ConnectionUser, Integer> activeConnectionGroupUserMap =
|
||||
new HashMap<ConnectionUser, Integer>();
|
||||
|
||||
/**
|
||||
* Map of all the connection users to the count of current usages.
|
||||
*/
|
||||
private Map<ConnectionUser, Integer> activeConnectionUserMap =
|
||||
new HashMap<ConnectionUser, Integer>();
|
||||
|
||||
/**
|
||||
* Returns the number of connections opened by the given user using
|
||||
* the given ConnectionGroup.
|
||||
*
|
||||
* @param connectionGroupID The connection group ID that this
|
||||
* ConnectionUser refers to.
|
||||
* @param userID The user ID that this ConnectionUser refers to.
|
||||
*
|
||||
* @return The number of connections opened by the given user to the given
|
||||
* ConnectionGroup.
|
||||
*/
|
||||
public int getConnectionGroupUserCount(int connectionGroupID, int userID) {
|
||||
Integer count = activeConnectionGroupUserMap.get
|
||||
(new ConnectionUser(connectionGroupID, userID));
|
||||
|
||||
// No ConnectionUser found means this combination was never used
|
||||
if(count == null)
|
||||
return 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given user is currently connected to the given BALANCING
|
||||
* connection group.
|
||||
*
|
||||
* @param connectionGroupID The connection group ID that this
|
||||
* ConnectionUser refers to.
|
||||
* @param userID The user ID that this ConnectionUser refers to.
|
||||
*
|
||||
* @return True if the given user is currently connected to the given
|
||||
* BALANCING connection group, false otherwise.
|
||||
*/
|
||||
public boolean isConnectionGroupUserActive(int connectionGroupID, int userID) {
|
||||
Integer count = activeConnectionGroupUserMap.get
|
||||
(new ConnectionUser(connectionGroupID, userID));
|
||||
|
||||
// The connection group is in use if the ConnectionUser count > 0
|
||||
return count != null && count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the count of the number of connections opened by the given user
|
||||
* to the given ConnectionGroup.
|
||||
*
|
||||
* @param connectionGroupID The connection group ID that this
|
||||
* ConnectionUser refers to.
|
||||
* @param userID The user ID that this ConnectionUser refers to.
|
||||
*/
|
||||
private void incrementConnectionGroupUserCount(int connectionGroupID, int userID) {
|
||||
int currentCount = getConnectionGroupUserCount(connectionGroupID, userID);
|
||||
|
||||
activeConnectionGroupUserMap.put
|
||||
(new ConnectionUser(connectionGroupID, userID), currentCount + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the count of the number of connections opened by the given user
|
||||
* to the given ConnectionGroup.
|
||||
*
|
||||
* @param connectionGroupID The connection group ID that this
|
||||
* ConnectionUser refers to.
|
||||
* @param userID The user ID that this ConnectionUser refers to.
|
||||
*/
|
||||
private void decrementConnectionGroupUserCount(int connectionGroupID, int userID) {
|
||||
int currentCount = getConnectionGroupUserCount(connectionGroupID, userID);
|
||||
|
||||
activeConnectionGroupUserMap.put
|
||||
(new ConnectionUser(connectionGroupID, userID), currentCount - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of connections opened by the given user using
|
||||
* the given Connection.
|
||||
*
|
||||
* @param connectionID The connection ID that this ConnectionUser refers to.
|
||||
* @param userID The user ID that this ConnectionUser refers to.
|
||||
*
|
||||
* @return The number of connections opened by the given user to the given
|
||||
* connection.
|
||||
*/
|
||||
public int getConnectionUserCount(int connectionID, int userID) {
|
||||
Integer count = activeConnectionUserMap.get
|
||||
(new ConnectionUser(connectionID, userID));
|
||||
|
||||
// No ConnectionUser found means this combination was never used
|
||||
if(count == null)
|
||||
return 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given user is currently connected to the given connection.
|
||||
*
|
||||
* @param connectionID The connection ID that this ConnectionUser refers to.
|
||||
* @param userID The user ID that this ConnectionUser refers to.
|
||||
*
|
||||
* @return True if the given user is currently connected to the given
|
||||
* connection, false otherwise.
|
||||
*/
|
||||
public boolean isConnectionUserActive(int connectionID, int userID) {
|
||||
Integer count = activeConnectionUserMap.get
|
||||
(new ConnectionUser(connectionID, userID));
|
||||
|
||||
// The connection is in use if the ConnectionUser count > 0
|
||||
return count != null && count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the count of the number of connections opened by the given user
|
||||
* to the given Connection.
|
||||
*
|
||||
* @param connectionID The connection ID that this ConnectionUser refers to.
|
||||
* @param userID The user ID that this ConnectionUser refers to.
|
||||
*/
|
||||
private void incrementConnectionUserCount(int connectionID, int userID) {
|
||||
int currentCount = getConnectionUserCount(connectionID, userID);
|
||||
|
||||
activeConnectionUserMap.put
|
||||
(new ConnectionUser(connectionID, userID), currentCount + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the count of the number of connections opened by the given user
|
||||
* to the given Connection.
|
||||
*
|
||||
* @param connectionID The connection ID that this ConnectionUser refers to.
|
||||
* @param userID The user ID that this ConnectionUser refers to.
|
||||
*/
|
||||
private void decrementConnectionUserCount(int connectionID, int userID) {
|
||||
int currentCount = getConnectionUserCount(connectionID, userID);
|
||||
|
||||
activeConnectionUserMap.put
|
||||
(new ConnectionUser(connectionID, userID), currentCount - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the connection with the lowest number of current
|
||||
* active users, if found.
|
||||
*
|
||||
* @param connectionIDs The subset of connection IDs to find the least
|
||||
* used connection within.
|
||||
*
|
||||
* @return The ID of the connection with the lowest number of current
|
||||
* active users, if found.
|
||||
*/
|
||||
public Integer getLeastUsedConnection(Collection<Integer> connectionIDs) {
|
||||
|
||||
if(connectionIDs.isEmpty())
|
||||
return null;
|
||||
|
||||
int minUserCount = Integer.MAX_VALUE;
|
||||
Integer minConnectionID = null;
|
||||
|
||||
for(Integer connectionID : connectionIDs) {
|
||||
Connection connection = activeConnectionMap.get(connectionID);
|
||||
|
||||
/*
|
||||
* If the connection is not found in the map, it has not been used,
|
||||
* and therefore will be count 0.
|
||||
*/
|
||||
if(connection == null) {
|
||||
minUserCount = 0;
|
||||
minConnectionID = connectionID;
|
||||
}
|
||||
// If this is the least active connection
|
||||
else if(connection.getCurrentUserCount() < minUserCount) {
|
||||
minUserCount = connection.getCurrentUserCount();
|
||||
minConnectionID = connection.getConnectionID();
|
||||
}
|
||||
}
|
||||
|
||||
return minConnectionID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the count of currently active users for the given connectionID.
|
||||
* @return the count of currently active users for the given connectionID.
|
||||
*/
|
||||
public int getCurrentUserCount(int connectionID) {
|
||||
Connection connection = activeConnectionMap.get(connectionID);
|
||||
|
||||
if(connection == null)
|
||||
return 0;
|
||||
|
||||
return connection.getCurrentUserCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement the current user count for this Connection.
|
||||
*
|
||||
* @param connectionID The ID of the MySQL connection that this
|
||||
* Connection represents.
|
||||
*
|
||||
* @throws GuacamoleException If the connection is not found.
|
||||
*/
|
||||
private void decrementUserCount(int connectionID)
|
||||
throws GuacamoleException {
|
||||
Connection connection = activeConnectionMap.get(connectionID);
|
||||
|
||||
if(connection == null)
|
||||
throw new GuacamoleResourceNotFoundException
|
||||
("Connection to decrement does not exist.");
|
||||
|
||||
// Decrement the current user count
|
||||
connection.setCurrentUserCount(connection.getCurrentUserCount() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the current user count for this Connection.
|
||||
*
|
||||
* @param connectionID The ID of the MySQL connection that this
|
||||
* Connection represents.
|
||||
*
|
||||
* @throws GuacamoleException If the connection is not found.
|
||||
*/
|
||||
private void incrementUserCount(int connectionID) {
|
||||
Connection connection = activeConnectionMap.get(connectionID);
|
||||
|
||||
// If the Connection does not exist, it should be created
|
||||
if(connection == null) {
|
||||
connection = new Connection(connectionID);
|
||||
activeConnectionMap.put(connectionID, connection);
|
||||
}
|
||||
|
||||
// Increment the current user count
|
||||
connection.setCurrentUserCount(connection.getCurrentUserCount() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a connection is currently in use.
|
||||
* @param connectionID The connection to check the status of.
|
||||
* @return true if the connection is currently in use.
|
||||
*/
|
||||
public boolean isActive(int connectionID) {
|
||||
return getCurrentUserCount(connectionID) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a connection as open.
|
||||
* @param connectionID The ID of the connection that is being opened.
|
||||
* @param userID The ID of the user who is opening the connection.
|
||||
* @param connectionGroupID The ID of the BALANCING connection group that is
|
||||
* being connected to; null if not used.
|
||||
* @return The ID of the history record created for this open connection.
|
||||
*/
|
||||
public int openConnection(int connectionID, int userID, Integer connectionGroupID) {
|
||||
|
||||
// Create the connection history record
|
||||
ConnectionHistory connectionHistory = new ConnectionHistory();
|
||||
connectionHistory.setConnection_id(connectionID);
|
||||
connectionHistory.setUser_id(userID);
|
||||
connectionHistory.setStart_date(new Date());
|
||||
connectionHistoryDAO.insert(connectionHistory);
|
||||
|
||||
// Increment the user count
|
||||
incrementUserCount(connectionID);
|
||||
|
||||
// Increment the connection user count
|
||||
incrementConnectionUserCount(connectionID, userID);
|
||||
|
||||
// If this is a connection to a BALANCING ConnectionGroup, increment the count
|
||||
if(connectionGroupID != null)
|
||||
incrementConnectionGroupUserCount(connectionGroupID, userID);
|
||||
|
||||
return connectionHistory.getHistory_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a connection as closed.
|
||||
* @param historyID The ID of the history record about the open connection.
|
||||
* @param connectionGroupID The ID of the BALANCING connection group that is
|
||||
* being connected to; null if not used.
|
||||
* @throws GuacamoleException If the open connection history is not found.
|
||||
*/
|
||||
public void closeConnection(int historyID, Integer connectionGroupID)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Get the existing history record
|
||||
ConnectionHistory connectionHistory =
|
||||
connectionHistoryDAO.selectByPrimaryKey(historyID);
|
||||
|
||||
if(connectionHistory == null)
|
||||
throw new GuacamoleResourceNotFoundException("History record not found.");
|
||||
|
||||
// Get the connection and user IDs
|
||||
int connectionID = connectionHistory.getConnection_id();
|
||||
int userID = connectionHistory.getUser_id();
|
||||
|
||||
// Update the connection history record to mark that it is now closed
|
||||
connectionHistory.setEnd_date(new Date());
|
||||
connectionHistoryDAO.updateByPrimaryKey(connectionHistory);
|
||||
|
||||
// Decrement the user count.
|
||||
decrementUserCount(connectionID);
|
||||
|
||||
// Decrement the connection user count
|
||||
decrementConnectionUserCount(connectionID, userID);
|
||||
|
||||
// If this is a connection to a BALANCING ConnectionGroup, decrement the count
|
||||
if(connectionGroupID != null)
|
||||
decrementConnectionGroupUserCount(connectionGroupID, userID);
|
||||
}
|
||||
}
|
@@ -1,336 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionParameterMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameter;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionParameterExample;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionPermissionKey;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionGroupService;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService;
|
||||
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
||||
import org.glyptodon.guacamole.GuacamoleUnsupportedException;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
|
||||
import org.mybatis.guice.transactional.Transactional;
|
||||
|
||||
/**
|
||||
* A MySQL-based implementation of the connection directory.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class ConnectionDirectory implements Directory<String, Connection>{
|
||||
|
||||
/**
|
||||
* The user who this connection directory belongs to. Access is based on
|
||||
* his/her permission settings.
|
||||
*/
|
||||
private AuthenticatedUser currentUser;
|
||||
|
||||
/**
|
||||
* The ID of the parent connection group.
|
||||
*/
|
||||
private Integer parentID;
|
||||
|
||||
/**
|
||||
* Service for checking permissions.
|
||||
*/
|
||||
@Inject
|
||||
private PermissionCheckService permissionCheckService;
|
||||
|
||||
/**
|
||||
* Service managing connections.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionService connectionService;
|
||||
|
||||
/**
|
||||
* Service managing connection groups.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupService connectionGroupService;
|
||||
|
||||
/**
|
||||
* Service for manipulating connection permissions in the database.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionPermissionMapper connectionPermissionDAO;
|
||||
|
||||
/**
|
||||
* Service for manipulating connection parameters in the database.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionParameterMapper connectionParameterDAO;
|
||||
|
||||
/**
|
||||
* Set the user and parentID for this directory.
|
||||
*
|
||||
* @param currentUser
|
||||
* The user owning this connection directory.
|
||||
*
|
||||
* @param parentID
|
||||
* The ID of the parent connection group.
|
||||
*/
|
||||
public void init(AuthenticatedUser currentUser, Integer parentID) {
|
||||
this.currentUser = currentUser;
|
||||
this.parentID = parentID;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Connection get(String identifier) throws GuacamoleException {
|
||||
|
||||
// Get connection
|
||||
MySQLConnection connection =
|
||||
connectionService.retrieveConnection(identifier, currentUser);
|
||||
|
||||
if(connection == null)
|
||||
return null;
|
||||
|
||||
// Verify permission to use the parent connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(connection.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
// Verify access is granted
|
||||
permissionCheckService.verifyConnectionAccess(
|
||||
currentUser,
|
||||
connection.getConnectionID(),
|
||||
MySQLConstants.CONNECTION_READ);
|
||||
|
||||
// Return connection
|
||||
return connection;
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Set<String> getIdentifiers() throws GuacamoleException {
|
||||
|
||||
// Verify permission to use the connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(parentID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
return permissionCheckService.retrieveConnectionIdentifiers(currentUser,
|
||||
parentID, MySQLConstants.CONNECTION_READ);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void add(Connection object) throws GuacamoleException {
|
||||
|
||||
String name = object.getName().trim();
|
||||
if(name.isEmpty())
|
||||
throw new GuacamoleClientException("The connection name cannot be blank.");
|
||||
|
||||
// Verify permission to create
|
||||
permissionCheckService.verifySystemAccess(currentUser,
|
||||
MySQLConstants.SYSTEM_CONNECTION_CREATE);
|
||||
|
||||
// Verify permission to edit the connection group
|
||||
permissionCheckService.verifyConnectionGroupAccess(currentUser,
|
||||
this.parentID, MySQLConstants.CONNECTION_GROUP_UPDATE);
|
||||
|
||||
// Verify permission to use the connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(parentID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
// Verify that no connection already exists with this name.
|
||||
MySQLConnection previousConnection =
|
||||
connectionService.retrieveConnection(name, parentID, currentUser);
|
||||
if(previousConnection != null)
|
||||
throw new GuacamoleClientException("That connection name is already in use.");
|
||||
|
||||
// Create connection
|
||||
MySQLConnection connection = connectionService.createConnection(
|
||||
name, object.getConfiguration().getProtocol(), currentUser, parentID);
|
||||
|
||||
// Set the connection ID
|
||||
object.setIdentifier(connection.getIdentifier());
|
||||
|
||||
// Add connection parameters
|
||||
createConfigurationValues(connection.getConnectionID(),
|
||||
object.getConfiguration());
|
||||
|
||||
// Finally, give the current user full access to the newly created
|
||||
// connection.
|
||||
ConnectionPermissionKey newConnectionPermission = new ConnectionPermissionKey();
|
||||
newConnectionPermission.setUser_id(currentUser.getUserID());
|
||||
newConnectionPermission.setConnection_id(connection.getConnectionID());
|
||||
|
||||
// Read permission
|
||||
newConnectionPermission.setPermission(MySQLConstants.CONNECTION_READ);
|
||||
connectionPermissionDAO.insert(newConnectionPermission);
|
||||
|
||||
// Update permission
|
||||
newConnectionPermission.setPermission(MySQLConstants.CONNECTION_UPDATE);
|
||||
connectionPermissionDAO.insert(newConnectionPermission);
|
||||
|
||||
// Delete permission
|
||||
newConnectionPermission.setPermission(MySQLConstants.CONNECTION_DELETE);
|
||||
connectionPermissionDAO.insert(newConnectionPermission);
|
||||
|
||||
// Administer permission
|
||||
newConnectionPermission.setPermission(MySQLConstants.CONNECTION_ADMINISTER);
|
||||
connectionPermissionDAO.insert(newConnectionPermission);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all parameter values from the given configuration into the
|
||||
* database, associating them with the connection having the givenID.
|
||||
*
|
||||
* @param connection_id The ID of the connection to associate all
|
||||
* parameters with.
|
||||
* @param config The GuacamoleConfiguration to read parameters from.
|
||||
*/
|
||||
private void createConfigurationValues(int connection_id,
|
||||
GuacamoleConfiguration config) {
|
||||
|
||||
// Insert new parameters for each parameter in the config
|
||||
for (String name : config.getParameterNames()) {
|
||||
|
||||
// Create a ConnectionParameter based on the current parameter
|
||||
ConnectionParameter parameter = new ConnectionParameter();
|
||||
parameter.setConnection_id(connection_id);
|
||||
parameter.setParameter_name(name);
|
||||
parameter.setParameter_value(config.getParameter(name));
|
||||
|
||||
// Insert connection parameter
|
||||
connectionParameterDAO.insert(parameter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void update(Connection object) throws GuacamoleException {
|
||||
|
||||
// If connection not actually from this auth provider, we can't handle
|
||||
// the update
|
||||
if (!(object instanceof MySQLConnection))
|
||||
throw new GuacamoleUnsupportedException("Connection not from database.");
|
||||
|
||||
MySQLConnection mySQLConnection = (MySQLConnection) object;
|
||||
|
||||
// Verify permission to update
|
||||
permissionCheckService.verifyConnectionAccess(currentUser,
|
||||
mySQLConnection.getConnectionID(),
|
||||
MySQLConstants.CONNECTION_UPDATE);
|
||||
|
||||
// Perform update
|
||||
connectionService.updateConnection(mySQLConnection);
|
||||
|
||||
// Delete old connection parameters
|
||||
ConnectionParameterExample parameterExample = new ConnectionParameterExample();
|
||||
parameterExample.createCriteria().andConnection_idEqualTo(mySQLConnection.getConnectionID());
|
||||
connectionParameterDAO.deleteByExample(parameterExample);
|
||||
|
||||
// Add connection parameters
|
||||
createConfigurationValues(mySQLConnection.getConnectionID(),
|
||||
object.getConfiguration());
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void remove(String identifier) throws GuacamoleException {
|
||||
|
||||
// Get connection
|
||||
MySQLConnection mySQLConnection =
|
||||
connectionService.retrieveConnection(identifier, currentUser);
|
||||
|
||||
if(mySQLConnection == null)
|
||||
throw new GuacamoleResourceNotFoundException("Connection not found.");
|
||||
|
||||
// Verify permission to use the parent connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(mySQLConnection.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
// Verify permission to delete
|
||||
permissionCheckService.verifyConnectionAccess(currentUser,
|
||||
mySQLConnection.getConnectionID(),
|
||||
MySQLConstants.CONNECTION_DELETE);
|
||||
|
||||
// Delete the connection itself
|
||||
connectionService.deleteConnection(mySQLConnection.getConnectionID());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(String identifier, Directory<String, Connection> directory)
|
||||
throws GuacamoleException {
|
||||
|
||||
if(!(directory instanceof ConnectionDirectory))
|
||||
throw new GuacamoleUnsupportedException("Directory not from database");
|
||||
|
||||
Integer toConnectionGroupID = ((ConnectionDirectory)directory).parentID;
|
||||
|
||||
// Get connection
|
||||
MySQLConnection mySQLConnection =
|
||||
connectionService.retrieveConnection(identifier, currentUser);
|
||||
|
||||
if(mySQLConnection == null)
|
||||
throw new GuacamoleResourceNotFoundException("Connection not found.");
|
||||
|
||||
// Verify permission to update the connection
|
||||
permissionCheckService.verifyConnectionAccess(currentUser,
|
||||
mySQLConnection.getConnectionID(),
|
||||
MySQLConstants.CONNECTION_UPDATE);
|
||||
|
||||
// Verify permission to use the from connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(mySQLConnection.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
// Verify permission to update the from connection group
|
||||
permissionCheckService.verifyConnectionGroupAccess(currentUser,
|
||||
mySQLConnection.getParentID(), MySQLConstants.CONNECTION_GROUP_UPDATE);
|
||||
|
||||
// Verify permission to use the to connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(toConnectionGroupID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
// Verify permission to update the to connection group
|
||||
permissionCheckService.verifyConnectionGroupAccess(currentUser,
|
||||
toConnectionGroupID, MySQLConstants.CONNECTION_GROUP_UPDATE);
|
||||
|
||||
// Verify that no connection already exists with this name.
|
||||
MySQLConnection previousConnection =
|
||||
connectionService.retrieveConnection(mySQLConnection.getName(),
|
||||
toConnectionGroupID, currentUser);
|
||||
if(previousConnection != null)
|
||||
throw new GuacamoleClientException("That connection name is already in use.");
|
||||
|
||||
// Update the connection
|
||||
mySQLConnection.setParentID(toConnectionGroupID);
|
||||
connectionService.updateConnection(mySQLConnection);
|
||||
}
|
||||
|
||||
}
|
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup.Type;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionGroupPermissionMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.model.ConnectionGroupPermissionKey;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionGroupService;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService;
|
||||
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
||||
import org.glyptodon.guacamole.GuacamoleUnsupportedException;
|
||||
import org.mybatis.guice.transactional.Transactional;
|
||||
|
||||
/**
|
||||
* A MySQL-based implementation of the connection group directory.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class ConnectionGroupDirectory implements Directory<String, ConnectionGroup>{
|
||||
|
||||
/**
|
||||
* The user who this connection directory belongs to. Access is based on
|
||||
* his/her permission settings.
|
||||
*/
|
||||
private AuthenticatedUser currentUser;
|
||||
|
||||
/**
|
||||
* The ID of the parent connection group.
|
||||
*/
|
||||
private Integer parentID;
|
||||
|
||||
/**
|
||||
* Service for checking permissions.
|
||||
*/
|
||||
@Inject
|
||||
private PermissionCheckService permissionCheckService;
|
||||
|
||||
/**
|
||||
* Service managing connection groups.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupService connectionGroupService;
|
||||
|
||||
/**
|
||||
* Service for manipulating connection group permissions in the database.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupPermissionMapper connectionGroupPermissionDAO;
|
||||
|
||||
/**
|
||||
* Set the user and parentID for this directory.
|
||||
*
|
||||
* @param currentUser
|
||||
* The user owning this connection group directory.
|
||||
*
|
||||
* @param parentID
|
||||
* The ID of the parent connection group.
|
||||
*/
|
||||
public void init(AuthenticatedUser currentUser, Integer parentID) {
|
||||
this.parentID = parentID;
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public ConnectionGroup get(String identifier) throws GuacamoleException {
|
||||
|
||||
// Get connection
|
||||
MySQLConnectionGroup connectionGroup =
|
||||
connectionGroupService.retrieveConnectionGroup(identifier, currentUser);
|
||||
|
||||
if(connectionGroup == null)
|
||||
return null;
|
||||
|
||||
// Verify permission to use the parent connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(connectionGroup.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
// Verify access is granted
|
||||
permissionCheckService.verifyConnectionGroupAccess(
|
||||
currentUser,
|
||||
connectionGroup.getConnectionGroupID(),
|
||||
MySQLConstants.CONNECTION_GROUP_READ);
|
||||
|
||||
// Return connection group
|
||||
return connectionGroup;
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public Set<String> getIdentifiers() throws GuacamoleException {
|
||||
|
||||
// Verify permission to use the connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(parentID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
return permissionCheckService.retrieveConnectionGroupIdentifiers(currentUser,
|
||||
parentID, MySQLConstants.CONNECTION_GROUP_READ);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void add(ConnectionGroup object) throws GuacamoleException {
|
||||
|
||||
String name = object.getName().trim();
|
||||
if(name.isEmpty())
|
||||
throw new GuacamoleClientException("The connection group name cannot be blank.");
|
||||
|
||||
Type type = object.getType();
|
||||
|
||||
String mySQLType = MySQLConstants.getConnectionGroupTypeConstant(type);
|
||||
|
||||
// Verify permission to create
|
||||
permissionCheckService.verifySystemAccess(currentUser,
|
||||
MySQLConstants.SYSTEM_CONNECTION_GROUP_CREATE);
|
||||
|
||||
// Verify permission to edit the parent connection group
|
||||
permissionCheckService.verifyConnectionGroupAccess(currentUser,
|
||||
this.parentID, MySQLConstants.CONNECTION_GROUP_UPDATE);
|
||||
|
||||
// Verify permission to use the parent connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(parentID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
// Verify that no connection already exists with this name.
|
||||
MySQLConnectionGroup previousConnectionGroup =
|
||||
connectionGroupService.retrieveConnectionGroup(name, parentID, currentUser);
|
||||
if(previousConnectionGroup != null)
|
||||
throw new GuacamoleClientException("That connection group name is already in use.");
|
||||
|
||||
// Create connection group
|
||||
MySQLConnectionGroup connectionGroup = connectionGroupService
|
||||
.createConnectionGroup(name, currentUser, parentID, mySQLType);
|
||||
|
||||
// Set the connection group ID
|
||||
object.setIdentifier(connectionGroup.getIdentifier());
|
||||
|
||||
// Finally, give the current user full access to the newly created
|
||||
// connection group.
|
||||
ConnectionGroupPermissionKey newConnectionGroupPermission = new ConnectionGroupPermissionKey();
|
||||
newConnectionGroupPermission.setUser_id(currentUser.getUserID());
|
||||
newConnectionGroupPermission.setConnection_group_id(connectionGroup.getConnectionGroupID());
|
||||
|
||||
// Read permission
|
||||
newConnectionGroupPermission.setPermission(MySQLConstants.CONNECTION_GROUP_READ);
|
||||
connectionGroupPermissionDAO.insert(newConnectionGroupPermission);
|
||||
|
||||
// Update permission
|
||||
newConnectionGroupPermission.setPermission(MySQLConstants.CONNECTION_GROUP_UPDATE);
|
||||
connectionGroupPermissionDAO.insert(newConnectionGroupPermission);
|
||||
|
||||
// Delete permission
|
||||
newConnectionGroupPermission.setPermission(MySQLConstants.CONNECTION_GROUP_DELETE);
|
||||
connectionGroupPermissionDAO.insert(newConnectionGroupPermission);
|
||||
|
||||
// Administer permission
|
||||
newConnectionGroupPermission.setPermission(MySQLConstants.CONNECTION_GROUP_ADMINISTER);
|
||||
connectionGroupPermissionDAO.insert(newConnectionGroupPermission);
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void update(ConnectionGroup object) throws GuacamoleException {
|
||||
|
||||
// If connection not actually from this auth provider, we can't handle
|
||||
// the update
|
||||
if (!(object instanceof MySQLConnectionGroup))
|
||||
throw new GuacamoleUnsupportedException("Connection not from database.");
|
||||
|
||||
MySQLConnectionGroup mySQLConnectionGroup = (MySQLConnectionGroup) object;
|
||||
|
||||
// Verify permission to update
|
||||
permissionCheckService.verifyConnectionGroupAccess(currentUser,
|
||||
mySQLConnectionGroup.getConnectionGroupID(),
|
||||
MySQLConstants.CONNECTION_GROUP_UPDATE);
|
||||
|
||||
// Perform update
|
||||
connectionGroupService.updateConnectionGroup(mySQLConnectionGroup);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void remove(String identifier) throws GuacamoleException {
|
||||
|
||||
// Get connection
|
||||
MySQLConnectionGroup mySQLConnectionGroup =
|
||||
connectionGroupService.retrieveConnectionGroup(identifier, currentUser);
|
||||
|
||||
if(mySQLConnectionGroup == null)
|
||||
throw new GuacamoleResourceNotFoundException("Connection group not found.");
|
||||
|
||||
// Verify permission to use the parent connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(mySQLConnectionGroup.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
// Verify permission to delete
|
||||
permissionCheckService.verifyConnectionGroupAccess(currentUser,
|
||||
mySQLConnectionGroup.getConnectionGroupID(),
|
||||
MySQLConstants.CONNECTION_GROUP_DELETE);
|
||||
|
||||
// Delete the connection group itself
|
||||
connectionGroupService.deleteConnectionGroup
|
||||
(mySQLConnectionGroup.getConnectionGroupID());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(String identifier, Directory<String, ConnectionGroup> directory)
|
||||
throws GuacamoleException {
|
||||
|
||||
if(MySQLConstants.CONNECTION_GROUP_ROOT_IDENTIFIER.equals(identifier))
|
||||
throw new GuacamoleUnsupportedException("The root connection group cannot be moved.");
|
||||
|
||||
if(!(directory instanceof ConnectionGroupDirectory))
|
||||
throw new GuacamoleUnsupportedException("Directory not from database");
|
||||
|
||||
Integer toConnectionGroupID = ((ConnectionGroupDirectory)directory).parentID;
|
||||
|
||||
// Get connection group
|
||||
MySQLConnectionGroup mySQLConnectionGroup =
|
||||
connectionGroupService.retrieveConnectionGroup(identifier, currentUser);
|
||||
|
||||
if(mySQLConnectionGroup == null)
|
||||
throw new GuacamoleResourceNotFoundException("Connection group not found.");
|
||||
|
||||
// Verify permission to update the connection group
|
||||
permissionCheckService.verifyConnectionGroupAccess(currentUser,
|
||||
mySQLConnectionGroup.getConnectionGroupID(),
|
||||
MySQLConstants.CONNECTION_GROUP_UPDATE);
|
||||
|
||||
// Verify permission to use the from connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(mySQLConnectionGroup.getParentID(), currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
// Verify permission to update the from connection group
|
||||
permissionCheckService.verifyConnectionGroupAccess(currentUser,
|
||||
mySQLConnectionGroup.getParentID(), MySQLConstants.CONNECTION_GROUP_UPDATE);
|
||||
|
||||
// Verify permission to use the to connection group for organizational purposes
|
||||
permissionCheckService.verifyConnectionGroupUsageAccess
|
||||
(toConnectionGroupID, currentUser, MySQLConstants.CONNECTION_GROUP_ORGANIZATIONAL);
|
||||
|
||||
// Verify permission to update the to connection group
|
||||
permissionCheckService.verifyConnectionGroupAccess(currentUser,
|
||||
toConnectionGroupID, MySQLConstants.CONNECTION_GROUP_UPDATE);
|
||||
|
||||
// Verify that no connection already exists with this name.
|
||||
MySQLConnectionGroup previousConnectionGroup =
|
||||
connectionGroupService.retrieveConnectionGroup(mySQLConnectionGroup.getName(),
|
||||
toConnectionGroupID, currentUser);
|
||||
if(previousConnectionGroup != null)
|
||||
throw new GuacamoleClientException("That connection group name is already in use.");
|
||||
|
||||
// Verify that moving this connectionGroup would not cause a cycle
|
||||
Integer relativeParentID = toConnectionGroupID;
|
||||
while(relativeParentID != null) {
|
||||
if(relativeParentID == mySQLConnectionGroup.getConnectionGroupID())
|
||||
throw new GuacamoleUnsupportedException("Connection group cycle detected.");
|
||||
|
||||
MySQLConnectionGroup relativeParentGroup = connectionGroupService.
|
||||
retrieveConnectionGroup(relativeParentID, currentUser);
|
||||
|
||||
relativeParentID = relativeParentGroup.getParentID();
|
||||
}
|
||||
|
||||
// Update the connection
|
||||
mySQLConnectionGroup.setParentID(toConnectionGroupID);
|
||||
connectionGroupService.updateConnectionGroup(mySQLConnectionGroup);
|
||||
}
|
||||
|
||||
}
|
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.name.Names;
|
||||
import java.util.Properties;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
||||
import org.glyptodon.guacamole.net.auth.Credentials;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionGroupMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionGroupPermissionMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionHistoryMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionParameterMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.ConnectionPermissionMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.SystemPermissionMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.UserMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.dao.UserPermissionMapper;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.properties.MySQLGuacamoleProperties;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionGroupService;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.service.ConnectionService;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.service.PasswordEncryptionService;
|
||||
import net.sourceforge.guacamole.net.auth.mysql.service.PermissionCheckService;
|
||||
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.UserService;
|
||||
import org.glyptodon.guacamole.properties.GuacamoleProperties;
|
||||
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
|
||||
import org.mybatis.guice.MyBatisModule;
|
||||
import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider;
|
||||
import org.mybatis.guice.datasource.helper.JdbcHelper;
|
||||
|
||||
/**
|
||||
* Provides a MySQL based implementation of the AuthenticationProvider
|
||||
* functionality.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class MySQLAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
/**
|
||||
* Set of all active connections.
|
||||
*/
|
||||
private ActiveConnectionMap activeConnectionMap = new ActiveConnectionMap();
|
||||
|
||||
/**
|
||||
* Injector which will manage the object graph of this authentication
|
||||
* provider.
|
||||
*/
|
||||
private Injector injector;
|
||||
|
||||
@Override
|
||||
public UserContext getUserContext(Credentials credentials) throws GuacamoleException {
|
||||
|
||||
// Get user service
|
||||
UserService userService = injector.getInstance(UserService.class);
|
||||
|
||||
// Get user
|
||||
MySQLUser authenticatedUser = userService.retrieveUser(credentials);
|
||||
if (authenticatedUser != null) {
|
||||
MySQLUserContext context = injector.getInstance(MySQLUserContext.class);
|
||||
context.init(new AuthenticatedUser(authenticatedUser.getUserID(), credentials));
|
||||
return context;
|
||||
}
|
||||
|
||||
// Otherwise, unauthorized
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new MySQLAuthenticationProvider that reads and writes
|
||||
* authentication data to a MySQL database defined by properties in
|
||||
* guacamole.properties.
|
||||
*
|
||||
* @throws GuacamoleException If a required property is missing, or
|
||||
* an error occurs while parsing a property.
|
||||
*/
|
||||
public MySQLAuthenticationProvider() throws GuacamoleException {
|
||||
|
||||
final Properties myBatisProperties = new Properties();
|
||||
final Properties driverProperties = new Properties();
|
||||
|
||||
// Set the mysql properties for MyBatis.
|
||||
myBatisProperties.setProperty("mybatis.environment.id", "guacamole");
|
||||
myBatisProperties.setProperty("JDBC.host", GuacamoleProperties.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_HOSTNAME));
|
||||
myBatisProperties.setProperty("JDBC.port", String.valueOf(GuacamoleProperties.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_PORT)));
|
||||
myBatisProperties.setProperty("JDBC.schema", GuacamoleProperties.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_DATABASE));
|
||||
myBatisProperties.setProperty("JDBC.username", GuacamoleProperties.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_USERNAME));
|
||||
myBatisProperties.setProperty("JDBC.password", GuacamoleProperties.getRequiredProperty(MySQLGuacamoleProperties.MYSQL_PASSWORD));
|
||||
myBatisProperties.setProperty("JDBC.autoCommit", "false");
|
||||
myBatisProperties.setProperty("mybatis.pooled.pingEnabled", "true");
|
||||
myBatisProperties.setProperty("mybatis.pooled.pingQuery", "SELECT 1");
|
||||
driverProperties.setProperty("characterEncoding","UTF-8");
|
||||
|
||||
// Set up Guice injector.
|
||||
injector = Guice.createInjector(
|
||||
JdbcHelper.MySQL,
|
||||
|
||||
new Module() {
|
||||
@Override
|
||||
public void configure(Binder binder) {
|
||||
Names.bindProperties(binder, myBatisProperties);
|
||||
binder.bind(Properties.class)
|
||||
.annotatedWith(Names.named("JDBC.driverProperties"))
|
||||
.toInstance(driverProperties);
|
||||
}
|
||||
},
|
||||
|
||||
new MyBatisModule() {
|
||||
@Override
|
||||
protected void initialize() {
|
||||
|
||||
// Datasource
|
||||
bindDataSourceProviderType(PooledDataSourceProvider.class);
|
||||
|
||||
// Transaction factory
|
||||
bindTransactionFactoryType(JdbcTransactionFactory.class);
|
||||
|
||||
// Add MyBatis mappers
|
||||
addMapperClass(ConnectionHistoryMapper.class);
|
||||
addMapperClass(ConnectionMapper.class);
|
||||
addMapperClass(ConnectionGroupMapper.class);
|
||||
addMapperClass(ConnectionGroupPermissionMapper.class);
|
||||
addMapperClass(ConnectionParameterMapper.class);
|
||||
addMapperClass(ConnectionPermissionMapper.class);
|
||||
addMapperClass(SystemPermissionMapper.class);
|
||||
addMapperClass(UserMapper.class);
|
||||
addMapperClass(UserPermissionMapper.class);
|
||||
|
||||
// Bind interfaces
|
||||
bind(MySQLUserContext.class);
|
||||
bind(UserDirectory.class);
|
||||
bind(MySQLUser.class);
|
||||
bind(SaltService.class).to(SecureRandomSaltService.class);
|
||||
bind(PasswordEncryptionService.class).to(SHA256PasswordEncryptionService.class);
|
||||
bind(PermissionCheckService.class);
|
||||
bind(ConnectionService.class);
|
||||
bind(ConnectionGroupService.class);
|
||||
bind(UserService.class);
|
||||
bind(ActiveConnectionMap.class).toInstance(activeConnectionMap);
|
||||
|
||||
}
|
||||
} // end of mybatis module
|
||||
|
||||
);
|
||||
} // end of constructor
|
||||
|
||||
@Override
|
||||
public UserContext updateUserContext(UserContext context,
|
||||
Credentials credentials) throws GuacamoleException {
|
||||
|
||||
// No need to update the context
|
||||
return context;
|
||||
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user