diff --git a/extensions/guacamole-auth-jdbc/README b/extensions/guacamole-auth-jdbc/README
index d4fa250aa..0fee7bc93 100644
--- a/extensions/guacamole-auth-jdbc/README
+++ b/extensions/guacamole-auth-jdbc/README
@@ -51,8 +51,8 @@ in the library directory configured in guacamole.properties.
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.
+ place the .jar files from the extracted database-specific subdirectory in
+ the library directory specified in guacamole.properties.
You will likely need to do this as root.
@@ -60,10 +60,10 @@ in the library directory configured in guacamole.properties.
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
+5) Set up your database to authenticate Guacamole users
A schema file is provided in the schema directory for creating
- the guacamole authentication tables in your MySQL database.
+ the guacamole authentication tables in your database of choice.
Additionally, a script is provided to create a default admin user
with username 'guacadmin' and password 'guacadmin'. This user can
@@ -90,6 +90,17 @@ in the library directory configured in guacamole.properties.
mysql-disallow-simultaneous-connections: true
+ For PostgreSQL, the properties are the same, but have different prefixes:
+
+ # Database connection configuration
+ postgresql-hostname: database.host.name
+ postgresql-port: 5432
+ postgresql-database: guacamole.database.name
+ postgresql-username: user
+ postgresql-password: pass
+
+ postgresql-disallow-simultaneous-connections: true
+
------------------------------------------------------------
Reporting problems
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/security/PasswordEncryptionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/security/PasswordEncryptionService.java
index ef3099468..2e78725ef 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/security/PasswordEncryptionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/security/PasswordEncryptionService.java
@@ -30,11 +30,16 @@ public interface PasswordEncryptionService {
/**
* Creates a password hash based on the provided username, password, and
- * salt.
+ * salt. If the provided salt is null, only the password itself is hashed.
*
- * @param password The password to hash.
- * @param salt The salt to use when hashing the password.
- * @return The generated password hash.
+ * @param password
+ * The password to hash.
+ *
+ * @param salt
+ * The salt to use when hashing the password, if any.
+ *
+ * @return
+ * The generated password hash.
*/
public byte[] createPasswordHash(String password, byte[] salt);
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/security/SHA256PasswordEncryptionService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/security/SHA256PasswordEncryptionService.java
index cfe5bc45f..577bdb0ef 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/security/SHA256PasswordEncryptionService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/security/SHA256PasswordEncryptionService.java
@@ -38,26 +38,26 @@ public byte[] createPasswordHash(String password, byte[] salt) {
try {
- // Build salted password
+ // Build salted password, if a salt was provided
StringBuilder builder = new StringBuilder();
builder.append(password);
- builder.append(DatatypeConverter.printHexBinary(salt));
- // Hash UTF-8 bytes of salted password
+ if (salt != null)
+ builder.append(DatatypeConverter.printHexBinary(salt));
+
+ // Hash UTF-8 bytes of possibly-salted password
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(builder.toString().getBytes("UTF-8"));
return md.digest();
}
- // Should not happen
- catch (UnsupportedEncodingException ex) {
- throw new RuntimeException(ex);
+ // Throw hard errors if standard pieces of Java are missing
+ catch (UnsupportedEncodingException e) {
+ throw new UnsupportedOperationException("Unexpected lack of UTF-8 support.", e);
}
-
- // Should not happen
- catch (NoSuchAlgorithmException ex) {
- throw new RuntimeException(ex);
+ catch (NoSuchAlgorithmException e) {
+ throw new UnsupportedOperationException("Unexpected lack of SHA-256 support.", e);
}
}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql
index 5c23bfc90..0a50bb379 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql
@@ -65,7 +65,9 @@ CREATE TABLE `guacamole_connection` (
--
-- Table of users. Each user has a unique username and a hashed password
--- with corresponding salt.
+-- with corresponding salt. Although the authentication system will always set
+-- salted passwords, other systems may set unsalted passwords by simply not
+-- providing the salt.
--
CREATE TABLE `guacamole_user` (
@@ -73,7 +75,7 @@ CREATE TABLE `guacamole_user` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(128) NOT NULL,
`password_hash` binary(32) NOT NULL,
- `password_salt` binary(32) NOT NULL,
+ `password_salt` binary(32),
PRIMARY KEY (`user_id`),
UNIQUE KEY `username` (`username`)
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/user/UserMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/user/UserMapper.xml
index 69c49d060..7c5b7357f 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/user/UserMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/user/UserMapper.xml
@@ -47,7 +47,7 @@
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'
+ AND permission = 'READ'
@@ -83,7 +83,7 @@
#{identifier,jdbcType=VARCHAR}
AND guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
- AND permission = 'read'
+ AND permission = 'READ'
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/.gitignore b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/.gitignore
new file mode 100644
index 000000000..42f4a1a64
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/.gitignore
@@ -0,0 +1,2 @@
+target/
+*~
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/pom.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/pom.xml
new file mode 100644
index 000000000..2329087cd
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/pom.xml
@@ -0,0 +1,78 @@
+
+
+ 4.0.0
+ org.glyptodon.guacamole
+ guacamole-auth-jdbc-postgresql
+ jar
+ guacamole-auth-jdbc-postgresql
+ http://guac-dev.org/
+
+
+ UTF-8
+
+
+
+ org.glyptodon.guacamole
+ guacamole-auth-jdbc
+ 0.9.5
+ ../../
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 1.6
+
+
+
+
+
+ maven-assembly-plugin
+ 2.2-beta-5
+
+
+ jar-with-dependencies
+ package
+
+ single
+
+
+ extension/${project.artifactId}-${project.version}
+ false
+
+ jar-with-dependencies
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.glyptodon.guacamole
+ guacamole-ext
+ provided
+
+
+
+
+ org.glyptodon.guacamole
+ guacamole-auth-jdbc-base
+ 0.9.5
+
+
+
+
+
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql
new file mode 100644
index 000000000..4e4297693
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql
@@ -0,0 +1,275 @@
+--
+-- 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.
+--
+
+--
+-- Connection group types
+--
+
+CREATE TYPE guacamole_connection_group_type AS ENUM(
+ 'ORGANIZATIONAL',
+ 'BALANCING'
+);
+
+--
+-- Object permission types
+--
+
+CREATE TYPE guacamole_object_permission_type AS ENUM(
+ 'READ',
+ 'UPDATE',
+ 'DELETE',
+ 'ADMINISTER'
+);
+
+--
+-- System permission types
+--
+
+CREATE TYPE guacamole_system_permission_type AS ENUM(
+ 'CREATE_CONNECTION',
+ 'CREATE_CONNECTION_GROUP',
+ 'CREATE_USER',
+ 'ADMINISTER'
+);
+
+--
+-- Table of connection groups. Each connection group has a name.
+--
+
+CREATE TABLE guacamole_connection_group (
+
+ connection_group_id serial NOT NULL,
+ parent_id integer,
+ connection_group_name varchar(128) NOT NULL,
+ type guacamole_connection_group_type
+ NOT NULL DEFAULT 'ORGANIZATIONAL',
+
+ PRIMARY KEY (connection_group_id),
+
+ CONSTRAINT connection_group_name_parent
+ UNIQUE (connection_group_name, parent_id),
+
+ CONSTRAINT guacamole_connection_group_ibfk_1
+ FOREIGN KEY (parent_id)
+ REFERENCES guacamole_connection_group (connection_group_id)
+ ON DELETE CASCADE
+
+);
+
+CREATE INDEX ON guacamole_connection_group(parent_id);
+
+--
+-- Table of connections. Each connection has a name, protocol, and
+-- associated set of parameters.
+-- A connection may belong to a connection group.
+--
+
+CREATE TABLE guacamole_connection (
+
+ connection_id serial NOT NULL,
+ connection_name varchar(128) NOT NULL,
+ parent_id integer,
+ protocol varchar(32) NOT NULL,
+
+ PRIMARY KEY (connection_id),
+
+ CONSTRAINT connection_name_parent
+ UNIQUE (connection_name, parent_id),
+
+ CONSTRAINT guacamole_connection_ibfk_1
+ FOREIGN KEY (parent_id)
+ REFERENCES guacamole_connection_group (connection_group_id)
+ ON DELETE CASCADE
+
+);
+
+CREATE INDEX ON guacamole_connection(parent_id);
+
+--
+-- Table of users. Each user has a unique username and a hashed password
+-- with corresponding salt. Although the authentication system will always set
+-- salted passwords, other systems may set unsalted passwords by simply not
+-- providing the salt.
+--
+
+CREATE TABLE guacamole_user (
+
+ user_id serial NOT NULL,
+ username varchar(128) NOT NULL,
+ password_hash bytea NOT NULL,
+ password_salt bytea,
+
+ PRIMARY KEY (user_id),
+
+ CONSTRAINT username
+ UNIQUE (username)
+
+);
+
+--
+-- Table of connection parameters. Each parameter is simply a name/value pair
+-- associated with a connection.
+--
+
+CREATE TABLE guacamole_connection_parameter (
+
+ connection_id integer NOT NULL,
+ parameter_name varchar(128) NOT NULL,
+ parameter_value varchar(4096) NOT NULL,
+
+ PRIMARY KEY (connection_id,parameter_name),
+
+ CONSTRAINT guacamole_connection_parameter_ibfk_1
+ FOREIGN KEY (connection_id)
+ REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
+
+);
+
+CREATE INDEX ON guacamole_connection_parameter(connection_id);
+
+--
+-- Table of connection permissions. Each connection permission grants a user
+-- specific access to a connection.
+--
+
+CREATE TABLE guacamole_connection_permission (
+
+ user_id integer NOT NULL,
+ connection_id integer NOT NULL,
+ permission guacamole_object_permission_type NOT NULL,
+
+ PRIMARY KEY (user_id,connection_id,permission),
+
+ CONSTRAINT guacamole_connection_permission_ibfk_1
+ FOREIGN KEY (connection_id)
+ REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE,
+
+ CONSTRAINT guacamole_connection_permission_ibfk_2
+ FOREIGN KEY (user_id)
+ REFERENCES guacamole_user (user_id) ON DELETE CASCADE
+
+);
+
+CREATE INDEX ON guacamole_connection_permission(connection_id);
+CREATE INDEX ON guacamole_connection_permission(user_id);
+
+--
+-- Table of connection group permissions. Each group permission grants a user
+-- specific access to a connection group.
+--
+
+CREATE TABLE guacamole_connection_group_permission (
+
+ user_id integer NOT NULL,
+ connection_group_id integer NOT NULL,
+ permission guacamole_object_permission_type NOT NULL,
+
+ PRIMARY KEY (user_id,connection_group_id,permission),
+
+ CONSTRAINT guacamole_connection_group_permission_ibfk_1
+ FOREIGN KEY (connection_group_id)
+ REFERENCES guacamole_connection_group (connection_group_id) ON DELETE CASCADE,
+
+ CONSTRAINT guacamole_connection_group_permission_ibfk_2
+ FOREIGN KEY (user_id)
+ REFERENCES guacamole_user (user_id) ON DELETE CASCADE
+
+);
+
+CREATE INDEX ON guacamole_connection_group_permission(connection_group_id);
+CREATE INDEX ON guacamole_connection_group_permission(user_id);
+
+--
+-- Table of system permissions. Each system permission grants a user a
+-- system-level privilege of some kind.
+--
+
+CREATE TABLE guacamole_system_permission (
+
+ user_id integer NOT NULL,
+ permission guacamole_system_permission_type NOT NULL,
+
+ PRIMARY KEY (user_id,permission),
+
+ CONSTRAINT guacamole_system_permission_ibfk_1
+ FOREIGN KEY (user_id)
+ REFERENCES guacamole_user (user_id) ON DELETE CASCADE
+
+);
+
+CREATE INDEX ON guacamole_system_permission(user_id);
+
+--
+-- Table of user permissions. Each user permission grants a user access to
+-- another user (the "affected" user) for a specific type of operation.
+--
+
+CREATE TABLE guacamole_user_permission (
+
+ user_id integer NOT NULL,
+ affected_user_id integer NOT NULL,
+ permission guacamole_object_permission_type NOT NULL,
+
+ PRIMARY KEY (user_id,affected_user_id,permission),
+
+ CONSTRAINT guacamole_user_permission_ibfk_1
+ FOREIGN KEY (affected_user_id)
+ REFERENCES guacamole_user (user_id) ON DELETE CASCADE,
+
+ CONSTRAINT guacamole_user_permission_ibfk_2
+ FOREIGN KEY (user_id)
+ REFERENCES guacamole_user (user_id) ON DELETE CASCADE
+
+);
+
+CREATE INDEX ON guacamole_user_permission(affected_user_id);
+CREATE INDEX ON guacamole_user_permission(user_id);
+
+--
+-- Table of connection history records. Each record defines a specific user's
+-- session, including the connection used, the start time, and the end time
+-- (if any).
+--
+
+CREATE TABLE guacamole_connection_history (
+
+ history_id serial NOT NULL,
+ user_id integer NOT NULL,
+ connection_id integer NOT NULL,
+ start_date timestamptz NOT NULL,
+ end_date timestamptz DEFAULT NULL,
+
+ PRIMARY KEY (history_id),
+
+ CONSTRAINT guacamole_connection_history_ibfk_1
+ FOREIGN KEY (user_id)
+ REFERENCES guacamole_user (user_id) ON DELETE CASCADE,
+
+ CONSTRAINT guacamole_connection_history_ibfk_2
+ FOREIGN KEY (connection_id)
+ REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
+
+);
+
+CREATE INDEX ON guacamole_connection_history(user_id);
+CREATE INDEX ON guacamole_connection_history(connection_id);
+
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/002-create-admin-user.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/002-create-admin-user.sql
new file mode 100644
index 000000000..16eafbe73
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/002-create-admin-user.sql
@@ -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.
+--
+
+
+-- Create default user "guacadmin" with password "guacadmin"
+INSERT INTO guacamole_user (username, password_hash, password_salt)
+VALUES ('guacadmin',
+ E'\\xCA458A7D494E3BE824F5E1E175A1556C0F8EEF2C2D7DF3633BEC4A29C4411960', -- 'guacadmin'
+ E'\\xFE24ADC5E11E2B25288D1704ABE67A79E342ECC26064CE69C5B3177795A82264');
+
+-- Grant this user all system permissions
+INSERT INTO guacamole_system_permission
+SELECT user_id, permission::guacamole_system_permission_type
+FROM (
+ VALUES
+ ('guacadmin', 'CREATE_CONNECTION'),
+ ('guacadmin', 'CREATE_CONNECTION_GROUP'),
+ ('guacadmin', 'CREATE_USER'),
+ ('guacadmin', 'ADMINISTER')
+) permissions (username, permission)
+JOIN guacamole_user ON permissions.username = guacamole_user.username;
+
+-- Grant admin permission to read/update/administer self
+INSERT INTO guacamole_user_permission
+SELECT guacamole_user.user_id, affected.user_id, permission::guacamole_object_permission_type
+FROM (
+ VALUES
+ ('guacadmin', 'guacadmin', 'READ'),
+ ('guacadmin', 'guacadmin', 'UPDATE'),
+ ('guacadmin', 'guacadmin', 'ADMINISTER')
+) permissions (username, affected_username, permission)
+JOIN guacamole_user ON permissions.username = guacamole_user.username
+JOIN guacamole_user affected ON permissions.affected_username = affected.username;
+
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/PostgreSQLAuthenticationProvider.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/PostgreSQLAuthenticationProvider.java
new file mode 100644
index 000000000..65bd2270a
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/PostgreSQLAuthenticationProvider.java
@@ -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.postgresql;
+
+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.socket.BalancedGuacamoleSocketService;
+import org.glyptodon.guacamole.auth.jdbc.socket.GuacamoleSocketService;
+import org.glyptodon.guacamole.auth.jdbc.socket.MultiseatGuacamoleSocketService;
+import org.glyptodon.guacamole.auth.jdbc.socket.SingleSeatGuacamoleSocketService;
+import org.glyptodon.guacamole.auth.jdbc.socket.UnrestrictedGuacamoleSocketService;
+import org.glyptodon.guacamole.auth.jdbc.user.UserContextService;
+import org.glyptodon.guacamole.environment.Environment;
+import org.glyptodon.guacamole.environment.LocalEnvironment;
+
+/**
+ * Provides a PostgreSQL-based implementation of the AuthenticationProvider
+ * functionality.
+ *
+ * @author James Muehlner
+ * @author Michael Jumper
+ */
+public class PostgreSQLAuthenticationProvider implements AuthenticationProvider {
+
+ /**
+ * Injector which will manage the object graph of this authentication
+ * provider.
+ */
+ private final Injector injector;
+
+ /**
+ * Returns the appropriate socket service class given the Guacamole
+ * environment. The class is chosen based on configuration options that
+ * dictate concurrent usage policy.
+ *
+ * @param environment
+ * The environment of the Guacamole server.
+ *
+ * @return
+ * The socket service class that matches the concurrent usage policy
+ * options set in the Guacamole environment.
+ *
+ * @throws GuacamoleException
+ * If an error occurs while reading the configuration options.
+ */
+ private Class extends GuacamoleSocketService>
+ getSocketServiceClass(Environment environment)
+ throws GuacamoleException {
+
+ // Read concurrency-related properties
+ boolean disallowSimultaneous = environment.getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_DISALLOW_SIMULTANEOUS_CONNECTIONS, false);
+ boolean disallowDuplicate = environment.getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_DISALLOW_DUPLICATE_CONNECTIONS, true);
+
+ if (disallowSimultaneous) {
+
+ // Connections may not be used concurrently
+ if (disallowDuplicate)
+ return SingleSeatGuacamoleSocketService.class;
+
+ // Connections are reserved for a single user when in use
+ else
+ return BalancedGuacamoleSocketService.class;
+
+ }
+
+ else {
+
+ // Connections may be used concurrently, but only once per user
+ if (disallowDuplicate)
+ return MultiseatGuacamoleSocketService.class;
+
+ // Connection use is not restricted
+ else
+ return UnrestrictedGuacamoleSocketService.class;
+
+ }
+
+ }
+
+ /**
+ * Creates a new PostgreSQLAuthenticationProvider that reads and writes
+ * authentication data to a PostgreSQL database defined by properties in
+ * guacamole.properties.
+ *
+ * @throws GuacamoleException
+ * If a required property is missing, or an error occurs while parsing
+ * a property.
+ */
+ public PostgreSQLAuthenticationProvider() throws GuacamoleException {
+
+ // Get local environment
+ Environment environment = new LocalEnvironment();
+
+ // Set up Guice injector.
+ injector = Guice.createInjector(
+
+ // Configure PostgreSQL-specific authentication
+ new PostgreSQLAuthenticationProviderModule(environment),
+
+ // Configure JDBC authentication core
+ new JDBCAuthenticationProviderModule(environment, getSocketServiceClass(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;
+
+ }
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/PostgreSQLAuthenticationProviderModule.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/PostgreSQLAuthenticationProviderModule.java
new file mode 100644
index 000000000..2decdf9a6
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/PostgreSQLAuthenticationProviderModule.java
@@ -0,0 +1,99 @@
+/*
+ * 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.postgresql;
+
+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 PostgreSQL-specific injections.
+ *
+ * @author James Muehlner
+ * @author Michael Jumper
+ */
+public class PostgreSQLAuthenticationProviderModule implements Module {
+
+ /**
+ * MyBatis-specific configuration properties.
+ */
+ private final Properties myBatisProperties = new Properties();
+
+ /**
+ * PostgreSQL-specific driver configuration properties.
+ */
+ private final Properties driverProperties = new Properties();
+
+ /**
+ * Creates a new PostgreSQL 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 PostgreSQLAuthenticationProviderModule(Environment environment)
+ throws GuacamoleException {
+
+ // Set the PostgreSQL-specific properties for MyBatis.
+ myBatisProperties.setProperty("mybatis.environment.id", "guacamole");
+ myBatisProperties.setProperty("JDBC.host", environment.getRequiredProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_HOSTNAME));
+ myBatisProperties.setProperty("JDBC.port", String.valueOf(environment.getRequiredProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_PORT)));
+ myBatisProperties.setProperty("JDBC.schema", environment.getRequiredProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_DATABASE));
+ myBatisProperties.setProperty("JDBC.username", environment.getRequiredProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_USERNAME));
+ myBatisProperties.setProperty("JDBC.password", environment.getRequiredProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_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 PostgreSQL-specific properties
+ JdbcHelper.PostgreSQL.configure(binder);
+
+ // Bind MyBatis properties
+ Names.bindProperties(binder, myBatisProperties);
+
+ // Bing JDBC driver properties
+ binder.bind(Properties.class)
+ .annotatedWith(Names.named("JDBC.driverProperties"))
+ .toInstance(driverProperties);
+
+ }
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/PostgreSQLGuacamoleProperties.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/PostgreSQLGuacamoleProperties.java
new file mode 100644
index 000000000..abb5a1249
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/PostgreSQLGuacamoleProperties.java
@@ -0,0 +1,127 @@
+/*
+ * 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.postgresql;
+
+import org.glyptodon.guacamole.properties.BooleanGuacamoleProperty;
+import org.glyptodon.guacamole.properties.IntegerGuacamoleProperty;
+import org.glyptodon.guacamole.properties.StringGuacamoleProperty;
+
+/**
+ * Properties used by the PostgreSQL Authentication plugin.
+ *
+ * @author James Muehlner
+ * @author Michael Jumper
+ */
+public class PostgreSQLGuacamoleProperties {
+
+ /**
+ * This class should not be instantiated.
+ */
+ private PostgreSQLGuacamoleProperties() {}
+
+ /**
+ * The URL of the PostgreSQL server hosting the Guacamole authentication tables.
+ */
+ public static final StringGuacamoleProperty POSTGRESQL_HOSTNAME =
+ new StringGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "postgresql-hostname"; }
+
+ };
+
+ /**
+ * The port of the PostgreSQL server hosting the Guacamole authentication
+ * tables.
+ */
+ public static final IntegerGuacamoleProperty POSTGRESQL_PORT =
+ new IntegerGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "postgresql-port"; }
+
+ };
+
+ /**
+ * The name of the PostgreSQL database containing the Guacamole
+ * authentication tables.
+ */
+ public static final StringGuacamoleProperty POSTGRESQL_DATABASE =
+ new StringGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "postgresql-database"; }
+
+ };
+
+ /**
+ * The username used to authenticate to the PostgreSQL database containing
+ * the Guacamole authentication tables.
+ */
+ public static final StringGuacamoleProperty POSTGRESQL_USERNAME =
+ new StringGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "postgresql-username"; }
+
+ };
+
+ /**
+ * The password used to authenticate to the PostgreSQL database containing
+ * the Guacamole authentication tables.
+ */
+ public static final StringGuacamoleProperty POSTGRESQL_PASSWORD =
+ new StringGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "postgresql-password"; }
+
+ };
+
+ /**
+ * Whether or not multiple users accessing the same connection at the same
+ * time should be disallowed.
+ */
+ public static final BooleanGuacamoleProperty
+ POSTGRESQL_DISALLOW_SIMULTANEOUS_CONNECTIONS =
+ new BooleanGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "postgresql-disallow-simultaneous-connections"; }
+
+ };
+
+ /**
+ * Whether or not the same user accessing the same connection or connection
+ * group at the same time should be disallowed.
+ */
+ public static final BooleanGuacamoleProperty
+ POSTGRESQL_DISALLOW_DUPLICATE_CONNECTIONS =
+ new BooleanGuacamoleProperty() {
+
+ @Override
+ public String getName() { return "postgresql-disallow-duplicate-connections"; }
+
+ };
+
+}
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/package-info.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/package-info.java
new file mode 100644
index 000000000..1a939e1a6
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/java/org/glyptodon/guacamole/auth/postgresql/package-info.java
@@ -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.
+ */
+
+/**
+ * The PostgreSQL authentication provider.
+ */
+package org.glyptodon.guacamole.auth.postgresql;
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionMapper.xml
new file mode 100644
index 000000000..11d18a9b4
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionMapper.xml
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DELETE FROM guacamole_connection
+ WHERE connection_id = #{identifier,jdbcType=INTEGER}::integer
+
+
+
+
+
+ INSERT INTO guacamole_connection (
+ connection_name,
+ parent_id,
+ protocol
+ )
+ VALUES (
+ #{object.name,jdbcType=VARCHAR},
+ #{object.parentIdentifier,jdbcType=INTEGER}::integer,
+ #{object.protocol,jdbcType=VARCHAR}
+ )
+
+
+
+
+
+ UPDATE guacamole_connection
+ SET connection_name = #{object.name,jdbcType=VARCHAR},
+ parent_id = #{object.parentIdentifier,jdbcType=INTEGER}::integer,
+ protocol = #{object.protocol,jdbcType=VARCHAR}
+ WHERE connection_id = #{object.objectID,jdbcType=INTEGER}::integer
+
+
+
\ No newline at end of file
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
new file mode 100644
index 000000000..de5f53076
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ INSERT INTO guacamole_connection_history (
+ connection_id,
+ user_id,
+ start_date,
+ end_date
+ )
+ VALUES (
+ #{record.connectionIdentifier,jdbcType=INTEGER}::integer,
+ #{record.userID,jdbcType=INTEGER},
+ #{record.startDate,jdbcType=TIMESTAMP},
+ #{record.endDate,jdbcType=TIMESTAMP}
+ )
+
+
+
+
\ No newline at end of file
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ParameterMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ParameterMapper.xml
new file mode 100644
index 000000000..e3fe5d8e9
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ParameterMapper.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DELETE FROM guacamole_connection_parameter
+ WHERE connection_id = #{identifier,jdbcType=INTEGER}::integer
+
+
+
+
+
+ INSERT INTO guacamole_connection_parameter (
+ connection_id,
+ parameter_name,
+ parameter_value
+ )
+ VALUES
+
+ (#{parameter.connectionIdentifier,jdbcType=INTEGER}::integer,
+ #{parameter.name,jdbcType=VARCHAR},
+ #{parameter.value,jdbcType=VARCHAR})
+
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
new file mode 100644
index 000000000..f437e51a0
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DELETE FROM guacamole_connection_group
+ WHERE connection_group_id = #{identifier,jdbcType=INTEGER}::integer
+
+
+
+
+
+ INSERT INTO guacamole_connection_group (
+ connection_group_name,
+ parent_id,
+ type
+ )
+ VALUES (
+ #{object.name,jdbcType=VARCHAR},
+ #{object.parentIdentifier,jdbcType=INTEGER}::integer,
+ #{object.type,jdbcType=VARCHAR}::guacamole_connection_group_type
+ )
+
+
+
+
+
+ UPDATE guacamole_connection_group
+ SET connection_group_name = #{object.name,jdbcType=VARCHAR},
+ parent_id = #{object.parentIdentifier,jdbcType=INTEGER}::integer,
+ type = #{object.type,jdbcType=VARCHAR}::guacamole_connection_group_type
+ WHERE connection_group_id = #{object.objectID,jdbcType=INTEGER}::integer
+
+
+
\ No newline at end of file
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/ConnectionGroupPermissionMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/ConnectionGroupPermissionMapper.xml
new file mode 100644
index 000000000..33b3562ed
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/ConnectionGroupPermissionMapper.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DELETE FROM guacamole_connection_group_permission
+ WHERE (user_id, permission, connection_group_id) IN
+
+ (#{permission.userID,jdbcType=INTEGER},
+ #{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
+ #{permission.objectIdentifier,jdbcType=INTEGER}::integer)
+
+
+
+
+
+
+
+ INSERT INTO guacamole_connection_group_permission (
+ user_id,
+ permission,
+ connection_group_id
+ )
+ VALUES
+
+ (#{permission.userID,jdbcType=INTEGER},
+ #{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
+ #{permission.objectIdentifier,jdbcType=INTEGER}::integer)
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/ConnectionPermissionMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/ConnectionPermissionMapper.xml
new file mode 100644
index 000000000..4ed1ad7e9
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/ConnectionPermissionMapper.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DELETE FROM guacamole_connection_permission
+ WHERE (user_id, permission, connection_id) IN
+
+ (#{permission.userID,jdbcType=INTEGER},
+ #{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
+ #{permission.objectIdentifier,jdbcType=INTEGER}::integer)
+
+
+
+
+
+
+
+ INSERT INTO guacamole_connection_permission (
+ user_id,
+ permission,
+ connection_id
+ )
+ VALUES
+
+ (#{permission.userID,jdbcType=INTEGER},
+ #{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
+ #{permission.objectIdentifier,jdbcType=INTEGER}::integer)
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/SystemPermissionMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/SystemPermissionMapper.xml
new file mode 100644
index 000000000..f1222012c
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/SystemPermissionMapper.xml
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DELETE FROM guacamole_system_permission
+ WHERE (user_id, permission) IN
+
+ (#{permission.userID,jdbcType=INTEGER},
+ #{permission.type,jdbcType=VARCHAR}::guacamole_system_permission_type)
+
+
+
+
+
+
+
+ INSERT INTO guacamole_system_permission (
+ user_id,
+ permission
+ )
+ VALUES
+
+ (#{permission.userID,jdbcType=INTEGER},
+ #{permission.type,jdbcType=VARCHAR}::guacamole_system_permission_type)
+
+
+
+
+
\ No newline at end of file
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/UserPermissionMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/UserPermissionMapper.xml
new file mode 100644
index 000000000..e16f02291
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/permission/UserPermissionMapper.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+ (#{permission.userID,jdbcType=INTEGER},
+ #{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
+ #{permission.objectIdentifier,jdbcType=INTEGER})
+
+
+
+
+
+
+
+ INSERT INTO guacamole_user_permission (
+ user_id,
+ permission,
+ affected_user_id
+ )
+ SELECT permissions.user_id, permissions.permission, guacamole_user.user_id FROM
+
+ SELECT #{permission.userID,jdbcType=INTEGER} AS user_id,
+ #{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type AS permission,
+ #{permission.objectIdentifier,jdbcType=INTEGER} AS username
+
+ AS permissions
+ JOIN guacamole_user ON guacamole_user.username = permissions.username;
+
+
+
+
\ No newline at end of file
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/user/UserMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/user/UserMapper.xml
new file mode 100644
index 000000000..41416f7db
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/user/UserMapper.xml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DELETE FROM guacamole_user
+ WHERE username = #{identifier,jdbcType=VARCHAR}
+
+
+
+
+
+ INSERT INTO guacamole_user (
+ username,
+ password_hash,
+ password_salt
+ )
+ VALUES (
+ #{object.identifier,jdbcType=VARCHAR},
+ #{object.passwordHash,jdbcType=BINARY},
+ #{object.passwordSalt,jdbcType=BINARY}
+ )
+
+
+
+
+
+ UPDATE guacamole_user
+ SET password_hash = #{object.passwordHash,jdbcType=BINARY},
+ password_salt = #{object.passwordSalt,jdbcType=BINARY}
+ WHERE user_id = #{object.objectID,jdbcType=VARCHAR}
+
+
+
diff --git a/extensions/guacamole-auth-jdbc/pom.xml b/extensions/guacamole-auth-jdbc/pom.xml
index c6c622994..49fb5c124 100644
--- a/extensions/guacamole-auth-jdbc/pom.xml
+++ b/extensions/guacamole-auth-jdbc/pom.xml
@@ -20,8 +20,9 @@
modules/guacamole-auth-jdbc-base
-
+
modules/guacamole-auth-jdbc-mysql
+ modules/guacamole-auth-jdbc-postgresql
diff --git a/extensions/guacamole-auth-jdbc/src/main/assembly/dist.xml b/extensions/guacamole-auth-jdbc/src/main/assembly/dist.xml
index 2d20b63a0..a416ea191 100644
--- a/extensions/guacamole-auth-jdbc/src/main/assembly/dist.xml
+++ b/extensions/guacamole-auth-jdbc/src/main/assembly/dist.xml
@@ -27,6 +27,19 @@
+
+
+ /postgresql/schema
+ modules/guacamole-auth-jdbc-postgresql/schema
+
+
+ modules/guacamole-auth-jdbc-postgresql/target/extension
+ /postgresql
+
+ *.jar
+
+
+