Add .gitignore and .ratignore files for various directories
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
gyurix
2025-04-29 21:43:12 +02:00
parent 983ecbfc53
commit be9f66dee9
2167 changed files with 254128 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
target/
*~

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<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.apache.guacamole</groupId>
<artifactId>guacamole-auth-jdbc-postgresql</artifactId>
<packaging>jar</packaging>
<name>guacamole-auth-jdbc-postgresql</name>
<url>http://guacamole.apache.org/</url>
<parent>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-jdbc</artifactId>
<version>1.6.0</version>
<relativePath>../../</relativePath>
</parent>
<dependencies>
<!-- Guacamole Extension API -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-ext</artifactId>
<scope>provided</scope>
</dependency>
<!-- Guacamole JDBC Authentication -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-auth-jdbc-base</artifactId>
<version>1.6.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,737 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
--
-- Connection group types
--
CREATE TYPE guacamole_connection_group_type AS ENUM(
'ORGANIZATIONAL',
'BALANCING'
);
--
-- Entity types
--
CREATE TYPE guacamole_entity_type AS ENUM(
'USER',
'USER_GROUP'
);
--
-- 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_SHARING_PROFILE',
'CREATE_USER',
'CREATE_USER_GROUP',
'AUDIT',
'ADMINISTER'
);
--
-- Guacamole proxy (guacd) encryption methods
--
CREATE TYPE guacamole_proxy_encryption_method AS ENUM(
'NONE',
'SSL'
);
--
-- 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',
-- Concurrency limits
max_connections integer,
max_connections_per_user integer,
enable_session_affinity boolean NOT NULL DEFAULT FALSE,
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 guacamole_connection_group_parent_id
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,
-- Concurrency limits
max_connections integer,
max_connections_per_user integer,
-- Connection Weight
connection_weight integer,
failover_only boolean NOT NULL DEFAULT FALSE,
-- Guacamole proxy (guacd) overrides
proxy_port integer,
proxy_hostname varchar(512),
proxy_encryption_method guacamole_proxy_encryption_method,
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 guacamole_connection_parent_id
ON guacamole_connection(parent_id);
--
-- Table of base entities which may each be either a user or user group. Other
-- tables which represent qualities shared by both users and groups will point
-- to guacamole_entity, while tables which represent qualities specific to
-- users or groups will point to guacamole_user or guacamole_user_group.
--
CREATE TABLE guacamole_entity (
entity_id serial NOT NULL,
name varchar(128) NOT NULL,
type guacamole_entity_type NOT NULL,
PRIMARY KEY (entity_id),
CONSTRAINT guacamole_entity_name_scope
UNIQUE (type, name)
);
--
-- 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,
entity_id integer NOT NULL,
-- Optionally-salted password
password_hash bytea NOT NULL,
password_salt bytea,
password_date timestamptz NOT NULL,
-- Account disabled/expired status
disabled boolean NOT NULL DEFAULT FALSE,
expired boolean NOT NULL DEFAULT FALSE,
-- Time-based access restriction
access_window_start time,
access_window_end time,
-- Date-based access restriction
valid_from date,
valid_until date,
-- Timezone used for all date/time comparisons and interpretation
timezone varchar(64),
-- Profile information
full_name varchar(256),
email_address varchar(256),
organization varchar(256),
organizational_role varchar(256),
PRIMARY KEY (user_id),
CONSTRAINT guacamole_user_single_entity
UNIQUE (entity_id),
CONSTRAINT guacamole_user_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id)
ON DELETE CASCADE
);
--
-- Table of user groups. Each user group may have an arbitrary set of member
-- users and member groups, with those members inheriting the permissions
-- granted to that group.
--
CREATE TABLE guacamole_user_group (
user_group_id serial NOT NULL,
entity_id integer NOT NULL,
-- Group disabled status
disabled boolean NOT NULL DEFAULT FALSE,
PRIMARY KEY (user_group_id),
CONSTRAINT guacamole_user_group_single_entity
UNIQUE (entity_id),
CONSTRAINT guacamole_user_group_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id)
ON DELETE CASCADE
);
--
-- Table of users which are members of given user groups.
--
CREATE TABLE guacamole_user_group_member (
user_group_id integer NOT NULL,
member_entity_id integer NOT NULL,
PRIMARY KEY (user_group_id, member_entity_id),
-- Parent must be a user group
CONSTRAINT guacamole_user_group_member_parent
FOREIGN KEY (user_group_id)
REFERENCES guacamole_user_group (user_group_id) ON DELETE CASCADE,
-- Member may be either a user or a user group (any entity)
CONSTRAINT guacamole_user_group_member_entity
FOREIGN KEY (member_entity_id)
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
);
--
-- Table of sharing profiles. Each sharing profile has a name, associated set
-- of parameters, and a primary connection. The primary connection is the
-- connection that the sharing profile shares, and the parameters dictate the
-- restrictions/features which apply to the user joining the connection via the
-- sharing profile.
--
CREATE TABLE guacamole_sharing_profile (
sharing_profile_id serial NOT NULL,
sharing_profile_name varchar(128) NOT NULL,
primary_connection_id integer NOT NULL,
PRIMARY KEY (sharing_profile_id),
CONSTRAINT sharing_profile_name_primary
UNIQUE (sharing_profile_name, primary_connection_id),
CONSTRAINT guacamole_sharing_profile_ibfk_1
FOREIGN KEY (primary_connection_id)
REFERENCES guacamole_connection (connection_id)
ON DELETE CASCADE
);
CREATE INDEX guacamole_sharing_profile_primary_connection_id
ON guacamole_sharing_profile(primary_connection_id);
--
-- 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 guacamole_connection_parameter_connection_id
ON guacamole_connection_parameter(connection_id);
--
-- Table of sharing profile parameters. Each parameter is simply
-- name/value pair associated with a sharing profile. These parameters dictate
-- the restrictions/features which apply to the user joining the associated
-- connection via the sharing profile.
--
CREATE TABLE guacamole_sharing_profile_parameter (
sharing_profile_id integer NOT NULL,
parameter_name varchar(128) NOT NULL,
parameter_value varchar(4096) NOT NULL,
PRIMARY KEY (sharing_profile_id, parameter_name),
CONSTRAINT guacamole_sharing_profile_parameter_ibfk_1
FOREIGN KEY (sharing_profile_id)
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_sharing_profile_parameter_sharing_profile_id
ON guacamole_sharing_profile_parameter(sharing_profile_id);
--
-- Table of arbitrary user attributes. Each attribute is simply a name/value
-- pair associated with a user. Arbitrary attributes are defined by other
-- extensions. Attributes defined by this extension will be mapped to
-- properly-typed columns of a specific table.
--
CREATE TABLE guacamole_user_attribute (
user_id integer NOT NULL,
attribute_name varchar(128) NOT NULL,
attribute_value varchar(4096) NOT NULL,
PRIMARY KEY (user_id, attribute_name),
CONSTRAINT guacamole_user_attribute_ibfk_1
FOREIGN KEY (user_id)
REFERENCES guacamole_user (user_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_user_attribute_user_id
ON guacamole_user_attribute(user_id);
--
-- Table of arbitrary user group attributes. Each attribute is simply a
-- name/value pair associated with a user group. Arbitrary attributes are
-- defined by other extensions. Attributes defined by this extension will be
-- mapped to properly-typed columns of a specific table.
--
CREATE TABLE guacamole_user_group_attribute (
user_group_id integer NOT NULL,
attribute_name varchar(128) NOT NULL,
attribute_value varchar(4096) NOT NULL,
PRIMARY KEY (user_group_id, attribute_name),
CONSTRAINT guacamole_user_group_attribute_ibfk_1
FOREIGN KEY (user_group_id)
REFERENCES guacamole_user_group (user_group_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_user_group_attribute_user_group_id
ON guacamole_user_group_attribute(user_group_id);
--
-- Table of arbitrary connection attributes. Each attribute is simply a
-- name/value pair associated with a connection. Arbitrary attributes are
-- defined by other extensions. Attributes defined by this extension will be
-- mapped to properly-typed columns of a specific table.
--
CREATE TABLE guacamole_connection_attribute (
connection_id integer NOT NULL,
attribute_name varchar(128) NOT NULL,
attribute_value varchar(4096) NOT NULL,
PRIMARY KEY (connection_id, attribute_name),
CONSTRAINT guacamole_connection_attribute_ibfk_1
FOREIGN KEY (connection_id)
REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_connection_attribute_connection_id
ON guacamole_connection_attribute(connection_id);
--
-- Table of arbitrary connection group attributes. Each attribute is simply a
-- name/value pair associated with a connection group. Arbitrary attributes are
-- defined by other extensions. Attributes defined by this extension will be
-- mapped to properly-typed columns of a specific table.
--
CREATE TABLE guacamole_connection_group_attribute (
connection_group_id integer NOT NULL,
attribute_name varchar(128) NOT NULL,
attribute_value varchar(4096) NOT NULL,
PRIMARY KEY (connection_group_id, attribute_name),
CONSTRAINT guacamole_connection_group_attribute_ibfk_1
FOREIGN KEY (connection_group_id)
REFERENCES guacamole_connection_group (connection_group_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_connection_group_attribute_connection_group_id
ON guacamole_connection_group_attribute(connection_group_id);
--
-- Table of arbitrary sharing profile attributes. Each attribute is simply a
-- name/value pair associated with a sharing profile. Arbitrary attributes are
-- defined by other extensions. Attributes defined by this extension will be
-- mapped to properly-typed columns of a specific table.
--
CREATE TABLE guacamole_sharing_profile_attribute (
sharing_profile_id integer NOT NULL,
attribute_name varchar(128) NOT NULL,
attribute_value varchar(4096) NOT NULL,
PRIMARY KEY (sharing_profile_id, attribute_name),
CONSTRAINT guacamole_sharing_profile_attribute_ibfk_1
FOREIGN KEY (sharing_profile_id)
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_sharing_profile_attribute_sharing_profile_id
ON guacamole_sharing_profile_attribute(sharing_profile_id);
--
-- Table of connection permissions. Each connection permission grants a user or
-- user group specific access to a connection.
--
CREATE TABLE guacamole_connection_permission (
entity_id integer NOT NULL,
connection_id integer NOT NULL,
permission guacamole_object_permission_type NOT NULL,
PRIMARY KEY (entity_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_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_connection_permission_connection_id
ON guacamole_connection_permission(connection_id);
CREATE INDEX guacamole_connection_permission_entity_id
ON guacamole_connection_permission(entity_id);
--
-- Table of connection group permissions. Each group permission grants a user
-- or user group specific access to a connection group.
--
CREATE TABLE guacamole_connection_group_permission (
entity_id integer NOT NULL,
connection_group_id integer NOT NULL,
permission guacamole_object_permission_type NOT NULL,
PRIMARY KEY (entity_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_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_connection_group_permission_connection_group_id
ON guacamole_connection_group_permission(connection_group_id);
CREATE INDEX guacamole_connection_group_permission_entity_id
ON guacamole_connection_group_permission(entity_id);
--
-- Table of sharing profile permissions. Each sharing profile permission grants
-- a user or user group specific access to a sharing profile.
--
CREATE TABLE guacamole_sharing_profile_permission (
entity_id integer NOT NULL,
sharing_profile_id integer NOT NULL,
permission guacamole_object_permission_type NOT NULL,
PRIMARY KEY (entity_id, sharing_profile_id, permission),
CONSTRAINT guacamole_sharing_profile_permission_ibfk_1
FOREIGN KEY (sharing_profile_id)
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE,
CONSTRAINT guacamole_sharing_profile_permission_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_sharing_profile_permission_sharing_profile_id
ON guacamole_sharing_profile_permission(sharing_profile_id);
CREATE INDEX guacamole_sharing_profile_permission_entity_id
ON guacamole_sharing_profile_permission(entity_id);
--
-- Table of system permissions. Each system permission grants a user or user
-- group a system-level privilege of some kind.
--
CREATE TABLE guacamole_system_permission (
entity_id integer NOT NULL,
permission guacamole_system_permission_type NOT NULL,
PRIMARY KEY (entity_id, permission),
CONSTRAINT guacamole_system_permission_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_system_permission_entity_id
ON guacamole_system_permission(entity_id);
--
-- Table of user permissions. Each user permission grants a user or user group
-- access to another user (the "affected" user) for a specific type of
-- operation.
--
CREATE TABLE guacamole_user_permission (
entity_id integer NOT NULL,
affected_user_id integer NOT NULL,
permission guacamole_object_permission_type NOT NULL,
PRIMARY KEY (entity_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_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_user_permission_affected_user_id
ON guacamole_user_permission(affected_user_id);
CREATE INDEX guacamole_user_permission_entity_id
ON guacamole_user_permission(entity_id);
--
-- Table of user group permissions. Each user group permission grants a user
-- or user group access to a another user group (the "affected" user group) for
-- a specific type of operation.
--
CREATE TABLE guacamole_user_group_permission (
entity_id integer NOT NULL,
affected_user_group_id integer NOT NULL,
permission guacamole_object_permission_type NOT NULL,
PRIMARY KEY (entity_id, affected_user_group_id, permission),
CONSTRAINT guacamole_user_group_permission_affected_user_group
FOREIGN KEY (affected_user_group_id)
REFERENCES guacamole_user_group (user_group_id) ON DELETE CASCADE,
CONSTRAINT guacamole_user_group_permission_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_user_group_permission_affected_user_group_id
ON guacamole_user_group_permission(affected_user_group_id);
CREATE INDEX guacamole_user_group_permission_entity_id
ON guacamole_user_group_permission(entity_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 DEFAULT NULL,
username varchar(128) NOT NULL,
remote_host varchar(256) DEFAULT NULL,
connection_id integer DEFAULT NULL,
connection_name varchar(128) NOT NULL,
sharing_profile_id integer DEFAULT NULL,
sharing_profile_name varchar(128) DEFAULT 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 SET NULL,
CONSTRAINT guacamole_connection_history_ibfk_2
FOREIGN KEY (connection_id)
REFERENCES guacamole_connection (connection_id) ON DELETE SET NULL,
CONSTRAINT guacamole_connection_history_ibfk_3
FOREIGN KEY (sharing_profile_id)
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE SET NULL
);
CREATE INDEX guacamole_connection_history_user_id
ON guacamole_connection_history(user_id);
CREATE INDEX guacamole_connection_history_connection_id
ON guacamole_connection_history(connection_id);
CREATE INDEX guacamole_connection_history_sharing_profile_id
ON guacamole_connection_history(sharing_profile_id);
CREATE INDEX guacamole_connection_history_start_date
ON guacamole_connection_history(start_date);
CREATE INDEX guacamole_connection_history_end_date
ON guacamole_connection_history(end_date);
CREATE INDEX guacamole_connection_history_connection_id_start_date
ON guacamole_connection_history(connection_id, start_date);
--
-- User login/logout history
--
CREATE TABLE guacamole_user_history (
history_id serial NOT NULL,
user_id integer DEFAULT NULL,
username varchar(128) NOT NULL,
remote_host varchar(256) DEFAULT NULL,
start_date timestamptz NOT NULL,
end_date timestamptz DEFAULT NULL,
PRIMARY KEY (history_id),
CONSTRAINT guacamole_user_history_ibfk_1
FOREIGN KEY (user_id)
REFERENCES guacamole_user (user_id) ON DELETE SET NULL
);
CREATE INDEX guacamole_user_history_user_id
ON guacamole_user_history(user_id);
CREATE INDEX guacamole_user_history_start_date
ON guacamole_user_history(start_date);
CREATE INDEX guacamole_user_history_end_date
ON guacamole_user_history(end_date);
CREATE INDEX guacamole_user_history_user_id_start_date
ON guacamole_user_history(user_id, start_date);
--
-- User password history
--
CREATE TABLE guacamole_user_password_history (
password_history_id serial NOT NULL,
user_id integer NOT NULL,
-- Salted password
password_hash bytea NOT NULL,
password_salt bytea,
password_date timestamptz NOT NULL,
PRIMARY KEY (password_history_id),
CONSTRAINT guacamole_user_password_history_ibfk_1
FOREIGN KEY (user_id)
REFERENCES guacamole_user (user_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_user_password_history_user_id
ON guacamole_user_password_history(user_id);

View File

@@ -0,0 +1,56 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
-- Create default user "guacadmin" with password "guacadmin"
INSERT INTO guacamole_entity (name, type) VALUES ('guacadmin', 'USER');
INSERT INTO guacamole_user (entity_id, password_hash, password_salt, password_date)
SELECT
entity_id,
decode('CA458A7D494E3BE824F5E1E175A1556C0F8EEF2C2D7DF3633BEC4A29C4411960', 'hex'), -- 'guacadmin'
decode('FE24ADC5E11E2B25288D1704ABE67A79E342ECC26064CE69C5B3177795A82264', 'hex'),
CURRENT_TIMESTAMP
FROM guacamole_entity WHERE name = 'guacadmin' AND guacamole_entity.type = 'USER';
-- Grant this user all system permissions
INSERT INTO guacamole_system_permission (entity_id, permission)
SELECT entity_id, permission::guacamole_system_permission_type
FROM (
VALUES
('guacadmin', 'CREATE_CONNECTION'),
('guacadmin', 'CREATE_CONNECTION_GROUP'),
('guacadmin', 'CREATE_SHARING_PROFILE'),
('guacadmin', 'CREATE_USER'),
('guacadmin', 'CREATE_USER_GROUP'),
('guacadmin', 'ADMINISTER')
) permissions (username, permission)
JOIN guacamole_entity ON permissions.username = guacamole_entity.name AND guacamole_entity.type = 'USER';
-- Grant admin permission to read/update/administer self
INSERT INTO guacamole_user_permission (entity_id, affected_user_id, permission)
SELECT guacamole_entity.entity_id, guacamole_user.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_entity ON permissions.username = guacamole_entity.name AND guacamole_entity.type = 'USER'
JOIN guacamole_entity affected ON permissions.affected_username = affected.name AND guacamole_entity.type = 'USER'
JOIN guacamole_user ON guacamole_user.entity_id = affected.entity_id;

View File

@@ -0,0 +1,196 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
--
-- User and connection IDs within history table can now be null
--
ALTER TABLE guacamole_connection_history
ALTER COLUMN user_id SET DEFAULT NULL,
ALTER COLUMN user_id DROP NOT NULL;
ALTER TABLE guacamole_connection_history
ALTER COLUMN connection_id SET DEFAULT NULL,
ALTER COLUMN connection_id DROP NOT NULL;
--
-- Add new username and connection_name columns to history table
--
ALTER TABLE guacamole_connection_history
ADD COLUMN username varchar(128);
ALTER TABLE guacamole_connection_history
ADD COLUMN connection_name varchar(128);
--
-- Populate new name columns by joining corresponding tables
--
UPDATE guacamole_connection_history
SET username = guacamole_user.username
FROM guacamole_user
WHERE guacamole_user.user_id = guacamole_connection_history.user_id;
UPDATE guacamole_connection_history
SET connection_name = guacamole_connection.connection_name
FROM guacamole_connection
WHERE guacamole_connection.connection_id =
guacamole_connection_history.connection_id;
--
-- Set NOT NULL now that the column is fully populated
--
ALTER TABLE guacamole_connection_history
ALTER COLUMN username SET NOT NULL;
ALTER TABLE guacamole_connection_history
ALTER COLUMN connection_name SET NOT NULL;
--
-- Remove old foreign key constraints with ON DELETE CASCADE
--
ALTER TABLE guacamole_connection_history
DROP CONSTRAINT guacamole_connection_history_ibfk_1;
ALTER TABLE guacamole_connection_history
DROP CONSTRAINT guacamole_connection_history_ibfk_2;
--
-- Recreate foreign key constraints with ON DELETE SET NULL
--
ALTER TABLE guacamole_connection_history
ADD CONSTRAINT guacamole_connection_history_ibfk_1
FOREIGN KEY (user_id)
REFERENCES guacamole_user (user_id) ON DELETE SET NULL;
ALTER TABLE guacamole_connection_history
ADD CONSTRAINT guacamole_connection_history_ibfk_2
FOREIGN KEY (connection_id)
REFERENCES guacamole_connection (connection_id) ON DELETE SET NULL;
--
-- Add session affinity column
--
ALTER TABLE guacamole_connection_group
ADD COLUMN enable_session_affinity boolean NOT NULL DEFAULT FALSE;
--
-- Add new system-level permission
--
ALTER TYPE guacamole_system_permission_type
ADD VALUE 'CREATE_SHARING_PROFILE'
AFTER 'CREATE_CONNECTION_GROUP';
--
-- Add sharing profile table
--
CREATE TABLE guacamole_sharing_profile (
sharing_profile_id serial NOT NULL,
sharing_profile_name varchar(128) NOT NULL,
primary_connection_id integer NOT NULL,
PRIMARY KEY (sharing_profile_id),
CONSTRAINT sharing_profile_name_primary
UNIQUE (sharing_profile_name, primary_connection_id),
CONSTRAINT guacamole_sharing_profile_ibfk_1
FOREIGN KEY (primary_connection_id)
REFERENCES guacamole_connection (connection_id)
ON DELETE CASCADE
);
CREATE INDEX guacamole_sharing_profile_primary_connection_id
ON guacamole_sharing_profile(primary_connection_id);
--
-- Add table of sharing profile parameters
--
CREATE TABLE guacamole_sharing_profile_parameter (
sharing_profile_id integer NOT NULL,
parameter_name varchar(128) NOT NULL,
parameter_value varchar(4096) NOT NULL,
PRIMARY KEY (sharing_profile_id, parameter_name),
CONSTRAINT guacamole_sharing_profile_parameter_ibfk_1
FOREIGN KEY (sharing_profile_id)
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_sharing_profile_parameter_sharing_profile_id
ON guacamole_sharing_profile_parameter(sharing_profile_id);
--
-- Object-level permission table for sharing profiles
--
CREATE TABLE guacamole_sharing_profile_permission (
user_id integer NOT NULL,
sharing_profile_id integer NOT NULL,
permission guacamole_object_permission_type NOT NULL,
PRIMARY KEY (user_id,sharing_profile_id,permission),
CONSTRAINT guacamole_sharing_profile_permission_ibfk_1
FOREIGN KEY (sharing_profile_id)
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE,
CONSTRAINT guacamole_sharing_profile_permission_ibfk_2
FOREIGN KEY (user_id)
REFERENCES guacamole_user (user_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_sharing_profile_permission_sharing_profile_id
ON guacamole_sharing_profile_permission(sharing_profile_id);
CREATE INDEX guacamole_sharing_profile_permission_user_id
ON guacamole_sharing_profile_permission(user_id);
--
-- Add new (optional) sharing profile ID and name columns to connection history
--
ALTER TABLE guacamole_connection_history
ADD COLUMN sharing_profile_id integer;
ALTER TABLE guacamole_connection_history
ADD COLUMN sharing_profile_name varchar(128);
ALTER TABLE guacamole_connection_history
ADD CONSTRAINT guacamole_connection_history_ibfk_3
FOREIGN KEY (sharing_profile_id)
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE SET NULL;
CREATE INDEX guacamole_connection_history_sharing_profile_id
ON guacamole_connection_history(sharing_profile_id);

View File

@@ -0,0 +1,55 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
--
-- Add per-user password set date
--
ALTER TABLE guacamole_user
ADD COLUMN password_date timestamptz;
UPDATE guacamole_user SET password_date = CURRENT_TIMESTAMP;
ALTER TABLE guacamole_user
ALTER COLUMN password_date SET NOT NULL;
--
-- User password history
--
CREATE TABLE guacamole_user_password_history (
password_history_id serial NOT NULL,
user_id integer NOT NULL,
-- Salted password
password_hash bytea NOT NULL,
password_salt bytea,
password_date timestamptz NOT NULL,
PRIMARY KEY (password_history_id),
CONSTRAINT guacamole_user_password_history_ibfk_1
FOREIGN KEY (user_id)
REFERENCES guacamole_user (user_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_user_password_history_user_id
ON guacamole_user_password_history(user_id);

View File

@@ -0,0 +1,45 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
--
-- Add new guacd encryption method type
--
CREATE TYPE guacamole_proxy_encryption_method AS ENUM(
'NONE',
'SSL'
);
--
-- Add guacd per-connection override columns
--
ALTER TABLE guacamole_connection ADD COLUMN proxy_port integer;
ALTER TABLE guacamole_connection ADD COLUMN proxy_hostname varchar(512);
ALTER TABLE guacamole_connection ADD COLUMN proxy_encryption_method guacamole_proxy_encryption_method;
--
-- Add new user profile columns
--
ALTER TABLE guacamole_user ADD COLUMN full_name VARCHAR(256);
ALTER TABLE guacamole_user ADD COLUMN email_address VARCHAR(256);
ALTER TABLE guacamole_user ADD COLUMN organization VARCHAR(256);
ALTER TABLE guacamole_user ADD COLUMN organizational_role VARCHAR(256);

View File

@@ -0,0 +1,79 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
--
-- Add per-connection weight
--
ALTER TABLE guacamole_connection
ADD COLUMN connection_weight int;
--
-- Add failover-only flag
--
ALTER TABLE guacamole_connection
ADD COLUMN failover_only BOOLEAN NOT NULL DEFAULT FALSE;
--
-- Add remote_host to connection history
--
ALTER TABLE guacamole_connection_history
ADD COLUMN remote_host VARCHAR(256) DEFAULT NULL;
--
-- Add covering index for connection history connection and start date
--
CREATE INDEX guacamole_connection_history_connection_id_start_date
ON guacamole_connection_history(connection_id, start_date);
--
-- User login/logout history
--
CREATE TABLE guacamole_user_history (
history_id serial NOT NULL,
user_id integer DEFAULT NULL,
username varchar(128) NOT NULL,
remote_host varchar(256) DEFAULT NULL,
start_date timestamptz NOT NULL,
end_date timestamptz DEFAULT NULL,
PRIMARY KEY (history_id),
CONSTRAINT guacamole_user_history_ibfk_1
FOREIGN KEY (user_id)
REFERENCES guacamole_user (user_id) ON DELETE SET NULL
);
CREATE INDEX guacamole_user_history_user_id
ON guacamole_user_history(user_id);
CREATE INDEX guacamole_user_history_start_date
ON guacamole_user_history(start_date);
CREATE INDEX guacamole_user_history_end_date
ON guacamole_user_history(end_date);
CREATE INDEX guacamole_user_history_user_id_start_date
ON guacamole_user_history(user_id, start_date);

View File

@@ -0,0 +1,31 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
--
-- Add per-user disable flag
--
ALTER TABLE guacamole_user ADD COLUMN disabled boolean NOT NULL DEFAULT FALSE;
--
-- Add per-user password expiration flag
--
ALTER TABLE guacamole_user ADD COLUMN expired boolean NOT NULL DEFAULT FALSE;

View File

@@ -0,0 +1,52 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
--
-- Add per-user time-based access restrictions.
--
ALTER TABLE guacamole_user ADD COLUMN access_window_start time;
ALTER TABLE guacamole_user ADD COLUMN access_window_end time;
--
-- Add per-user date-based account validity restrictions.
--
ALTER TABLE guacamole_user ADD COLUMN valid_from date;
ALTER TABLE guacamole_user ADD COLUMN valid_until date;
--
-- Add per-user timezone for sake of time comparisons/interpretation.
--
ALTER TABLE guacamole_user ADD COLUMN timezone varchar(64);
--
-- Add connection concurrency limits
--
ALTER TABLE guacamole_connection ADD COLUMN max_connections integer;
ALTER TABLE guacamole_connection ADD COLUMN max_connections_per_user integer;
--
-- Add connection group concurrency limits
--
ALTER TABLE guacamole_connection_group ADD COLUMN max_connections integer;
ALTER TABLE guacamole_connection_group ADD COLUMN max_connections_per_user integer;

View File

@@ -0,0 +1,32 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
--
-- Ensure history entry start/end dates are indexed.
--
CREATE INDEX guacamole_connection_history_start_date
ON guacamole_connection_history(start_date);
CREATE INDEX guacamole_connection_history_end_date
ON guacamole_connection_history(end_date);
CREATE INDEX guacamole_connection_history_search_index
ON guacamole_connection_history(start_date, connection_id, user_id);

View File

@@ -0,0 +1,471 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
--
-- Add new system-level permission
--
ALTER TYPE guacamole_system_permission_type
ADD VALUE 'CREATE_USER_GROUP'
AFTER 'CREATE_USER';
--
-- Entity types
--
CREATE TYPE guacamole_entity_type AS ENUM(
'USER',
'USER_GROUP'
);
--
-- Table of base entities which may each be either a user or user group. Other
-- tables which represent qualities shared by both users and groups will point
-- to guacamole_entity, while tables which represent qualities specific to
-- users or groups will point to guacamole_user or guacamole_user_group.
--
CREATE TABLE guacamole_entity (
entity_id serial NOT NULL,
name varchar(128) NOT NULL,
type guacamole_entity_type NOT NULL,
PRIMARY KEY (entity_id),
CONSTRAINT guacamole_entity_name_scope
UNIQUE (type, name)
);
--
-- Table of user groups. Each user group may have an arbitrary set of member
-- users and member groups, with those members inheriting the permissions
-- granted to that group.
--
CREATE TABLE guacamole_user_group (
user_group_id serial NOT NULL,
entity_id integer NOT NULL,
-- Group disabled status
disabled boolean NOT NULL DEFAULT FALSE,
PRIMARY KEY (user_group_id),
CONSTRAINT guacamole_user_group_single_entity
UNIQUE (entity_id),
CONSTRAINT guacamole_user_group_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id)
ON DELETE CASCADE
);
--
-- Table of users which are members of given user groups.
--
CREATE TABLE guacamole_user_group_member (
user_group_id integer NOT NULL,
member_entity_id integer NOT NULL,
PRIMARY KEY (user_group_id, member_entity_id),
-- Parent must be a user group
CONSTRAINT guacamole_user_group_member_parent
FOREIGN KEY (user_group_id)
REFERENCES guacamole_user_group (user_group_id) ON DELETE CASCADE,
-- Member may be either a user or a user group (any entity)
CONSTRAINT guacamole_user_group_member_entity
FOREIGN KEY (member_entity_id)
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
);
--
-- Table of user group permissions. Each user group permission grants a user
-- access to a particular user group for a specific type of operation.
--
CREATE TABLE guacamole_user_group_permission (
entity_id integer NOT NULL,
affected_user_group_id integer NOT NULL,
permission guacamole_object_permission_type NOT NULL,
PRIMARY KEY (entity_id, affected_user_group_id, permission),
CONSTRAINT guacamole_user_group_permission_affected_user_group
FOREIGN KEY (affected_user_group_id)
REFERENCES guacamole_user_group (user_group_id) ON DELETE CASCADE,
CONSTRAINT guacamole_user_group_permission_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_user_group_permission_affected_user_group_id
ON guacamole_user_group_permission(affected_user_group_id);
CREATE INDEX guacamole_user_group_permission_entity_id
ON guacamole_user_group_permission(entity_id);
--
-- Modify guacamole_user table to use guacamole_entity as a base
--
-- Add new entity_id column
ALTER TABLE guacamole_user ADD COLUMN entity_id integer;
-- Create user entities for each guacamole_user entry
INSERT INTO guacamole_entity (name, type)
SELECT username, 'USER' FROM guacamole_user;
-- Update guacamole_user to point to corresponding guacamole_entity
UPDATE guacamole_user SET entity_id = (
SELECT entity_id FROM guacamole_entity
WHERE
username = guacamole_entity.name
AND type = 'USER'
);
-- The entity_id column should now be safely non-NULL
ALTER TABLE guacamole_user
ALTER COLUMN entity_id SET NOT NULL;
-- The entity_id column should now be unique for each user
ALTER TABLE guacamole_user
ADD CONSTRAINT guacamole_user_single_entity
UNIQUE (entity_id);
-- The entity_id column should now safely point to guacamole_entity entries
ALTER TABLE guacamole_user
ADD CONSTRAINT guacamole_user_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id)
ON DELETE CASCADE;
-- The username column can now safely be removed
ALTER TABLE guacamole_user DROP COLUMN username;
--
-- Modify guacamole_connection_permission to use guacamole_entity instead of
-- guacamole_user
--
-- Add new entity_id column
ALTER TABLE guacamole_connection_permission ADD COLUMN entity_id integer;
-- Update guacamole_connection_permission to point to the guacamole_entity
-- that has been granted the permission
UPDATE guacamole_connection_permission SET entity_id = (
SELECT entity_id FROM guacamole_user
WHERE guacamole_user.user_id = guacamole_connection_permission.user_id
);
-- The entity_id column should now be safely non-NULL
ALTER TABLE guacamole_connection_permission
ALTER COLUMN entity_id SET NOT NULL;
-- The entity_id column should now safely point to guacamole_entity entries
ALTER TABLE guacamole_connection_permission
ADD CONSTRAINT guacamole_connection_permission_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id)
ON DELETE CASCADE;
CREATE INDEX guacamole_connection_permission_entity_id
ON guacamole_connection_permission(entity_id);
-- Remove user_id column (implicitly drops associated contraints/keys)
ALTER TABLE guacamole_connection_permission DROP COLUMN user_id;
-- Add new primary key which uses entity_id
ALTER TABLE guacamole_connection_permission
ADD PRIMARY KEY (entity_id, connection_id, permission);
--
-- Modify guacamole_connection_group_permission to use guacamole_entity instead
-- of guacamole_user
--
-- Add new entity_id column
ALTER TABLE guacamole_connection_group_permission ADD COLUMN entity_id integer;
-- Update guacamole_connection_group_permission to point to the guacamole_entity
-- that has been granted the permission
UPDATE guacamole_connection_group_permission SET entity_id = (
SELECT entity_id FROM guacamole_user
WHERE guacamole_user.user_id = guacamole_connection_group_permission.user_id
);
-- The entity_id column should now be safely non-NULL
ALTER TABLE guacamole_connection_group_permission
ALTER COLUMN entity_id SET NOT NULL;
-- The entity_id column should now safely point to guacamole_entity entries
ALTER TABLE guacamole_connection_group_permission
ADD CONSTRAINT guacamole_connection_group_permission_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id)
ON DELETE CASCADE;
CREATE INDEX guacamole_connection_group_permission_entity_id
ON guacamole_connection_group_permission(entity_id);
-- Remove user_id column (implicitly drops associated contraints/keys)
ALTER TABLE guacamole_connection_group_permission DROP COLUMN user_id;
-- Add new primary key which uses entity_id
ALTER TABLE guacamole_connection_group_permission
ADD PRIMARY KEY (entity_id, connection_group_id, permission);
--
-- Modify guacamole_sharing_profile_permission to use guacamole_entity instead
-- of guacamole_user
--
-- Add new entity_id column
ALTER TABLE guacamole_sharing_profile_permission ADD COLUMN entity_id integer;
-- Update guacamole_sharing_profile_permission to point to the guacamole_entity
-- that has been granted the permission
UPDATE guacamole_sharing_profile_permission SET entity_id = (
SELECT entity_id FROM guacamole_user
WHERE guacamole_user.user_id = guacamole_sharing_profile_permission.user_id
);
-- The entity_id column should now be safely non-NULL
ALTER TABLE guacamole_sharing_profile_permission
ALTER COLUMN entity_id SET NOT NULL;
-- The entity_id column should now safely point to guacamole_entity entries
ALTER TABLE guacamole_sharing_profile_permission
ADD CONSTRAINT guacamole_sharing_profile_permission_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id)
ON DELETE CASCADE;
CREATE INDEX guacamole_sharing_profile_permission_entity_id
ON guacamole_sharing_profile_permission(entity_id);
-- Remove user_id column (implicitly drops associated contraints/keys)
ALTER TABLE guacamole_sharing_profile_permission DROP COLUMN user_id;
-- Add new primary key which uses entity_id
ALTER TABLE guacamole_sharing_profile_permission
ADD PRIMARY KEY (entity_id, sharing_profile_id, permission);
--
-- Modify guacamole_user_permission to use guacamole_entity instead of
-- guacamole_user
--
-- Add new entity_id column
ALTER TABLE guacamole_user_permission ADD COLUMN entity_id integer;
-- Update guacamole_user_permission to point to the guacamole_entity
-- that has been granted the permission
UPDATE guacamole_user_permission SET entity_id = (
SELECT entity_id FROM guacamole_user
WHERE guacamole_user.user_id = guacamole_user_permission.user_id
);
-- The entity_id column should now be safely non-NULL
ALTER TABLE guacamole_user_permission
ALTER COLUMN entity_id SET NOT NULL;
-- The entity_id column should now safely point to guacamole_entity entries
ALTER TABLE guacamole_user_permission
ADD CONSTRAINT guacamole_user_permission_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id)
ON DELETE CASCADE;
CREATE INDEX guacamole_user_permission_entity_id
ON guacamole_user_permission(entity_id);
-- Remove user_id column (implicitly drops associated contraints/keys)
ALTER TABLE guacamole_user_permission DROP COLUMN user_id;
-- Add new primary key which uses entity_id
ALTER TABLE guacamole_user_permission
ADD PRIMARY KEY (entity_id, affected_user_id, permission);
--
-- Modify guacamole_system_permission to use guacamole_entity instead of
-- guacamole_user
--
-- Add new entity_id column
ALTER TABLE guacamole_system_permission ADD COLUMN entity_id integer;
-- Update guacamole_system_permission to point to the guacamole_entity
-- that has been granted the permission
UPDATE guacamole_system_permission SET entity_id = (
SELECT entity_id FROM guacamole_user
WHERE guacamole_user.user_id = guacamole_system_permission.user_id
);
-- The entity_id column should now be safely non-NULL
ALTER TABLE guacamole_system_permission
ALTER COLUMN entity_id SET NOT NULL;
-- The entity_id column should now safely point to guacamole_entity entries
ALTER TABLE guacamole_system_permission
ADD CONSTRAINT guacamole_system_permission_entity
FOREIGN KEY (entity_id)
REFERENCES guacamole_entity (entity_id)
ON DELETE CASCADE;
CREATE INDEX guacamole_system_permission_entity_id
ON guacamole_system_permission(entity_id);
-- Remove user_id column (implicitly drops associated contraints/keys)
ALTER TABLE guacamole_system_permission DROP COLUMN user_id;
-- Add new primary key which uses entity_id
ALTER TABLE guacamole_system_permission
ADD PRIMARY KEY (entity_id, permission);
--
-- Table of arbitrary user attributes. Each attribute is simply a name/value
-- pair associated with a user. Arbitrary attributes are defined by other
-- extensions. Attributes defined by this extension will be mapped to
-- properly-typed columns of a specific table.
--
CREATE TABLE guacamole_user_attribute (
user_id integer NOT NULL,
attribute_name varchar(128) NOT NULL,
attribute_value varchar(4096) NOT NULL,
PRIMARY KEY (user_id, attribute_name),
CONSTRAINT guacamole_user_attribute_ibfk_1
FOREIGN KEY (user_id)
REFERENCES guacamole_user (user_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_user_attribute_user_id
ON guacamole_user_attribute(user_id);
--
-- Table of arbitrary user group attributes. Each attribute is simply a
-- name/value pair associated with a user group. Arbitrary attributes are
-- defined by other extensions. Attributes defined by this extension will be
-- mapped to properly-typed columns of a specific table.
--
CREATE TABLE guacamole_user_group_attribute (
user_group_id integer NOT NULL,
attribute_name varchar(128) NOT NULL,
attribute_value varchar(4096) NOT NULL,
PRIMARY KEY (user_group_id, attribute_name),
CONSTRAINT guacamole_user_group_attribute_ibfk_1
FOREIGN KEY (user_group_id)
REFERENCES guacamole_user_group (user_group_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_user_group_attribute_user_group_id
ON guacamole_user_group_attribute(user_group_id);
--
-- Table of arbitrary connection attributes. Each attribute is simply a
-- name/value pair associated with a connection. Arbitrary attributes are
-- defined by other extensions. Attributes defined by this extension will be
-- mapped to properly-typed columns of a specific table.
--
CREATE TABLE guacamole_connection_attribute (
connection_id integer NOT NULL,
attribute_name varchar(128) NOT NULL,
attribute_value varchar(4096) NOT NULL,
PRIMARY KEY (connection_id, attribute_name),
CONSTRAINT guacamole_connection_attribute_ibfk_1
FOREIGN KEY (connection_id)
REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_connection_attribute_connection_id
ON guacamole_connection_attribute(connection_id);
--
-- Table of arbitrary connection group attributes. Each attribute is simply a
-- name/value pair associated with a connection group. Arbitrary attributes are
-- defined by other extensions. Attributes defined by this extension will be
-- mapped to properly-typed columns of a specific table.
--
CREATE TABLE guacamole_connection_group_attribute (
connection_group_id integer NOT NULL,
attribute_name varchar(128) NOT NULL,
attribute_value varchar(4096) NOT NULL,
PRIMARY KEY (connection_group_id, attribute_name),
CONSTRAINT guacamole_connection_group_attribute_ibfk_1
FOREIGN KEY (connection_group_id)
REFERENCES guacamole_connection_group (connection_group_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_connection_group_attribute_connection_group_id
ON guacamole_connection_group_attribute(connection_group_id);
--
-- Table of arbitrary sharing profile attributes. Each attribute is simply a
-- name/value pair associated with a sharing profile. Arbitrary attributes are
-- defined by other extensions. Attributes defined by this extension will be
-- mapped to properly-typed columns of a specific table.
--
CREATE TABLE guacamole_sharing_profile_attribute (
sharing_profile_id integer NOT NULL,
attribute_name varchar(128) NOT NULL,
attribute_value varchar(4096) NOT NULL,
PRIMARY KEY (sharing_profile_id, attribute_name),
CONSTRAINT guacamole_sharing_profile_attribute_ibfk_1
FOREIGN KEY (sharing_profile_id)
REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
);
CREATE INDEX guacamole_sharing_profile_attribute_sharing_profile_id
ON guacamole_sharing_profile_attribute(sharing_profile_id);

View File

@@ -0,0 +1,27 @@
--
-- Licensed to the Apache Software Foundation (ASF) under one
-- or more contributor license agreements. See the NOTICE file
-- distributed with this work for additional information
-- regarding copyright ownership. The ASF licenses this file
-- to you under the Apache License, Version 2.0 (the
-- "License"); you may not use this file except in compliance
-- with the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing,
-- software distributed under the License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-- KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations
-- under the License.
--
--
-- Add new system-level audit permission
--
ALTER TYPE guacamole_system_permission_type
ADD VALUE 'AUDIT'
BEFORE 'ADMINISTER';

View File

@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.postgresql;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.InjectedAuthenticationProvider;
import org.apache.guacamole.auth.jdbc.JDBCAuthenticationProviderService;
/**
* Provides a PostgreSQL-based implementation of the AuthenticationProvider
* functionality.
*/
public class PostgreSQLAuthenticationProvider extends InjectedAuthenticationProvider {
/**
* 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 {
super(new PostgreSQLInjectorProvider(), JDBCAuthenticationProviderService.class);
}
@Override
public String getIdentifier() {
return "postgresql";
}
}

View File

@@ -0,0 +1,144 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.postgresql;
import com.google.inject.Binder;
import com.google.inject.Module;
import com.google.inject.name.Names;
import java.io.File;
import java.util.Properties;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.postgresql.conf.PostgreSQLEnvironment;
import org.apache.guacamole.auth.postgresql.conf.PostgreSQLSSLMode;
import org.mybatis.guice.datasource.helper.JdbcHelper;
/**
* Guice module which configures PostgreSQL-specific injections.
*/
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(PostgreSQLEnvironment environment)
throws GuacamoleException {
// Set the PostgreSQL-specific properties for MyBatis.
myBatisProperties.setProperty("mybatis.environment.id", "guacamole");
myBatisProperties.setProperty("JDBC.host", environment.getPostgreSQLHostname());
myBatisProperties.setProperty("JDBC.port", String.valueOf(environment.getPostgreSQLPort()));
myBatisProperties.setProperty("JDBC.schema", environment.getPostgreSQLDatabase());
myBatisProperties.setProperty("JDBC.autoCommit", "false");
myBatisProperties.setProperty("mybatis.pooled.pingEnabled", "true");
myBatisProperties.setProperty("mybatis.pooled.pingQuery", "SELECT 1");
// Only set if > 0. Underlying backend does not take 0 as not-set.
int defaultStatementTimeout = environment.getPostgreSQLDefaultStatementTimeout();
if (defaultStatementTimeout > 0) {
myBatisProperties.setProperty(
"mybatis.configuration.defaultStatementTimeout",
String.valueOf(defaultStatementTimeout)
);
}
// Use UTF-8 in database
driverProperties.setProperty("characterEncoding", "UTF-8");
// Check the SSL mode and set if configured.
PostgreSQLSSLMode sslMode = environment.getPostgreSQLSSLMode();
/**
* Older versions of the PostgreSQL JDBC driver do not support directly
* setting the "prefer" mode; however, the behavior defined by this
* mode is the default if nothing is set, so if that mode is requested
* in guacamole.properties we just don't set sslmode in the driver.
*/
if (sslMode != PostgreSQLSSLMode.PREFER)
driverProperties.setProperty("sslmode", sslMode.getDriverValue());
// If SSL is requested disabled, also set the legacy property.
if (sslMode == PostgreSQLSSLMode.DISABLE)
driverProperties.setProperty("ssl", "false");
// If SSL is enabled, check for and set other SSL properties.
else {
File sslClientCert = environment.getPostgreSQLSSLClientCertFile();
if (sslClientCert != null)
driverProperties.setProperty("sslcert", sslClientCert.getAbsolutePath());
File sslClientKey = environment.getPostgreSQLSSLClientKeyFile();
if (sslClientKey != null)
driverProperties.setProperty("sslkey", sslClientKey.getAbsolutePath());
File sslRootCert = environment.getPostgreSQLSSLClientRootCertFile();
if (sslRootCert != null)
driverProperties.setProperty("sslrootcert", sslRootCert.getAbsolutePath());
String sslClientKeyPassword = environment.getPostgreSQLSSLClientKeyPassword();
if (sslClientKeyPassword != null)
driverProperties.setProperty("sslpassword", sslClientKeyPassword);
}
// Handle case where TCP connection to database is silently dropped
driverProperties.setProperty(
"socketTimeout",
String.valueOf(environment.getPostgreSQLSocketTimeout())
);
}
@Override
public void configure(Binder binder) {
// Bind PostgreSQL-specific properties
JdbcHelper.PostgreSQL.configure(binder);
// Bind MyBatis properties
Names.bindProperties(binder, myBatisProperties);
// Bind JDBC driver properties
binder.bind(Properties.class)
.annotatedWith(Names.named("JDBC.driverProperties"))
.toInstance(driverProperties);
}
}

View File

@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.postgresql;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.JDBCAuthenticationProviderModule;
import org.apache.guacamole.auth.jdbc.JDBCInjectorProvider;
import org.apache.guacamole.auth.postgresql.conf.PostgreSQLEnvironment;
/**
* JDBCInjectorProvider implementation which configures Guice injections for
* connecting to a PostgreSQL database based on PostgreSQL-specific options
* provided via guacamole.properties.
*/
public class PostgreSQLInjectorProvider extends JDBCInjectorProvider {
@Override
protected Injector create() throws GuacamoleException {
// Get local environment
PostgreSQLEnvironment environment = new PostgreSQLEnvironment();
// Set up Guice injector
return Guice.createInjector(
new JDBCAuthenticationProviderModule(environment),
new PostgreSQLAuthenticationProviderModule(environment)
);
}
}

View File

@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.postgresql;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.InjectedAuthenticationProvider;
import org.apache.guacamole.auth.jdbc.sharing.SharedAuthenticationProviderService;
/**
* Provides a implementation of AuthenticationProvider which interacts with the
* PostgreSQL AuthenticationProvider, accepting share keys as credentials and
* providing access to the shared connections.
*/
public class PostgreSQLSharedAuthenticationProvider extends InjectedAuthenticationProvider {
/**
* Creates a new PostgreSQLSharedAuthenticationProvider that provides access
* to shared connections exposed by the PostgreSQLAuthenticationProvider.
*
* @throws GuacamoleException
* If a required property is missing, or an error occurs while parsing
* a property.
*/
public PostgreSQLSharedAuthenticationProvider() throws GuacamoleException {
super(new PostgreSQLInjectorProvider(), SharedAuthenticationProviderService.class);
}
@Override
public String getIdentifier() {
return "postgresql-shared";
}
}

View File

@@ -0,0 +1,395 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.postgresql.conf;
import java.io.File;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
import org.apache.ibatis.session.SqlSession;
/**
* A PostgreSQL-specific implementation of JDBCEnvironment provides database
* properties specifically for PostgreSQL.
*/
public class PostgreSQLEnvironment extends JDBCEnvironment {
/**
* The default host to connect to, if POSTGRESQL_HOSTNAME is not specified.
*/
private static final String DEFAULT_HOSTNAME = "localhost";
/**
* The default port to connect to, if POSTGRESQL_PORT is not specified.
*/
private static final int DEFAULT_PORT = 5432;
/**
* The default number of seconds the driver will wait for a response from
* the database, before aborting the query.
* A value of 0 (the default) means the timeout is disabled.
*/
private static final int DEFAULT_STATEMENT_TIMEOUT = 0;
/**
* The default number of seconds to wait for socket read operations.
* A value of 0 (the default) means the timeout is disabled.
*/
private static final int DEFAULT_SOCKET_TIMEOUT = 0;
/**
* Whether a database user account is required by default for authentication
* to succeed.
*/
private static final boolean DEFAULT_USER_REQUIRED = false;
/**
* The default value for the maximum number of connections to be
* allowed to the Guacamole server overall.
*/
private final int DEFAULT_ABSOLUTE_MAX_CONNECTIONS = 0;
/**
* The default value for the default maximum number of connections to be
* allowed per user to any one connection. Note that, as long as the
* legacy "disallow duplicate" and "disallow simultaneous" properties are
* still supported, these cannot be constants, as the legacy properties
* dictate the values that should be used in the absence of the correct
* properties.
*/
private final int DEFAULT_MAX_CONNECTIONS_PER_USER = 0;
/**
* The default value for the default maximum number of connections to be
* allowed per user to any one connection group. Note that, as long as the
* legacy "disallow duplicate" and "disallow simultaneous" properties are
* still supported, these cannot be constants, as the legacy properties
* dictate the values that should be used in the absence of the correct
* properties.
*/
private final int DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER = 1;
/**
* The default value for the default maximum number of connections to be
* allowed to any one connection. Note that, as long as the legacy
* "disallow duplicate" and "disallow simultaneous" properties are still
* supported, these cannot be constants, as the legacy properties dictate
* the values that should be used in the absence of the correct properties.
*/
private final int DEFAULT_MAX_CONNECTIONS = 0;
/**
* The default value for the default maximum number of connections to be
* allowed to any one connection group. Note that, as long as the legacy
* "disallow duplicate" and "disallow simultaneous" properties are still
* supported, these cannot be constants, as the legacy properties dictate
* the values that should be used in the absence of the correct properties.
*/
private final int DEFAULT_MAX_GROUP_CONNECTIONS = 0;
/**
* The default value to use for SSL mode if none is explicitly configured.
*/
private final PostgreSQLSSLMode DEFAULT_SSL_MODE = PostgreSQLSSLMode.PREFER;
/**
* The default maximum number of identifiers/parameters to be included in a
* single batch when executing SQL statements for PostgreSQL.
*
* PostgreSQL has a maximum limit of 65535 parameters per prepared statement.
* A value of 5000 is chosen to avoid potential performance issues or query
* execution errors while staying well below the maximum limit.
*
* @see https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-MAX-PREPARED-STATEMENT-ARGS
*/
private static final int DEFAULT_BATCH_SIZE = 5000;
/**
* Constructs a new PostgreSQLEnvironment, providing access to PostgreSQL-specific
* configuration options.
*
* @throws GuacamoleException
* If an error occurs while setting up the underlying JDBCEnvironment
* or while parsing legacy PostgreSQL configuration options.
*/
public PostgreSQLEnvironment() throws GuacamoleException {
// Init underlying JDBC environment
super();
}
@Override
public boolean isUserRequired() throws GuacamoleException {
return getProperty(
PostgreSQLGuacamoleProperties.POSTGRESQL_USER_REQUIRED,
DEFAULT_USER_REQUIRED
);
}
@Override
public int getAbsoluteMaxConnections() throws GuacamoleException {
return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_ABSOLUTE_MAX_CONNECTIONS,
DEFAULT_ABSOLUTE_MAX_CONNECTIONS
);
}
@Override
public int getBatchSize() throws GuacamoleException {
return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_BATCH_SIZE,
DEFAULT_BATCH_SIZE
);
}
@Override
public int getDefaultMaxConnections() throws GuacamoleException {
return getProperty(
PostgreSQLGuacamoleProperties.POSTGRESQL_DEFAULT_MAX_CONNECTIONS,
DEFAULT_MAX_CONNECTIONS
);
}
@Override
public int getDefaultMaxGroupConnections() throws GuacamoleException {
return getProperty(
PostgreSQLGuacamoleProperties.POSTGRESQL_DEFAULT_MAX_GROUP_CONNECTIONS,
DEFAULT_MAX_GROUP_CONNECTIONS
);
}
@Override
public int getDefaultMaxConnectionsPerUser() throws GuacamoleException {
return getProperty(
PostgreSQLGuacamoleProperties.POSTGRESQL_DEFAULT_MAX_CONNECTIONS_PER_USER,
DEFAULT_MAX_CONNECTIONS_PER_USER
);
}
@Override
public int getDefaultMaxGroupConnectionsPerUser() throws GuacamoleException {
return getProperty(
PostgreSQLGuacamoleProperties.POSTGRESQL_DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER,
DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER
);
}
@Override
public PasswordPolicy getPasswordPolicy() {
return new PostgreSQLPasswordPolicy(this);
}
/**
* Returns the hostname of the PostgreSQL server hosting the Guacamole
* authentication tables. If unspecified, this will be "localhost".
*
* @return
* The URL of the PostgreSQL server.
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value.
*/
public String getPostgreSQLHostname() throws GuacamoleException {
return getProperty(
PostgreSQLGuacamoleProperties.POSTGRESQL_HOSTNAME,
DEFAULT_HOSTNAME
);
}
/**
* Returns the port number of the PostgreSQL server hosting the Guacamole
* authentication tables. If unspecified, this will be the default
* PostgreSQL port of 5432.
*
* @return
* The port number of the PostgreSQL server.
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value.
*/
public int getPostgreSQLPort() throws GuacamoleException {
return getProperty(
PostgreSQLGuacamoleProperties.POSTGRESQL_PORT,
DEFAULT_PORT
);
}
/**
* Returns the name of the PostgreSQL database containing the Guacamole
* authentication tables.
*
* @return
* The name of the PostgreSQL database.
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value, or if the
* value was not set, as this property is required.
*/
public String getPostgreSQLDatabase() throws GuacamoleException {
return getRequiredProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_DATABASE);
}
@Override
public String getUsername() throws GuacamoleException {
return getRequiredProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_USERNAME);
}
@Override
public String getPassword() throws GuacamoleException {
return getRequiredProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_PASSWORD);
}
/**
* Returns the defaultStatementTimeout set for PostgreSQL connections.
* If unspecified, this will default to 0,
* and should not be passed through to the backend.
*
* @return
* The statement timeout (in seconds)
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value.
*/
public int getPostgreSQLDefaultStatementTimeout() throws GuacamoleException {
return getProperty(
PostgreSQLGuacamoleProperties.POSTGRESQL_DEFAULT_STATEMENT_TIMEOUT,
DEFAULT_STATEMENT_TIMEOUT
);
}
/**
* Returns the socketTimeout property to set on PostgreSQL connections.
* If unspecified, this will default to 0 (no timeout)
*
* @return
* The socketTimeout to use when waiting on read operations (in seconds)
*
* @throws GuacamoleException
* If an error occurs while retrieving the property value.
*/
public int getPostgreSQLSocketTimeout() throws GuacamoleException {
return getProperty(
PostgreSQLGuacamoleProperties.POSTGRESQL_SOCKET_TIMEOUT,
DEFAULT_SOCKET_TIMEOUT
);
}
@Override
public boolean isRecursiveQuerySupported(SqlSession session) {
return true; // All versions of PostgreSQL support recursive queries through CTEs
}
/**
* Get the SSL mode to use to make the JDBC connection to the PostgreSQL
* server. If unspecified this will default to PREFER, attempting SSL
* and falling back to plain-text if SSL fails.
*
* @return
* The enum value of the SSL mode to use to make the JDBC connection
* to the server.
*
* @throws GuacamoleException
* If an error occurs retrieving the value from guacamole.properties.
*/
public PostgreSQLSSLMode getPostgreSQLSSLMode() throws GuacamoleException {
return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_SSL_MODE,
DEFAULT_SSL_MODE);
}
/**
* Return the SSL client certificate file to use to make the connection
* to the PostgreSQL server.
*
* @return
* The SSL client certificate file to use for the PostgreSQL connection.
*
* @throws GuacamoleException
* If an error occurs retrieving the value from guacamole.properties.
*/
public File getPostgreSQLSSLClientCertFile() throws GuacamoleException {
return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_SSL_CERT_FILE);
}
/**
* Return the SSL client private key file to use to make the connection to the
* PostgreSQL server.
*
* @return
* The SSL client private key file to use for the PostgreSQL connection.
* @throws GuacamoleException
* If an error occurs retrieving the value from guacamole.properties.
*/
public File getPostgreSQLSSLClientKeyFile() throws GuacamoleException {
return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_SSL_KEY_FILE);
}
/**
* Return the SSL client root certificate file to use to make the connection
* to the PostgreSQL server.
*
* @return
* The SSL client root certificate file to use to make the connection
* to the PostgreSQL server.
*
* @throws GuacamoleException
* If an error occurs retrieving the value from guacamole.properties.
*/
public File getPostgreSQLSSLClientRootCertFile() throws GuacamoleException {
return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_SSL_ROOT_CERT_FILE);
}
/**
* Return the password to use to decrypt the private SSL key file when making
* the connection to the PostgreSQL server.
*
* @return
* The password to use to decrypt the private SSL key file when making
* the connection to the PostgreSQL server.
*
* @throws GuacamoleException
* If an error occurs retrieving the value from guacamole.properties.
*/
public String getPostgreSQLSSLClientKeyPassword() throws GuacamoleException {
return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_SSL_KEY_PASSWORD);
}
@Override
public boolean autoCreateAbsentAccounts() throws GuacamoleException {
return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_AUTO_CREATE_ACCOUNTS,
false);
}
@Override
public boolean trackExternalConnectionHistory() throws GuacamoleException {
// Track external connection history unless explicitly disabled
return getProperty(PostgreSQLGuacamoleProperties.POSTGRESQL_TRACK_EXTERNAL_CONNECTION_HISTORY,
true);
}
@Override
public boolean enforceAccessWindowsForActiveSessions() throws GuacamoleException {
// Enforce access window restrictions for active sessions unless explicitly disabled
return getProperty(
PostgreSQLGuacamoleProperties.POSTGRESQL_ENFORCE_ACCESS_WINDOWS_FOR_ACTIVE_SESSIONS,
true);
}
}

View File

@@ -0,0 +1,330 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.postgresql.conf;
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
import org.apache.guacamole.properties.EnumGuacamoleProperty;
import org.apache.guacamole.properties.FileGuacamoleProperty;
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
import org.apache.guacamole.properties.StringGuacamoleProperty;
/**
* Properties used by the PostgreSQL Authentication plugin.
*/
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"; }
};
/**
* The number of seconds the driver will wait for a response from
* the database, before aborting the query.
* A value of 0 (the default) means the timeout is disabled.
*/
public static final IntegerGuacamoleProperty
POSTGRESQL_DEFAULT_STATEMENT_TIMEOUT = new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-default-statement-timeout"; }
};
/**
* The number of seconds to wait for socket read operations.
* If reading from the server takes longer than this value, the
* connection will be closed. This can be used to handle network problems
* such as a dropped connection to the database. Similar to
* postgresql-default-statement-timeout, it will have the effect of
* aborting queries that take too long.
* A value of 0 (the default) means the timeout is disabled.
*/
public static final IntegerGuacamoleProperty
POSTGRESQL_SOCKET_TIMEOUT = new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-socket-timeout"; }
};
/**
* Whether a user account within the database is required for authentication
* to succeed, even if the user has been authenticated via another
* authentication provider.
*/
public static final BooleanGuacamoleProperty
POSTGRESQL_USER_REQUIRED = new BooleanGuacamoleProperty() {
@Override
public String getName() { return "postgresql-user-required"; }
};
/**
* The maximum number of concurrent connections to allow overall. Zero
* denotes unlimited.
*/
public static final IntegerGuacamoleProperty
POSTGRESQL_ABSOLUTE_MAX_CONNECTIONS =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-absolute-max-connections"; }
};
/**
* The maximum number of concurrent connections to allow to any one
* connection. Zero denotes unlimited.
*/
public static final IntegerGuacamoleProperty
POSTGRESQL_DEFAULT_MAX_CONNECTIONS =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-default-max-connections"; }
};
/**
* The maximum number of concurrent connections to allow to any one
* connection group. Zero denotes unlimited.
*/
public static final IntegerGuacamoleProperty
POSTGRESQL_DEFAULT_MAX_GROUP_CONNECTIONS =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-default-max-group-connections"; }
};
/**
* The maximum number of concurrent connections to allow to any one
* connection by an individual user. Zero denotes unlimited.
*/
public static final IntegerGuacamoleProperty
POSTGRESQL_DEFAULT_MAX_CONNECTIONS_PER_USER =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-default-max-connections-per-user"; }
};
/**
* The maximum number of concurrent connections to allow to any one
* connection group by an individual user. Zero denotes
* unlimited.
*/
public static final IntegerGuacamoleProperty
POSTGRESQL_DEFAULT_MAX_GROUP_CONNECTIONS_PER_USER =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-default-max-group-connections-per-user"; }
};
/**
* The SSL mode that should be used by the JDBC driver when making
* connections to the remote server. By default SSL will be attempted but
* plain-text will be allowed if SSL fails.
*/
public static final EnumGuacamoleProperty<PostgreSQLSSLMode> POSTGRESQL_SSL_MODE =
new EnumGuacamoleProperty<PostgreSQLSSLMode>(PostgreSQLSSLMode.class) {
@Override
public String getName() { return "postgresql-ssl-mode"; }
};
/**
* The client SSL certificate file used by the JDBC driver to make the
* SSL connection.
*/
public static final FileGuacamoleProperty POSTGRESQL_SSL_CERT_FILE =
new FileGuacamoleProperty() {
@Override
public String getName() { return "postgresql-ssl-cert-file"; }
};
/**
* The client SSL private key file used by the JDBC driver to make the
* SSL connection.
*/
public static final FileGuacamoleProperty POSTGRESQL_SSL_KEY_FILE =
new FileGuacamoleProperty() {
@Override
public String getName() { return "postgresql-ssl-key-file"; }
};
/**
* The client SSL root certificate file used by the JDBC driver to validate
* certificates when making the SSL connection.
*/
public static final FileGuacamoleProperty POSTGRESQL_SSL_ROOT_CERT_FILE =
new FileGuacamoleProperty() {
@Override
public String getName() { return "postgresql-ssl-root-cert-file"; }
};
/**
* The password of the SSL private key used by the JDBC driver to make
* the SSL connection to the PostgreSQL server.
*/
public static final StringGuacamoleProperty POSTGRESQL_SSL_KEY_PASSWORD =
new StringGuacamoleProperty() {
@Override
public String getName() { return "postgresql-ssl-key-password"; }
};
/**
* Whether or not to automatically create accounts in the PostgreSQL
* database for users who successfully authenticate through another
* extension. By default users will not be automatically created.
*/
public static final BooleanGuacamoleProperty POSTGRESQL_AUTO_CREATE_ACCOUNTS =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "postgresql-auto-create-accounts"; }
};
/**
* Whether or not to track connection history for connections that do not originate
* from within the Postgres database. By default, external connection history will be
* tracked.
*/
public static final BooleanGuacamoleProperty POSTGRESQL_TRACK_EXTERNAL_CONNECTION_HISTORY =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "postgresql-track-external-connection-history"; }
};
/**
* Whether or not user-specific access time windows should be enforced for active sessions,
* i.e. whether users with active sessions should be logged out immediately when an access
* window closes.
*/
public static final BooleanGuacamoleProperty POSTGRESQL_ENFORCE_ACCESS_WINDOWS_FOR_ACTIVE_SESSIONS =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "postgresql-enforce-access-windows-for-active-sessions"; }
};
/**
* The maximum number of identifiers/parameters to be included in a single batch when
* executing SQL statements.
*/
public static final IntegerGuacamoleProperty POSTGRESQL_BATCH_SIZE =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-batch-size"; }
};
/**
* A property used to configure whether or not usernames within the Postgres
* JDBC module should be treated as case-sensitive.
*/
public static final BooleanGuacamoleProperty POSTGRESQL_CASE_SENSITIVE_USERNAMES =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "postgresql-case-sensitive-usernames"; }
};
}

View File

@@ -0,0 +1,194 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.postgresql.conf;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.auth.jdbc.JDBCEnvironment;
import org.apache.guacamole.auth.jdbc.security.PasswordPolicy;
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
import org.apache.guacamole.properties.IntegerGuacamoleProperty;
/**
* PasswordPolicy implementation which reads the details of the policy from
* PostgreSQL-specific properties in guacamole.properties.
*/
public class PostgreSQLPasswordPolicy implements PasswordPolicy {
/**
* The property which specifies the minimum length required of all user
* passwords. By default, this will be zero.
*/
private static final IntegerGuacamoleProperty MIN_LENGTH =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-user-password-min-length"; }
};
/**
* The property which specifies the minimum number of days which must
* elapse before a user may reset their password. If set to zero, the
* default, then this restriction does not apply.
*/
private static final IntegerGuacamoleProperty MIN_AGE =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-user-password-min-age"; }
};
/**
* The property which specifies the maximum number of days which may
* elapse before a user is required to reset their password. If set to zero,
* the default, then this restriction does not apply.
*/
private static final IntegerGuacamoleProperty MAX_AGE =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-user-password-max-age"; }
};
/**
* The property which specifies the number of previous passwords remembered
* for each user. If set to zero, the default, then this restriction does
* not apply.
*/
private static final IntegerGuacamoleProperty HISTORY_SIZE =
new IntegerGuacamoleProperty() {
@Override
public String getName() { return "postgresql-user-password-history-size"; }
};
/**
* The property which specifies whether all user passwords must have at
* least one lowercase character and one uppercase character. By default,
* no such restriction is imposed.
*/
private static final BooleanGuacamoleProperty REQUIRE_MULTIPLE_CASE =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "postgresql-user-password-require-multiple-case"; }
};
/**
* The property which specifies whether all user passwords must have at
* least one numeric character (digit). By default, no such restriction is
* imposed.
*/
private static final BooleanGuacamoleProperty REQUIRE_DIGIT =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "postgresql-user-password-require-digit"; }
};
/**
* The property which specifies whether all user passwords must have at
* least one non-alphanumeric character (symbol). By default, no such
* restriction is imposed.
*/
private static final BooleanGuacamoleProperty REQUIRE_SYMBOL =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "postgresql-user-password-require-symbol"; }
};
/**
* The property which specifies whether users are prohibited from including
* their own username in their password. By default, no such restriction is
* imposed.
*/
private static final BooleanGuacamoleProperty PROHIBIT_USERNAME =
new BooleanGuacamoleProperty() {
@Override
public String getName() { return "postgresql-user-password-prohibit-username"; }
};
/**
* The Guacamole server environment.
*/
private final JDBCEnvironment environment;
/**
* Creates a new PostgreSQLPasswordPolicy which reads the details of the
* policy from the properties exposed by the given environment.
*
* @param environment
* The environment from which password policy properties should be
* read.
*/
public PostgreSQLPasswordPolicy(JDBCEnvironment environment) {
this.environment = environment;
}
@Override
public int getMinimumLength() throws GuacamoleException {
return environment.getProperty(MIN_LENGTH, 0);
}
@Override
public int getMinimumAge() throws GuacamoleException {
return environment.getProperty(MIN_AGE, 0);
}
@Override
public int getMaximumAge() throws GuacamoleException {
return environment.getProperty(MAX_AGE, 0);
}
@Override
public int getHistorySize() throws GuacamoleException {
return environment.getProperty(HISTORY_SIZE, 0);
}
@Override
public boolean isMultipleCaseRequired() throws GuacamoleException {
return environment.getProperty(REQUIRE_MULTIPLE_CASE, false);
}
@Override
public boolean isNumericRequired() throws GuacamoleException {
return environment.getProperty(REQUIRE_DIGIT, false);
}
@Override
public boolean isNonAlphanumericRequired() throws GuacamoleException {
return environment.getProperty(REQUIRE_SYMBOL, false);
}
@Override
public boolean isUsernameProhibited() throws GuacamoleException {
return environment.getProperty(PROHIBIT_USERNAME, false);
}
}

View File

@@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.guacamole.auth.postgresql.conf;
import org.apache.guacamole.properties.EnumGuacamoleProperty.PropertyValue;
/**
* Possible values for PostgreSQL SSL connectivity.
*/
public enum PostgreSQLSSLMode {
/**
* Do not use SSL to connect to server.
*/
@PropertyValue("disable")
DISABLE("disable"),
/**
* Allow SSL connections, but try non-SSL, first.
*/
@PropertyValue("allow")
ALLOW("allow"),
/**
* Prefer SSL connections, falling back to non-SSL if that fails.
*/
@PropertyValue("prefer")
PREFER("prefer"),
/**
* Require SSL connections, do not connect if SSL fails.
*/
@PropertyValue("require")
REQUIRE("require"),
/**
* Require SSL connections and validate the CA certificate.
*/
@PropertyValue("verify-ca")
VERIFY_CA("verify-ca"),
/**
* Require SSL connections and validate both the CA and server certificates.
*/
@PropertyValue("verify-full")
VERIFY_FULL("verify-full");
/**
* The value expected by and passed on to the JDBC driver for the given
* SSL operation mode.
*/
private final String driverValue;
/**
* Create a new instance of this enum with the given driverValue as the
* value that will be used when configuring the JDBC driver.
*
* @param driverValue
* The value to use when configuring the JDBC driver.
*/
PostgreSQLSSLMode(String driverValue) {
this.driverValue = driverValue;
}
/**
* Returns the String value for a given Enum that properly configures the
* JDBC driver for the desired mode of SSL operation.
*
* @return
* The String value for the current Enum that configures the JDBC driver
* for the desired mode of SSL operation.
*/
public String getDriverValue() {
return driverValue;
}
}

View File

@@ -0,0 +1,23 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* The PostgreSQL authentication provider.
*/
package org.apache.guacamole.auth.postgresql;

View File

@@ -0,0 +1,36 @@
{
"guacamoleVersion" : "1.6.0",
"name" : "PostgreSQL Authentication",
"namespace" : "postgresql",
"authProviders" : [
"org.apache.guacamole.auth.postgresql.PostgreSQLAuthenticationProvider",
"org.apache.guacamole.auth.postgresql.PostgreSQLSharedAuthenticationProvider"
],
"css" : [
"styles/jdbc.css"
],
"html" : [
"html/shared-connection.html"
],
"translations" : [
"translations/ca.json",
"translations/de.json",
"translations/en.json",
"translations/es.json",
"translations/fr.json",
"translations/ja.json",
"translations/ko.json",
"translations/pl.json",
"translations/pt.json",
"translations/ru.json",
"translations/zh.json"
]
}

View File

@@ -0,0 +1,147 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.base.EntityMapper" >
<!--
* SQL fragment which tests whether the value of the given column matches
* the given entity ID. If group identifiers are provided, the IDs of the
* entities for all groups having those identifiers are tested, as well.
* Disabled groups are ignored.
*
* @param column
* The name of the column to test. This column MUST contain an entity
* ID (a foreign key into the guacamole_entity table).
*
* @param entityID
* The ID of the specific entity to test the column against.
*
* @param groups
* A collection of group identifiers to additionally test the column
* against. Though this functionality is optional, a collection must
* always be given, even if that collection is empty.
-->
<sql id="isRelatedEntity">
(
${column} = ${entityID}
<if test="!${groups}.isEmpty()">
OR ${column} IN (
SELECT guacamole_entity.entity_id
FROM guacamole_entity
JOIN guacamole_user_group ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE
type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
name IN
<foreach collection="${groups}" item="effectiveGroup"
open="(" separator="," close=")">
#{effectiveGroup,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(name) IN
<foreach collection="${groups}" item="effectiveGroup"
open="(" separator="," close=")">
LOWER(#{effectiveGroup,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
AND disabled = false
)
</if>
)
</sql>
<!-- Select names of all effective groups (including inherited) -->
<select id="selectEffectiveGroupIdentifiers" resultType="string">
WITH RECURSIVE related_entity(entity_id) AS (
SELECT
guacamole_user_group.entity_id
FROM guacamole_user_group
JOIN guacamole_user_group_member ON guacamole_user_group.user_group_id = guacamole_user_group_member.user_group_id
WHERE
guacamole_user_group_member.member_entity_id = #{entity.entityID}
AND guacamole_user_group.disabled = false
<if test="!effectiveGroups.isEmpty()">
UNION
SELECT
guacamole_entity.entity_id
FROM guacamole_entity
JOIN guacamole_user_group ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE
type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
name IN
<foreach collection="effectiveGroups" item="effectiveGroup"
open="(" separator="," close=")">
#{effectiveGroup,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(name) IN
<foreach collection="effectiveGroups" item="effectiveGroup"
open="(" separator="," close=")">
LOWER(#{effectiveGroup,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
AND guacamole_user_group.disabled = false
</if>
UNION
SELECT
guacamole_user_group.entity_id
FROM related_entity
JOIN guacamole_user_group_member ON related_entity.entity_id = guacamole_user_group_member.member_entity_id
JOIN guacamole_user_group ON guacamole_user_group.user_group_id = guacamole_user_group_member.user_group_id
WHERE
guacamole_user_group.disabled = false
)
SELECT name
FROM related_entity
JOIN guacamole_entity ON related_entity.entity_id = guacamole_entity.entity_id
WHERE
guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type;
</select>
<!-- Insert single entity -->
<insert id="insert" useGeneratedKeys="true" keyProperty="entity.entityID"
parameterType="org.apache.guacamole.auth.jdbc.base.EntityModel">
INSERT INTO guacamole_entity (
name,
type
)
VALUES (
#{entity.identifier,jdbcType=VARCHAR},
#{entity.entityType,jdbcType=VARCHAR}::guacamole_entity_type
)
</insert>
</mapper>

View File

@@ -0,0 +1,342 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.connection.ConnectionMapper" >
<!-- Result mapper for connection objects -->
<resultMap id="ConnectionResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionModel" >
<!-- Connection properties -->
<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"/>
<result column="max_connections" property="maxConnections" jdbcType="INTEGER"/>
<result column="max_connections_per_user" property="maxConnectionsPerUser" jdbcType="INTEGER"/>
<result column="proxy_hostname" property="proxyHostname" jdbcType="VARCHAR"/>
<result column="proxy_port" property="proxyPort" jdbcType="INTEGER"/>
<result column="proxy_encryption_method" property="proxyEncryptionMethod" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.GuacamoleProxyConfiguration$EncryptionMethod"/>
<result column="connection_weight" property="connectionWeight" jdbcType="INTEGER"/>
<result column="failover_only" property="failoverOnly" jdbcType="BOOLEAN"/>
<result column="last_active" property="lastActive" jdbcType="TIMESTAMP"/>
<!-- Associated sharing profiles -->
<collection property="sharingProfileIdentifiers" resultSet="sharingProfiles" ofType="java.lang.String"
column="connection_id" foreignColumn="primary_connection_id">
<result column="sharing_profile_id"/>
</collection>
<!-- Arbitrary attributes -->
<collection property="arbitraryAttributes" resultSet="arbitraryAttributes"
ofType="org.apache.guacamole.auth.jdbc.base.ArbitraryAttributeModel"
column="connection_id" foreignColumn="connection_id">
<result property="name" column="attribute_name" jdbcType="VARCHAR"/>
<result property="value" column="attribute_value" jdbcType="VARCHAR"/>
</collection>
</resultMap>
<!-- Select all connection identifiers -->
<select id="selectIdentifiers" resultType="string">
SELECT connection_id
FROM guacamole_connection
</select>
<!--
* SQL fragment which lists the IDs of all connections readable by the
* entity having the given entity ID. If group identifiers are provided,
* the IDs of the entities for all groups having those identifiers are
* tested, as well. Disabled groups are ignored.
*
* @param entityID
* The ID of the specific entity to test against.
*
* @param groups
* A collection of group identifiers to additionally test against.
* Though this functionality is optional, a collection must always be
* given, even if that collection is empty.
-->
<sql id="getReadableIDs">
SELECT DISTINCT connection_id
FROM guacamole_connection_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="${entityID}"/>
<property name="groups" value="${groups}"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = 'READ'
</sql>
<!-- Select identifiers of all readable connections -->
<select id="selectReadableIdentifiers" resultType="string">
<include refid="org.apache.guacamole.auth.jdbc.connection.ConnectionMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
</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=INTEGER}::integer</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
WHERE
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}::integer</if>
<if test="parentIdentifier == null">parent_id IS NULL</if>
AND connection_id IN (
<include refid="org.apache.guacamole.auth.jdbc.connection.ConnectionMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
</select>
<!-- Select multiple connections by identifier -->
<select id="select" resultMap="ConnectionResultMap"
resultSets="connections,sharingProfiles,arbitraryAttributes">
SELECT
guacamole_connection.connection_id,
guacamole_connection.connection_name,
parent_id,
protocol,
max_connections,
max_connections_per_user,
proxy_hostname,
proxy_port,
proxy_encryption_method,
connection_weight,
failover_only,
MAX(start_date) AS last_active
FROM guacamole_connection
LEFT JOIN guacamole_connection_history ON guacamole_connection_history.connection_id = guacamole_connection.connection_id
WHERE guacamole_connection.connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
GROUP BY guacamole_connection.connection_id;
SELECT primary_connection_id, sharing_profile_id
FROM guacamole_sharing_profile
WHERE primary_connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>;
SELECT
connection_id,
attribute_name,
attribute_value
FROM guacamole_connection_attribute
WHERE connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>;
</select>
<!-- Select multiple connections by identifier only if readable -->
<select id="selectReadable" resultMap="ConnectionResultMap"
resultSets="connections,sharingProfiles,arbitraryAttributes">
SELECT
guacamole_connection.connection_id,
guacamole_connection.connection_name,
parent_id,
protocol,
max_connections,
max_connections_per_user,
proxy_hostname,
proxy_port,
proxy_encryption_method,
connection_weight,
failover_only,
MAX(start_date) AS last_active
FROM guacamole_connection
LEFT JOIN guacamole_connection_history ON guacamole_connection_history.connection_id = guacamole_connection.connection_id
WHERE guacamole_connection.connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND guacamole_connection.connection_id IN (
<include refid="org.apache.guacamole.auth.jdbc.connection.ConnectionMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
GROUP BY guacamole_connection.connection_id;
SELECT primary_connection_id, guacamole_sharing_profile.sharing_profile_id
FROM guacamole_sharing_profile
WHERE primary_connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND guacamole_sharing_profile.sharing_profile_id IN (
<include refid="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
SELECT
guacamole_connection_attribute.connection_id,
attribute_name,
attribute_value
FROM guacamole_connection_attribute
WHERE guacamole_connection_attribute.connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND guacamole_connection_attribute.connection_id IN (
<include refid="org.apache.guacamole.auth.jdbc.connection.ConnectionMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
</select>
<!-- Select single connection by name -->
<select id="selectOneByName" resultMap="ConnectionResultMap">
SELECT
guacamole_connection.connection_id,
guacamole_connection.connection_name,
parent_id,
protocol,
max_connections,
max_connections_per_user,
proxy_hostname,
proxy_port,
proxy_encryption_method,
connection_weight,
failover_only,
MAX(start_date) AS last_active
FROM guacamole_connection
LEFT JOIN guacamole_connection_history ON guacamole_connection_history.connection_id = guacamole_connection.connection_id
WHERE
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}::integer</if>
<if test="parentIdentifier == null">parent_id IS NULL</if>
AND guacamole_connection.connection_name = #{name,jdbcType=VARCHAR}
GROUP BY guacamole_connection.connection_id
</select>
<!-- Delete single connection by identifier -->
<delete id="delete">
DELETE FROM guacamole_connection
WHERE connection_id = #{identifier,jdbcType=INTEGER}::integer
</delete>
<!-- Insert single connection -->
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
parameterType="org.apache.guacamole.auth.jdbc.connection.ConnectionModel">
INSERT INTO guacamole_connection (
connection_name,
parent_id,
protocol,
max_connections,
max_connections_per_user,
proxy_hostname,
proxy_port,
proxy_encryption_method,
connection_weight,
failover_only
)
VALUES (
#{object.name,jdbcType=VARCHAR},
#{object.parentIdentifier,jdbcType=INTEGER}::integer,
#{object.protocol,jdbcType=VARCHAR},
#{object.maxConnections,jdbcType=INTEGER},
#{object.maxConnectionsPerUser,jdbcType=INTEGER},
#{object.proxyHostname,jdbcType=VARCHAR},
#{object.proxyPort,jdbcType=INTEGER},
#{object.proxyEncryptionMethod,jdbcType=VARCHAR}::guacamole_proxy_encryption_method,
#{object.connectionWeight,jdbcType=INTEGER},
#{object.failoverOnly,jdbcType=BOOLEAN}
)
</insert>
<!-- Update single connection -->
<update id="update" parameterType="org.apache.guacamole.auth.jdbc.connection.ConnectionModel">
UPDATE guacamole_connection
SET connection_name = #{object.name,jdbcType=VARCHAR},
parent_id = #{object.parentIdentifier,jdbcType=INTEGER}::integer,
protocol = #{object.protocol,jdbcType=VARCHAR},
max_connections = #{object.maxConnections,jdbcType=INTEGER},
max_connections_per_user = #{object.maxConnectionsPerUser,jdbcType=INTEGER},
proxy_hostname = #{object.proxyHostname,jdbcType=VARCHAR},
proxy_port = #{object.proxyPort,jdbcType=INTEGER},
proxy_encryption_method = #{object.proxyEncryptionMethod,jdbcType=VARCHAR}::guacamole_proxy_encryption_method,
connection_weight = #{object.connectionWeight,jdbcType=INTEGER},
failover_only = #{object.failoverOnly,jdbcType=BOOLEAN}
WHERE connection_id = #{object.objectID,jdbcType=INTEGER}::integer
</update>
<!-- Delete attributes associated with connection -->
<delete id="deleteAttributes">
DELETE FROM guacamole_connection_attribute
WHERE connection_id = #{object.objectID,jdbcType=INTEGER}
</delete>
<!-- Insert attributes for connection -->
<insert id="insertAttributes" parameterType="org.apache.guacamole.auth.jdbc.base.ArbitraryAttributeModel">
INSERT INTO guacamole_connection_attribute (
connection_id,
attribute_name,
attribute_value
)
VALUES
<foreach collection="object.arbitraryAttributes" item="attribute" separator=",">
(#{object.objectID,jdbcType=INTEGER},
#{attribute.name,jdbcType=VARCHAR},
#{attribute.value,jdbcType=VARCHAR})
</foreach>
</insert>
</mapper>

View File

@@ -0,0 +1,68 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.connection.ConnectionParameterMapper">
<!-- Result mapper for connection parameters -->
<resultMap id="ParameterResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionParameterModel">
<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=INTEGER}::integer
</select>
<!-- Delete all parameters of a given connection -->
<delete id="delete">
DELETE FROM guacamole_connection_parameter
WHERE connection_id = #{identifier,jdbcType=INTEGER}::integer
</delete>
<!-- Insert all given parameters -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.connection.ConnectionParameterModel">
INSERT INTO guacamole_connection_parameter (
connection_id,
parameter_name,
parameter_value
)
VALUES
<foreach collection="parameters" item="parameter" separator=",">
(#{parameter.connectionIdentifier,jdbcType=INTEGER}::integer,
#{parameter.name,jdbcType=VARCHAR},
#{parameter.value,jdbcType=VARCHAR})
</foreach>
</insert>
</mapper>

View File

@@ -0,0 +1,261 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordMapper" >
<!-- Result mapper for system permissions -->
<resultMap id="ConnectionRecordResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
<id column="history_id" property="recordID" jdbcType="INTEGER"/>
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
<result column="connection_name" property="connectionName" jdbcType="VARCHAR"/>
<result column="remote_host" property="remoteHost" jdbcType="VARCHAR"/>
<result column="sharing_profile_id" property="sharingProfileIdentifier" jdbcType="INTEGER"/>
<result column="sharing_profile_name" property="sharingProfileName" jdbcType="VARCHAR"/>
<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>
<!-- Insert the given connection record -->
<insert id="insert" useGeneratedKeys="true" keyProperty="record.recordID"
parameterType="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
INSERT INTO guacamole_connection_history (
connection_id,
connection_name,
remote_host,
sharing_profile_id,
sharing_profile_name,
user_id,
username,
start_date,
end_date
)
VALUES (
#{record.connectionIdentifier,jdbcType=INTEGER}::integer,
#{record.connectionName,jdbcType=VARCHAR},
#{record.remoteHost,jdbcType=VARCHAR},
#{record.sharingProfileIdentifier,jdbcType=INTEGER}::integer,
#{record.sharingProfileName,jdbcType=VARCHAR},
(SELECT user_id FROM guacamole_user
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name = #{record.username,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(guacamole_entity.name) = LOWER(#{record.username,jdbcType=VARCHAR})
</otherwise>
</choose>
AND guacamole_entity.type = 'USER'::guacamole_entity_type),
#{record.username,jdbcType=VARCHAR},
#{record.startDate,jdbcType=TIMESTAMP},
#{record.endDate,jdbcType=TIMESTAMP}
)
</insert>
<!-- Update the given connection record, assigning an end date -->
<update id="updateEndDate" parameterType="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
UPDATE guacamole_connection_history
SET end_date = #{record.endDate,jdbcType=TIMESTAMP}
WHERE history_id = #{record.recordID,jdbcType=INTEGER}::integer
</update>
<!-- Search for specific connection records -->
<select id="search" resultMap="ConnectionRecordResultMap">
SELECT
guacamole_connection_history.history_id,
guacamole_connection_history.connection_id,
guacamole_connection_history.connection_name,
guacamole_connection_history.remote_host,
guacamole_connection_history.sharing_profile_id,
guacamole_connection_history.sharing_profile_name,
guacamole_connection_history.user_id,
guacamole_connection_history.username,
guacamole_connection_history.start_date,
guacamole_connection_history.end_date
FROM guacamole_connection_history
<!-- Search terms -->
<where>
<if test="recordIdentifier != null">
guacamole_connection_history.history_id = #{recordIdentifier,jdbcType=INTEGER}::integer
</if>
<if test="identifier != null">
AND guacamole_connection_history.connection_id = #{identifier,jdbcType=INTEGER}::integer
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
(
guacamole_connection_history.user_id IN (
SELECT user_id
FROM guacamole_user
WHERE
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
POSITION(#{term.term,jdbcType=VARCHAR} IN username) > 0
</when>
<otherwise>
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(username)) > 0
</otherwise>
</choose>
)
OR guacamole_connection_history.connection_id IN (
SELECT connection_id
FROM guacamole_connection
WHERE POSITION(#{term.term,jdbcType=VARCHAR} IN connection_name) > 0
)
<if test="term.startDate != null and term.endDate != null">
OR start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP}
</if>
)
</foreach>
</where>
<!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
<!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate"
open="ORDER BY " separator=", ">
<choose>
<when test="sortPredicate.property == START_DATE">guacamole_connection_history.start_date</when>
<otherwise>1</otherwise>
</choose>
<if test="sortPredicate.descending">DESC</if>
</foreach>
LIMIT #{limit,jdbcType=INTEGER}
</select>
<!-- Search for specific connection records -->
<select id="searchReadable" resultMap="ConnectionRecordResultMap">
SELECT
guacamole_connection_history.history_id,
guacamole_connection_history.connection_id,
guacamole_connection_history.connection_name,
guacamole_connection_history.remote_host,
guacamole_connection_history.sharing_profile_id,
guacamole_connection_history.sharing_profile_name,
guacamole_connection_history.user_id,
guacamole_connection_history.username,
guacamole_connection_history.start_date,
guacamole_connection_history.end_date
FROM guacamole_connection_history
LEFT JOIN guacamole_connection ON guacamole_connection_history.connection_id = guacamole_connection.connection_id
LEFT JOIN guacamole_user ON guacamole_connection_history.user_id = guacamole_user.user_id
<!-- Search terms -->
<where>
<if test="recordIdentifier != null">
guacamole_connection_history.history_id = #{recordIdentifier,jdbcType=INTEGER}::integer
</if>
<!-- Restrict to readable connections -->
AND guacamole_connection_history.connection_id IN (
<include refid="org.apache.guacamole.auth.jdbc.connection.ConnectionMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
<!-- Restrict to readable users -->
AND guacamole_connection_history.user_id IN (
<include refid="org.apache.guacamole.auth.jdbc.user.UserMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
<if test="identifier != null">
AND guacamole_connection_history.connection_id = #{identifier,jdbcType=INTEGER}::integer
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
(
guacamole_connection_history.user_id IN (
SELECT user_id
FROM guacamole_user
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
</when>
<otherwise>
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(guacamole_entity.name)) > 0
</otherwise>
</choose>
AND guacamole_entity.type = 'USER'::guacamole_entity_type
)
OR guacamole_connection_history.connection_id IN (
SELECT connection_id
FROM guacamole_connection
WHERE POSITION(#{term.term,jdbcType=VARCHAR} IN connection_name) > 0
)
<if test="term.startDate != null and term.endDate != null">
OR start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP}
</if>
)
</foreach>
</where>
<!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
<!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate"
open="ORDER BY " separator=", ">
<choose>
<when test="sortPredicate.property == START_DATE">guacamole_connection_history.start_date</when>
<otherwise>1</otherwise>
</choose>
<if test="sortPredicate.descending">DESC</if>
</foreach>
LIMIT #{limit,jdbcType=INTEGER}
</select>
</mapper>

View File

@@ -0,0 +1,333 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupMapper" >
<!-- Result mapper for connection objects -->
<resultMap id="ConnectionGroupResultMap" type="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel" >
<!-- Connection group properties -->
<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.apache.guacamole.net.auth.ConnectionGroup$Type"/>
<result column="max_connections" property="maxConnections" jdbcType="INTEGER"/>
<result column="max_connections_per_user" property="maxConnectionsPerUser" jdbcType="INTEGER"/>
<result column="enable_session_affinity" property="sessionAffinityEnabled" jdbcType="BOOLEAN"/>
<!-- Child connection groups -->
<collection property="connectionGroupIdentifiers" resultSet="childConnectionGroups" ofType="java.lang.String"
column="connection_group_id" foreignColumn="parent_id">
<result column="connection_group_id"/>
</collection>
<!-- Child connections -->
<collection property="connectionIdentifiers" resultSet="childConnections" ofType="java.lang.String"
column="connection_group_id" foreignColumn="parent_id">
<result column="connection_id"/>
</collection>
<!-- Arbitrary attributes -->
<collection property="arbitraryAttributes" resultSet="arbitraryAttributes"
ofType="org.apache.guacamole.auth.jdbc.base.ArbitraryAttributeModel"
column="connection_group_id" foreignColumn="connection_group_id">
<result property="name" column="attribute_name" jdbcType="VARCHAR"/>
<result property="value" column="attribute_value" jdbcType="VARCHAR"/>
</collection>
</resultMap>
<!-- Select all connection group identifiers -->
<select id="selectIdentifiers" resultType="string">
SELECT connection_group_id
FROM guacamole_connection_group
</select>
<!--
* SQL fragment which lists the IDs of all connection groups readable by
* the entity having the given entity ID. If group identifiers are
* provided, the IDs of the entities for all groups having those
* identifiers are tested, as well. Disabled groups are ignored.
*
* @param entityID
* The ID of the specific entity to test against.
*
* @param groups
* A collection of group identifiers to additionally test against.
* Though this functionality is optional, a collection must always be
* given, even if that collection is empty.
-->
<sql id="getReadableIDs">
SELECT DISTINCT connection_group_id
FROM guacamole_connection_group_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="${entityID}"/>
<property name="groups" value="${groups}"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = 'READ'
</sql>
<!-- Select identifiers of all readable connection groups -->
<select id="selectReadableIdentifiers" resultType="string">
<include refid="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
</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=INTEGER}::integer</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
WHERE
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}::integer</if>
<if test="parentIdentifier == null">parent_id IS NULL</if>
AND connection_group_id IN (
<include refid="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
</select>
<!-- Select multiple connection groups by identifier -->
<select id="select" resultMap="ConnectionGroupResultMap"
resultSets="connectionGroups,childConnectionGroups,childConnections,arbitraryAttributes">
SELECT
connection_group_id,
connection_group_name,
parent_id,
type,
max_connections,
max_connections_per_user,
enable_session_affinity
FROM guacamole_connection_group
WHERE connection_group_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>;
SELECT parent_id, connection_group_id
FROM guacamole_connection_group
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>;
SELECT parent_id, connection_id
FROM guacamole_connection
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>;
SELECT
connection_group_id,
attribute_name,
attribute_value
FROM guacamole_connection_group_attribute
WHERE connection_group_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>;
</select>
<!-- Select multiple connection groups by identifier only if readable -->
<select id="selectReadable" resultMap="ConnectionGroupResultMap"
resultSets="connectionGroups,childConnectionGroups,childConnections,arbitraryAttributes">
SELECT
guacamole_connection_group.connection_group_id,
connection_group_name,
parent_id,
type,
max_connections,
max_connections_per_user,
enable_session_affinity
FROM guacamole_connection_group
WHERE guacamole_connection_group.connection_group_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND guacamole_connection_group.connection_group_id IN (
<include refid="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
SELECT parent_id, guacamole_connection_group.connection_group_id
FROM guacamole_connection_group
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND guacamole_connection_group.connection_group_id IN (
<include refid="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
SELECT parent_id, guacamole_connection.connection_id
FROM guacamole_connection
WHERE parent_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND guacamole_connection.connection_id IN (
<include refid="org.apache.guacamole.auth.jdbc.connection.ConnectionMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
SELECT
guacamole_connection_group_attribute.connection_group_id,
attribute_name,
attribute_value
FROM guacamole_connection_group_attribute
WHERE guacamole_connection_group_attribute.connection_group_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND guacamole_connection_group_attribute.connection_group_id IN (
<include refid="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
</select>
<!-- Select single connection group by name -->
<select id="selectOneByName" resultMap="ConnectionGroupResultMap">
SELECT
connection_group_id,
connection_group_name,
parent_id,
type,
max_connections,
max_connections_per_user,
enable_session_affinity
FROM guacamole_connection_group
WHERE
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}::integer</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=INTEGER}::integer
</delete>
<!-- Insert single connection -->
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
parameterType="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel">
INSERT INTO guacamole_connection_group (
connection_group_name,
parent_id,
type,
max_connections,
max_connections_per_user,
enable_session_affinity
)
VALUES (
#{object.name,jdbcType=VARCHAR},
#{object.parentIdentifier,jdbcType=INTEGER}::integer,
#{object.type,jdbcType=VARCHAR}::guacamole_connection_group_type,
#{object.maxConnections,jdbcType=INTEGER},
#{object.maxConnectionsPerUser,jdbcType=INTEGER},
#{object.sessionAffinityEnabled,jdbcType=BOOLEAN}
)
</insert>
<!-- Update single connection group -->
<update id="update" parameterType="org.apache.guacamole.auth.jdbc.connectiongroup.ConnectionGroupModel">
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,
max_connections = #{object.maxConnections,jdbcType=INTEGER},
max_connections_per_user = #{object.maxConnectionsPerUser,jdbcType=INTEGER},
enable_session_affinity = #{object.sessionAffinityEnabled,jdbcType=BOOLEAN}
WHERE connection_group_id = #{object.objectID,jdbcType=INTEGER}::integer
</update>
<!-- Delete attributes associated with connection group -->
<delete id="deleteAttributes">
DELETE FROM guacamole_connection_group_attribute
WHERE connection_group_id = #{object.objectID,jdbcType=INTEGER}
</delete>
<!-- Insert attributes for connection group -->
<insert id="insertAttributes" parameterType="org.apache.guacamole.auth.jdbc.base.ArbitraryAttributeModel">
INSERT INTO guacamole_connection_group_attribute (
connection_group_id,
attribute_name,
attribute_value
)
VALUES
<foreach collection="object.arbitraryAttributes" item="attribute" separator=",">
(#{object.objectID,jdbcType=INTEGER},
#{attribute.name,jdbcType=VARCHAR},
#{attribute.value,jdbcType=VARCHAR})
</foreach>
</insert>
</mapper>

View File

@@ -0,0 +1,141 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.ConnectionGroupPermissionMapper" >
<!-- Result mapper for connection permissions -->
<resultMap id="ConnectionGroupPermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
<result column="entity_id" property="entityID" jdbcType="INTEGER"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
<result column="connection_group_id" property="objectIdentifier" jdbcType="INTEGER"/>
</resultMap>
<!-- Select all permissions for a given entity -->
<select id="select" resultMap="ConnectionGroupPermissionResultMap">
SELECT DISTINCT
#{entity.entityID,jdbcType=INTEGER} AS entity_id,
permission,
connection_group_id
FROM guacamole_connection_group_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="ConnectionGroupPermissionResultMap">
SELECT DISTINCT
#{entity.entityID,jdbcType=INTEGER} AS entity_id,
permission,
connection_group_id
FROM guacamole_connection_group_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = #{type,jdbcType=VARCHAR}::guacamole_object_permission_type
AND connection_group_id = #{identifier,jdbcType=INTEGER}::integer
</select>
<!-- Select identifiers accessible by the given entity for the given permissions -->
<select id="selectAccessibleIdentifiers" resultType="string">
SELECT DISTINCT connection_group_id
FROM guacamole_connection_group_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND connection_group_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND permission IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
#{permission,jdbcType=VARCHAR}::guacamole_object_permission_type
</foreach>
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
DELETE FROM guacamole_connection_group_permission
WHERE (entity_id, permission, connection_group_id) IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.entityID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
#{permission.objectIdentifier,jdbcType=INTEGER}::integer)
</foreach>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
INSERT INTO guacamole_connection_group_permission (
entity_id,
permission,
connection_group_id
)
SELECT DISTINCT
permissions.entity_id,
permissions.permission,
permissions.connection_group_id
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.entityID,jdbcType=INTEGER} AS entity_id,
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type AS permission,
#{permission.objectIdentifier,jdbcType=INTEGER}::integer AS connection_group_id
</foreach>
AS permissions
WHERE (entity_id, permission, connection_group_id) NOT IN (
SELECT
guacamole_connection_group_permission.entity_id,
guacamole_connection_group_permission.permission,
guacamole_connection_group_permission.connection_group_id
FROM guacamole_connection_group_permission
);
</insert>
</mapper>

View File

@@ -0,0 +1,141 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.ConnectionPermissionMapper" >
<!-- Result mapper for connection permissions -->
<resultMap id="ConnectionPermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
<result column="entity_id" property="entityID" jdbcType="INTEGER"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
<result column="connection_id" property="objectIdentifier" jdbcType="INTEGER"/>
</resultMap>
<!-- Select all permissions for a given entity -->
<select id="select" resultMap="ConnectionPermissionResultMap">
SELECT DISTINCT
#{entity.entityID,jdbcType=INTEGER} AS entity_id,
permission,
connection_id
FROM guacamole_connection_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="ConnectionPermissionResultMap">
SELECT DISTINCT
#{entity.entityID,jdbcType=INTEGER} AS entity_id,
permission,
connection_id
FROM guacamole_connection_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = #{type,jdbcType=VARCHAR}::guacamole_object_permission_type
AND connection_id = #{identifier,jdbcType=INTEGER}::integer
</select>
<!-- Select identifiers accessible by the given entity for the given permissions -->
<select id="selectAccessibleIdentifiers" resultType="string">
SELECT DISTINCT connection_id
FROM guacamole_connection_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND connection_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND permission IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
#{permission,jdbcType=VARCHAR}::guacamole_object_permission_type
</foreach>
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
DELETE FROM guacamole_connection_permission
WHERE (entity_id, permission, connection_id) IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.entityID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
#{permission.objectIdentifier,jdbcType=INTEGER}::integer)
</foreach>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
INSERT INTO guacamole_connection_permission (
entity_id,
permission,
connection_id
)
SELECT DISTINCT
permissions.entity_id,
permissions.permission,
permissions.connection_id
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.entityID,jdbcType=INTEGER} AS entity_id,
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type AS permission,
#{permission.objectIdentifier,jdbcType=INTEGER}::integer AS connection_id
</foreach>
AS permissions
WHERE (entity_id, permission, connection_id) NOT IN (
SELECT
guacamole_connection_permission.entity_id,
guacamole_connection_permission.permission,
guacamole_connection_permission.connection_id
FROM guacamole_connection_permission
);
</insert>
</mapper>

View File

@@ -0,0 +1,141 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.SharingProfilePermissionMapper">
<!-- Result mapper for sharing profile permissions -->
<resultMap id="SharingProfilePermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
<result column="entity_id" property="entityID" jdbcType="INTEGER"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
<result column="sharing_profile_id" property="objectIdentifier" jdbcType="INTEGER"/>
</resultMap>
<!-- Select all permissions for a given entity -->
<select id="select" resultMap="SharingProfilePermissionResultMap">
SELECT DISTINCT
#{entity.entityID,jdbcType=INTEGER} AS entity_id,
permission,
sharing_profile_id
FROM guacamole_sharing_profile_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="SharingProfilePermissionResultMap">
SELECT DISTINCT
#{entity.entityID,jdbcType=INTEGER} AS entity_id,
permission,
sharing_profile_id
FROM guacamole_sharing_profile_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = #{type,jdbcType=VARCHAR}::guacamole_object_permission_type
AND sharing_profile_id = #{identifier,jdbcType=INTEGER}::integer
</select>
<!-- Select identifiers accessible by the given entity for the given permissions -->
<select id="selectAccessibleIdentifiers" resultType="string">
SELECT DISTINCT sharing_profile_id
FROM guacamole_sharing_profile_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND sharing_profile_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND permission IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
#{permission,jdbcType=VARCHAR}::guacamole_object_permission_type
</foreach>
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
DELETE FROM guacamole_sharing_profile_permission
WHERE (entity_id, permission, sharing_profile_id) IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.entityID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
#{permission.objectIdentifier,jdbcType=INTEGER}::integer)
</foreach>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
INSERT INTO guacamole_sharing_profile_permission (
entity_id,
permission,
sharing_profile_id
)
SELECT DISTINCT
permissions.entity_id,
permissions.permission,
permissions.sharing_profile_id
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.entityID,jdbcType=INTEGER} AS entity_id,
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type AS permission,
#{permission.objectIdentifier,jdbcType=INTEGER}::integer AS sharing_profile_id
</foreach>
AS permissions
WHERE (entity_id, permission, sharing_profile_id) NOT IN (
SELECT
guacamole_sharing_profile_permission.entity_id,
guacamole_sharing_profile_permission.permission,
guacamole_sharing_profile_permission.sharing_profile_id
FROM guacamole_sharing_profile_permission
);
</insert>
</mapper>

View File

@@ -0,0 +1,107 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.SystemPermissionMapper" >
<!-- Result mapper for system permissions -->
<resultMap id="SystemPermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.SystemPermissionModel">
<result column="entity_id" property="entityID" jdbcType="INTEGER"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.SystemPermission$Type"/>
</resultMap>
<!-- Select all permissions for a given entity -->
<select id="select" resultMap="SystemPermissionResultMap">
SELECT DISTINCT
#{entity.entityID} AS entity_id,
permission
FROM guacamole_system_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="SystemPermissionResultMap">
SELECT DISTINCT
#{entity.entityID} AS entity_id,
permission
FROM guacamole_system_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = #{type,jdbcType=VARCHAR}::guacamole_system_permission_type
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.SystemPermissionModel">
DELETE FROM guacamole_system_permission
WHERE (entity_id, permission) IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.entityID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR}::guacamole_system_permission_type)
</foreach>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.SystemPermissionModel">
INSERT INTO guacamole_system_permission (
entity_id,
permission
)
SELECT DISTINCT
permissions.entity_id,
permissions.permission
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.entityID,jdbcType=INTEGER} AS entity_id,
#{permission.type,jdbcType=VARCHAR}::guacamole_system_permission_type AS permission
</foreach>
AS permissions
WHERE (entity_id, permission) NOT IN (
SELECT
guacamole_system_permission.entity_id,
guacamole_system_permission.permission
FROM guacamole_system_permission
);
</insert>
</mapper>

View File

@@ -0,0 +1,203 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.UserGroupPermissionMapper" >
<!-- Result mapper for user group permissions -->
<resultMap id="UserGroupPermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
<result column="entity_id" property="entityID" jdbcType="INTEGER"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
<result column="affected_name" property="objectIdentifier" jdbcType="INTEGER"/>
</resultMap>
<!-- Select all permissions for a given entity -->
<select id="select" resultMap="UserGroupPermissionResultMap">
SELECT DISTINCT
#{entity.entityID,jdbcType=INTEGER} AS entity_id,
permission,
affected_entity.name AS affected_name
FROM guacamole_user_group_permission
JOIN guacamole_user_group affected_group ON guacamole_user_group_permission.affected_user_group_id = affected_group.user_group_id
JOIN guacamole_entity affected_entity ON affected_group.entity_id = affected_entity.entity_id
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="guacamole_user_group_permission.entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND affected_entity.type = 'USER_GROUP'::guacamole_entity_type
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="UserGroupPermissionResultMap">
SELECT DISTINCT
#{entity.entityID,jdbcType=INTEGER} AS entity_id,
permission,
affected_entity.name AS affected_name
FROM guacamole_user_group_permission
JOIN guacamole_user_group affected_group ON guacamole_user_group_permission.affected_user_group_id = affected_group.user_group_id
JOIN guacamole_entity affected_entity ON affected_group.entity_id = affected_entity.entity_id
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="guacamole_user_group_permission.entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = #{type,jdbcType=VARCHAR}::guacamole_object_permission_type
AND affected_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
affected_entity.name = #{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(affected_entity.name) = LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</select>
<!-- Select identifiers accessible by the given entity for the given permissions -->
<select id="selectAccessibleIdentifiers" resultType="string">
SELECT DISTINCT affected_entity.name
FROM guacamole_user_group_permission
JOIN guacamole_user_group affected_group ON guacamole_user_group_permission.affected_user_group_id = affected_group.user_group_id
JOIN guacamole_entity affected_entity ON affected_group.entity_id = affected_entity.entity_id
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="guacamole_user_group_permission.entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND affected_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
affected_entity.name IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(affected_entity.name) IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
AND permission IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
#{permission,jdbcType=VARCHAR}::guacamole_object_permission_type
</foreach>
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
DELETE FROM guacamole_user_group_permission
USING guacamole_user_group affected_group, guacamole_entity affected_entity
WHERE
guacamole_user_group_permission.affected_user_group_id = affected_group.user_group_id
AND affected_group.entity_id = affected_entity.entity_id
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
(guacamole_user_group_permission.entity_id, permission, affected_entity.name)
</when>
<otherwise>
(guacamole_user_group_permission.entity_id, permission, LOWER(affected_entity.name))
</otherwise>
</choose>
IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.entityID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
#{permission.objectIdentifier,jdbcType=INTEGER}
</when>
<otherwise>
LOWER(#{permission.objectIdentifier,jdbcType=INTEGER})
</otherwise>
</choose>
)
</foreach>
AND affected_entity.type = 'USER_GROUP'::guacamole_entity_type
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
INSERT INTO guacamole_user_group_permission (
entity_id,
permission,
affected_user_group_id
)
SELECT DISTINCT
permissions.entity_id,
permissions.permission,
affected_group.user_group_id
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.entityID,jdbcType=INTEGER} AS entity_id,
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type AS permission,
#{permission.objectIdentifier,jdbcType=VARCHAR}::text AS affected_name
</foreach>
AS permissions
JOIN guacamole_entity affected_entity ON
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
affected_entity.name = permissions.affected_name
</when>
<otherwise>
LOWER(affected_entity.name) = LOWER(permissions.affected_name)
</otherwise>
</choose>
AND affected_entity.type = 'USER_GROUP'::guacamole_entity_type
JOIN guacamole_user_group affected_group ON affected_group.entity_id = affected_entity.entity_id
WHERE (permissions.entity_id, permissions.permission, affected_group.user_group_id) NOT IN (
SELECT
guacamole_user_group_permission.entity_id,
guacamole_user_group_permission.permission,
guacamole_user_group_permission.affected_user_group_id
FROM guacamole_user_group_permission
);
</insert>
</mapper>

View File

@@ -0,0 +1,201 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.permission.UserPermissionMapper" >
<!-- Result mapper for user permissions -->
<resultMap id="UserPermissionResultMap" type="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
<result column="entity_id" property="entityID" jdbcType="INTEGER"/>
<result column="permission" property="type" jdbcType="VARCHAR"
javaType="org.apache.guacamole.net.auth.permission.ObjectPermission$Type"/>
<result column="affected_name" property="objectIdentifier" jdbcType="VARCHAR"/>
</resultMap>
<!-- Select all permissions for a given entity -->
<select id="select" resultMap="UserPermissionResultMap">
SELECT DISTINCT
#{entity.entityID,jdbcType=INTEGER} AS entity_id,
permission,
affected_entity.name AS affected_name
FROM guacamole_user_permission
JOIN guacamole_user affected_user ON guacamole_user_permission.affected_user_id = affected_user.user_id
JOIN guacamole_entity affected_entity ON affected_user.entity_id = affected_entity.entity_id
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="guacamole_user_permission.entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND affected_entity.type = 'USER'::guacamole_entity_type
</select>
<!-- Select the single permission matching the given criteria -->
<select id="selectOne" resultMap="UserPermissionResultMap">
SELECT DISTINCT
#{entity.entityID,jdbcType=INTEGER} AS entity_id,
permission,
affected_entity.name AS affected_name
FROM guacamole_user_permission
JOIN guacamole_user affected_user ON guacamole_user_permission.affected_user_id = affected_user.user_id
JOIN guacamole_entity affected_entity ON affected_user.entity_id = affected_entity.entity_id
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="guacamole_user_permission.entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = #{type,jdbcType=VARCHAR}::guacamole_object_permission_type
AND affected_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
affected_entity.name = #{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(affected_entity.name) = LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</select>
<!-- Select identifiers accessible by the given entity for the given permissions -->
<select id="selectAccessibleIdentifiers" resultType="string">
SELECT DISTINCT affected_entity.name
FROM guacamole_user_permission
JOIN guacamole_user affected_user ON guacamole_user_permission.affected_user_id = affected_user.user_id
JOIN guacamole_entity affected_entity ON affected_user.entity_id = affected_entity.entity_id
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="guacamole_user_permission.entity_id"/>
<property name="entityID" value="#{entity.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND affected_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
affected_entity.name IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(affected_entity.name) IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
AND permission IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
#{permission,jdbcType=VARCHAR}::guacamole_object_permission_type
</foreach>
</select>
<!-- Delete all given permissions -->
<delete id="delete" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
DELETE FROM guacamole_user_permission
USING guacamole_user affected_user, guacamole_entity affected_entity
WHERE
guacamole_user_permission.affected_user_id = affected_user.user_id
AND affected_user.entity_id = affected_entity.entity_id
AND affected_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
(guacamole_user_permission.entity_id, permission, affected_entity.name) IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.entityID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
#{permission.objectIdentifier,jdbcType=VARCHAR})
</foreach>
</when>
<otherwise>
(guacamole_user_permission.entity_id, permission, LOWER(affected_entity.name)) IN
<foreach collection="permissions" item="permission"
open="(" separator="," close=")">
(#{permission.entityID,jdbcType=INTEGER},
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type,
LOWER(#{permission.objectIdentifier,jdbcType=VARCHAR}))
</foreach>
</otherwise>
</choose>
</delete>
<!-- Insert all given permissions -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel">
INSERT INTO guacamole_user_permission (
entity_id,
permission,
affected_user_id
)
SELECT DISTINCT
permissions.entity_id,
permissions.permission,
affected_user.user_id
FROM
<foreach collection="permissions" item="permission"
open="(" separator="UNION ALL" close=")">
SELECT #{permission.entityID,jdbcType=INTEGER} AS entity_id,
#{permission.type,jdbcType=VARCHAR}::guacamole_object_permission_type AS permission,
#{permission.objectIdentifier,jdbcType=VARCHAR}::text AS affected_name
</foreach>
AS permissions
JOIN guacamole_entity affected_entity ON
affected_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
affected_entity.name = permissions.affected_name
</when>
<otherwise>
LOWER(affected_entity.name) = LOWER(permissions.affected_name)
</otherwise>
</choose>
JOIN guacamole_user affected_user ON affected_user.entity_id = affected_entity.entity_id
WHERE (permissions.entity_id, permissions.permission, affected_user.user_id) NOT IN (
SELECT
guacamole_user_permission.entity_id,
guacamole_user_permission.permission,
guacamole_user_permission.affected_user_id
FROM guacamole_user_permission
);
</insert>
</mapper>

View File

@@ -0,0 +1,220 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileMapper">
<!-- Result mapper for sharing profile objects -->
<resultMap id="SharingProfileResultMap" type="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileModel">
<!-- Sharing profile properties -->
<id column="sharing_profile_id" property="objectID" jdbcType="INTEGER"/>
<result column="sharing_profile_name" property="name" jdbcType="VARCHAR"/>
<result column="primary_connection_id" property="parentIdentifier" jdbcType="INTEGER"/>
<!-- Arbitrary attributes -->
<collection property="arbitraryAttributes" resultSet="arbitraryAttributes"
ofType="org.apache.guacamole.auth.jdbc.base.ArbitraryAttributeModel"
column="sharing_profile_id" foreignColumn="sharing_profile_id">
<result property="name" column="attribute_name" jdbcType="VARCHAR"/>
<result property="value" column="attribute_value" jdbcType="VARCHAR"/>
</collection>
</resultMap>
<!-- Select all sharing profile identifiers -->
<select id="selectIdentifiers" resultType="string">
SELECT sharing_profile_id
FROM guacamole_sharing_profile
</select>
<!--
* SQL fragment which lists the IDs of all sharing profiles readable by
* the entity having the given entity ID. If group identifiers are
* provided, the IDs of the entities for all groups having those
* identifiers are tested, as well. Disabled groups are ignored.
*
* @param entityID
* The ID of the specific entity to test against.
*
* @param groups
* A collection of group identifiers to additionally test against.
* Though this functionality is optional, a collection must always be
* given, even if that collection is empty.
-->
<sql id="getReadableIDs">
SELECT DISTINCT sharing_profile_id
FROM guacamole_sharing_profile_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="${entityID}"/>
<property name="groups" value="${groups}"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = 'READ'
</sql>
<!-- Select identifiers of all readable sharing profiles -->
<select id="selectReadableIdentifiers" resultType="string">
<include refid="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
</select>
<!-- Select multiple sharing profiles by identifier -->
<select id="select" resultMap="SharingProfileResultMap"
resultSets="sharingProfiles,arbitraryAttributes">
SELECT
sharing_profile_id,
sharing_profile_name,
primary_connection_id
FROM guacamole_sharing_profile
WHERE sharing_profile_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>;
SELECT
sharing_profile_id,
attribute_name,
attribute_value
FROM guacamole_sharing_profile_attribute
WHERE sharing_profile_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>;
</select>
<!-- Select multiple sharing profiles by identifier only if readable -->
<select id="selectReadable" resultMap="SharingProfileResultMap"
resultSets="sharingProfiles,arbitraryAttributes">
SELECT
guacamole_sharing_profile.sharing_profile_id,
guacamole_sharing_profile.sharing_profile_name,
primary_connection_id
FROM guacamole_sharing_profile
WHERE guacamole_sharing_profile.sharing_profile_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND guacamole_sharing_profile.sharing_profile_id IN (
<include refid="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
SELECT
guacamole_sharing_profile_attribute.sharing_profile_id,
attribute_name,
attribute_value
FROM guacamole_sharing_profile_attribute
WHERE guacamole_sharing_profile_attribute.sharing_profile_id IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=INTEGER}::integer
</foreach>
AND guacamole_sharing_profile_attribute.sharing_profile_id IN (
<include refid="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
</select>
<!-- Select single sharing profile by name -->
<select id="selectOneByName" resultMap="SharingProfileResultMap">
SELECT
sharing_profile_id,
sharing_profile_name,
primary_connection_id
FROM guacamole_sharing_profile
WHERE
primary_connection_id = #{parentIdentifier,jdbcType=INTEGER}::integer
AND sharing_profile_name = #{name,jdbcType=VARCHAR}
</select>
<!-- Delete single sharing profile by identifier -->
<delete id="delete">
DELETE FROM guacamole_sharing_profile
WHERE sharing_profile_id = #{identifier,jdbcType=INTEGER}::integer
</delete>
<!-- Insert single sharing profile -->
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
parameterType="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileModel">
INSERT INTO guacamole_sharing_profile (
sharing_profile_name,
primary_connection_id
)
VALUES (
#{object.name,jdbcType=VARCHAR},
#{object.parentIdentifier,jdbcType=INTEGER}::integer
)
</insert>
<!-- Update single sharing profile -->
<update id="update" parameterType="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileModel">
UPDATE guacamole_sharing_profile
SET sharing_profile_name = #{object.name,jdbcType=VARCHAR},
primary_connection_id = #{object.parentIdentifier,jdbcType=INTEGER}::integer
WHERE sharing_profile_id = #{object.objectID,jdbcType=INTEGER}::integer
</update>
<!-- Delete attributes associated with sharing profile -->
<delete id="deleteAttributes">
DELETE FROM guacamole_sharing_profile_attribute
WHERE sharing_profile_id = #{object.objectID,jdbcType=INTEGER}
</delete>
<!-- Insert attributes for sharing profile -->
<insert id="insertAttributes" parameterType="org.apache.guacamole.auth.jdbc.base.ArbitraryAttributeModel">
INSERT INTO guacamole_sharing_profile_attribute (
sharing_profile_id,
attribute_name,
attribute_value
)
VALUES
<foreach collection="object.arbitraryAttributes" item="attribute" separator=",">
(#{object.objectID,jdbcType=INTEGER},
#{attribute.name,jdbcType=VARCHAR},
#{attribute.value,jdbcType=VARCHAR})
</foreach>
</insert>
</mapper>

View File

@@ -0,0 +1,68 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterMapper">
<!-- Result mapper for sharing profile parameters -->
<resultMap id="ParameterResultMap" type="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterModel">
<result column="sharing_profile_id" property="sharingProfileIdentifier" 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 sharing profile -->
<select id="select" resultMap="ParameterResultMap">
SELECT
sharing_profile_id,
parameter_name,
parameter_value
FROM guacamole_sharing_profile_parameter
WHERE
sharing_profile_id = #{identifier,jdbcType=INTEGER}::integer
</select>
<!-- Delete all parameters of a given sharing profile -->
<delete id="delete">
DELETE FROM guacamole_sharing_profile_parameter
WHERE sharing_profile_id = #{identifier,jdbcType=INTEGER}::integer
</delete>
<!-- Insert all given parameters -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterModel">
INSERT INTO guacamole_sharing_profile_parameter (
sharing_profile_id,
parameter_name,
parameter_value
)
VALUES
<foreach collection="parameters" item="parameter" separator=",">
(#{parameter.sharingProfileIdentifier,jdbcType=INTEGER}::integer,
#{parameter.name,jdbcType=VARCHAR},
#{parameter.value,jdbcType=VARCHAR})
</foreach>
</insert>
</mapper>

View File

@@ -0,0 +1,87 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.user.PasswordRecordMapper" >
<!-- Result mapper for historical passwords -->
<resultMap id="PasswordRecordResultMap" type="org.apache.guacamole.auth.jdbc.user.PasswordRecordModel">
<result column="user_id" property="userID" jdbcType="INTEGER"/>
<result column="password_hash" property="passwordHash" jdbcType="BINARY"/>
<result column="password_salt" property="passwordSalt" jdbcType="BINARY"/>
<result column="password_date" property="passwordDate" jdbcType="TIMESTAMP"/>
</resultMap>
<!-- Select all password records for a given user -->
<select id="select" resultMap="PasswordRecordResultMap">
SELECT
guacamole_user_password_history.user_id,
guacamole_user_password_history.password_hash,
guacamole_user_password_history.password_salt,
guacamole_user_password_history.password_date
FROM guacamole_user_password_history
JOIN guacamole_user ON guacamole_user_password_history.user_id = guacamole_user.user_id
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name = #{username,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(guacamole_entity.name) = LOWER(#{username,jdbcType=VARCHAR})
</otherwise>
</choose>
ORDER BY
guacamole_user_password_history.password_date DESC
LIMIT #{maxHistorySize}
</select>
<!-- Insert the given password record -->
<insert id="insert" parameterType="org.apache.guacamole.auth.jdbc.user.PasswordRecordModel">
INSERT INTO guacamole_user_password_history (
user_id,
password_hash,
password_salt,
password_date
)
VALUES (
#{record.userID,jdbcType=INTEGER},
#{record.passwordHash,jdbcType=BINARY},
#{record.passwordSalt,jdbcType=BINARY},
#{record.passwordDate,jdbcType=TIMESTAMP}
);
DELETE FROM guacamole_user_password_history
WHERE password_history_id IN (
SELECT password_history_id
FROM guacamole_user_password_history
WHERE user_id = #{record.userID,jdbcType=INTEGER}
ORDER BY password_date DESC
OFFSET #{maxHistorySize}
);
</insert>
</mapper>

View File

@@ -0,0 +1,441 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.user.UserMapper" >
<!-- Result mapper for user objects -->
<resultMap id="UserResultMap" type="org.apache.guacamole.auth.jdbc.user.UserModel" >
<!-- User properties -->
<id column="user_id" property="objectID" jdbcType="INTEGER"/>
<result column="entity_id" property="entityID" jdbcType="INTEGER"/>
<result column="name" property="identifier" jdbcType="VARCHAR"/>
<result column="password_hash" property="passwordHash" jdbcType="BINARY"/>
<result column="password_salt" property="passwordSalt" jdbcType="BINARY"/>
<result column="password_date" property="passwordDate" jdbcType="TIMESTAMP"/>
<result column="disabled" property="disabled" jdbcType="BOOLEAN"/>
<result column="expired" property="expired" jdbcType="BOOLEAN"/>
<result column="access_window_start" property="accessWindowStart" jdbcType="TIME"/>
<result column="access_window_end" property="accessWindowEnd" jdbcType="TIME"/>
<result column="valid_from" property="validFrom" jdbcType="DATE"/>
<result column="valid_until" property="validUntil" jdbcType="DATE"/>
<result column="timezone" property="timeZone" jdbcType="VARCHAR"/>
<result column="full_name" property="fullName" jdbcType="VARCHAR"/>
<result column="email_address" property="emailAddress" jdbcType="VARCHAR"/>
<result column="organization" property="organization" jdbcType="VARCHAR"/>
<result column="organizational_role" property="organizationalRole" jdbcType="VARCHAR"/>
<result column="last_active" property="lastActive" jdbcType="TIMESTAMP"/>
<!-- Arbitrary attributes -->
<collection property="arbitraryAttributes" resultSet="arbitraryAttributes"
ofType="org.apache.guacamole.auth.jdbc.base.ArbitraryAttributeModel"
column="user_id" foreignColumn="user_id">
<result property="name" column="attribute_name" jdbcType="VARCHAR"/>
<result property="value" column="attribute_value" jdbcType="VARCHAR"/>
</collection>
</resultMap>
<!-- Select all usernames -->
<select id="selectIdentifiers" resultType="string">
SELECT name
FROM guacamole_entity
WHERE guacamole_entity.type = 'USER'::guacamole_entity_type
</select>
<!--
* SQL fragment which lists the IDs of all users readable by the entity
* having the given entity ID. If group identifiers are provided, the IDs
* of the entities for all groups having those identifiers are tested, as
* well. Disabled groups are ignored.
*
* @param entityID
* The ID of the specific entity to test against.
*
* @param groups
* A collection of group identifiers to additionally test against.
* Though this functionality is optional, a collection must always be
* given, even if that collection is empty.
-->
<sql id="getReadableIDs">
SELECT DISTINCT guacamole_user_permission.affected_user_id
FROM guacamole_user_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="${entityID}"/>
<property name="groups" value="${groups}"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = 'READ'
</sql>
<!-- Select usernames of all readable users -->
<select id="selectReadableIdentifiers" resultType="string">
SELECT guacamole_entity.name
FROM guacamole_user
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER'::guacamole_entity_type
AND guacamole_user.user_id IN (
<include refid="org.apache.guacamole.auth.jdbc.user.UserMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
</select>
<!-- Select multiple users by username -->
<select id="select" resultMap="UserResultMap"
resultSets="users,arbitraryAttributes">
SELECT
guacamole_user.user_id,
guacamole_entity.entity_id,
guacamole_entity.name,
password_hash,
password_salt,
password_date,
disabled,
expired,
access_window_start,
access_window_end,
valid_from,
valid_until,
timezone,
full_name,
email_address,
organization,
organizational_role,
MAX(start_date) AS last_active
FROM guacamole_user
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
WHERE guacamole_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name
</when>
<otherwise>
LOWER(guacamole_entity.name)
</otherwise>
</choose>
IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
#{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</foreach>
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
SELECT
guacamole_user_attribute.user_id,
guacamole_user_attribute.attribute_name,
guacamole_user_attribute.attribute_value
FROM guacamole_user_attribute
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name
</when>
<otherwise>
LOWER(guacamole_entity.name)
</otherwise>
</choose>
IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
#{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</foreach>
;
</select>
<!-- Select multiple users by username only if readable -->
<select id="selectReadable" resultMap="UserResultMap"
resultSets="users,arbitraryAttributes">
SELECT
guacamole_user.user_id,
guacamole_entity.entity_id,
guacamole_entity.name,
password_hash,
password_salt,
password_date,
disabled,
expired,
access_window_start,
access_window_end,
valid_from,
valid_until,
timezone,
full_name,
email_address,
organization,
organizational_role,
MAX(start_date) AS last_active
FROM guacamole_user
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
WHERE guacamole_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name
</when>
<otherwise>
LOWER(guacamole_entity.name)
</otherwise>
</choose>
IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
#{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</foreach>
AND guacamole_user.user_id IN (
<include refid="org.apache.guacamole.auth.jdbc.user.UserMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
SELECT
guacamole_user_attribute.user_id,
guacamole_user_attribute.attribute_name,
guacamole_user_attribute.attribute_value
FROM guacamole_user_attribute
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name
</when>
<otherwise>
LOWER(guacamole_entity.name)
</otherwise>
</choose>
IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
#{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</foreach>
AND guacamole_user.user_id IN (
<include refid="org.apache.guacamole.auth.jdbc.user.UserMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
</select>
<!-- Select single user by username -->
<select id="selectOne" resultMap="UserResultMap"
resultSets="users,arbitraryAttributes">
SELECT
guacamole_user.user_id,
guacamole_entity.entity_id,
guacamole_entity.name,
password_hash,
password_salt,
password_date,
disabled,
expired,
access_window_start,
access_window_end,
valid_from,
valid_until,
timezone,
full_name,
email_address,
organization,
organizational_role,
MAX(start_date) AS last_active
FROM guacamole_user
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
WHERE guacamole_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name = #{username,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(guacamole_entity.name) = LOWER(#{username,jdbcType=VARCHAR})
</otherwise>
</choose>
GROUP BY guacamole_user.user_id, guacamole_entity.entity_id;
SELECT
guacamole_user_attribute.user_id,
guacamole_user_attribute.attribute_name,
guacamole_user_attribute.attribute_value
FROM guacamole_user_attribute
JOIN guacamole_user ON guacamole_user.user_id = guacamole_user_attribute.user_id
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name = #{username,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(guacamole_entity.name) = LOWER(#{username,jdbcType=VARCHAR})
</otherwise>
</choose>
</select>
<!-- Delete single user by username -->
<delete id="delete">
DELETE FROM guacamole_entity
WHERE type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
name = #{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(name) = LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</delete>
<!-- Insert single user -->
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
parameterType="org.apache.guacamole.auth.jdbc.user.UserModel">
INSERT INTO guacamole_user (
entity_id,
password_hash,
password_salt,
password_date,
disabled,
expired,
access_window_start,
access_window_end,
valid_from,
valid_until,
timezone,
full_name,
email_address,
organization,
organizational_role
)
VALUES (
#{object.entityID,jdbcType=VARCHAR},
#{object.passwordHash,jdbcType=BINARY},
#{object.passwordSalt,jdbcType=BINARY},
#{object.passwordDate,jdbcType=TIMESTAMP},
#{object.disabled,jdbcType=BOOLEAN},
#{object.expired,jdbcType=BOOLEAN},
#{object.accessWindowStart,jdbcType=TIME},
#{object.accessWindowEnd,jdbcType=TIME},
#{object.validFrom,jdbcType=DATE},
#{object.validUntil,jdbcType=DATE},
#{object.timeZone,jdbcType=VARCHAR},
#{object.fullName,jdbcType=VARCHAR},
#{object.emailAddress,jdbcType=VARCHAR},
#{object.organization,jdbcType=VARCHAR},
#{object.organizationalRole,jdbcType=VARCHAR}
)
</insert>
<!-- Update single user -->
<update id="update" parameterType="org.apache.guacamole.auth.jdbc.user.UserModel">
UPDATE guacamole_user
SET password_hash = #{object.passwordHash,jdbcType=BINARY},
password_salt = #{object.passwordSalt,jdbcType=BINARY},
password_date = #{object.passwordDate,jdbcType=TIMESTAMP},
disabled = #{object.disabled,jdbcType=BOOLEAN},
expired = #{object.expired,jdbcType=BOOLEAN},
access_window_start = #{object.accessWindowStart,jdbcType=TIME},
access_window_end = #{object.accessWindowEnd,jdbcType=TIME},
valid_from = #{object.validFrom,jdbcType=DATE},
valid_until = #{object.validUntil,jdbcType=DATE},
timezone = #{object.timeZone,jdbcType=VARCHAR},
full_name = #{object.fullName,jdbcType=VARCHAR},
email_address = #{object.emailAddress,jdbcType=VARCHAR},
organization = #{object.organization,jdbcType=VARCHAR},
organizational_role = #{object.organizationalRole,jdbcType=VARCHAR}
WHERE user_id = #{object.objectID,jdbcType=INTEGER}
</update>
<!-- Delete attributes associated with user -->
<delete id="deleteAttributes">
DELETE FROM guacamole_user_attribute
WHERE user_id = #{object.objectID,jdbcType=INTEGER}
</delete>
<!-- Insert attributes for user -->
<insert id="insertAttributes" parameterType="org.apache.guacamole.auth.jdbc.base.ArbitraryAttributeModel">
INSERT INTO guacamole_user_attribute (
user_id,
attribute_name,
attribute_value
)
VALUES
<foreach collection="object.arbitraryAttributes" item="attribute" separator=",">
(#{object.objectID,jdbcType=INTEGER},
#{attribute.name,jdbcType=VARCHAR},
#{attribute.value,jdbcType=VARCHAR})
</foreach>
</insert>
</mapper>

View File

@@ -0,0 +1,121 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.user.UserParentUserGroupMapper" >
<!-- Select the names of all parent user groups -->
<select id="selectChildIdentifiers" resultType="string">
SELECT name
FROM guacamole_user_group_member
JOIN guacamole_user_group ON guacamole_user_group_member.user_group_id = guacamole_user_group.user_group_id
JOIN guacamole_entity ON guacamole_entity.entity_id = guacamole_user_group.entity_id
WHERE
guacamole_user_group_member.member_entity_id = #{parent.entityID,jdbcType=INTEGER}
AND guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
</select>
<!-- Select the names of all readable parent user groups -->
<select id="selectReadableChildIdentifiers" resultType="string">
SELECT guacamole_entity.name
FROM guacamole_user_group_member
JOIN guacamole_user_group ON guacamole_user_group_member.user_group_id = guacamole_user_group.user_group_id
JOIN guacamole_entity ON guacamole_entity.entity_id = guacamole_user_group.entity_id
WHERE
guacamole_user_group.user_group_id IN (
<include refid="org.apache.guacamole.auth.jdbc.usergroup.UserGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
AND guacamole_user_group_member.member_entity_id = #{parent.entityID,jdbcType=INTEGER}
AND guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
</select>
<!-- Delete parent groups by name -->
<delete id="delete">
DELETE FROM guacamole_user_group_member
USING guacamole_user_group, guacamole_entity
WHERE
member_entity_id = #{parent.entityID,jdbcType=INTEGER}
AND guacamole_user_group.user_group_id = guacamole_user_group_member.user_group_id
AND guacamole_entity.entity_id = guacamole_user_group.entity_id
AND guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(guacamole_entity.name) IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
</delete>
<!-- Insert parent groups by name -->
<insert id="insert">
INSERT INTO guacamole_user_group_member (
user_group_id,
member_entity_id
)
SELECT DISTINCT
guacamole_user_group.user_group_id,
#{parent.entityID,jdbcType=INTEGER}
FROM guacamole_user_group
JOIN guacamole_entity ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(guacamole_entity.name) IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
AND guacamole_user_group.user_group_id NOT IN (
SELECT guacamole_user_group_member.user_group_id
FROM guacamole_user_group_member
WHERE guacamole_user_group_member.member_entity_id = #{parent.entityID,jdbcType=INTEGER}
)
</insert>
</mapper>

View File

@@ -0,0 +1,227 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.user.UserRecordMapper" >
<!-- Result mapper for system permissions -->
<resultMap id="UserRecordResultMap" type="org.apache.guacamole.auth.jdbc.base.ActivityRecordModel">
<id column="history_id" property="recordID" jdbcType="INTEGER"/>
<result column="remote_host" property="remoteHost" jdbcType="VARCHAR"/>
<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>
<!-- Insert the given user record -->
<insert id="insert" useGeneratedKeys="true" keyProperty="record.recordID"
parameterType="org.apache.guacamole.auth.jdbc.base.ActivityRecordModel">
INSERT INTO guacamole_user_history (
remote_host,
user_id,
username,
start_date,
end_date
)
VALUES (
#{record.remoteHost,jdbcType=VARCHAR},
(SELECT user_id FROM guacamole_user
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name = #{record.username,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(guacamole_entity.name) = LOWER(#{record.username,jdbcType=VARCHAR})
</otherwise>
</choose>
AND guacamole_entity.type = 'USER'::guacamole_entity_type),
#{record.username,jdbcType=VARCHAR},
#{record.startDate,jdbcType=TIMESTAMP},
#{record.endDate,jdbcType=TIMESTAMP}
)
</insert>
<!-- Update the given user record, assigning an end date -->
<update id="updateEndDate" parameterType="org.apache.guacamole.auth.jdbc.base.ActivityRecordModel">
UPDATE guacamole_user_history
SET end_date = #{record.endDate,jdbcType=TIMESTAMP}
WHERE history_id = #{record.recordID,jdbcType=INTEGER}::integer
</update>
<!-- Search for specific user records -->
<select id="search" resultMap="UserRecordResultMap">
SELECT
guacamole_user_history.history_id,
guacamole_user_history.remote_host,
guacamole_user_history.user_id,
guacamole_user_history.username,
guacamole_user_history.start_date,
guacamole_user_history.end_date
FROM guacamole_user_history
<!-- Search terms -->
<where>
<if test="identifier != null">
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_user_history.username = #{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(guacamole_user_history.username) = LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
(
guacamole_user_history.user_id IN (
SELECT user_id
FROM guacamole_user
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
</when>
<otherwise>
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(guacamole_entity.name)) > 0
</otherwise>
</choose>
AND guacamole_entity.type = 'USER'::guacamole_entity_type),
)
<if test="term.startDate != null and term.endDate != null">
OR start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP}
</if>
)
</foreach>
</where>
<!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
<!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate"
open="ORDER BY " separator=", ">
<choose>
<when test="sortPredicate.property == START_DATE">guacamole_user_history.start_date</when>
<otherwise>1</otherwise>
</choose>
<if test="sortPredicate.descending">DESC</if>
</foreach>
LIMIT #{limit,jdbcType=INTEGER}
</select>
<!-- Search for specific user records -->
<select id="searchReadable" resultMap="UserRecordResultMap">
SELECT
guacamole_user_history.history_id,
guacamole_user_history.remote_host,
guacamole_user_history.user_id,
guacamole_user_history.username,
guacamole_user_history.start_date,
guacamole_user_history.end_date
FROM guacamole_user_history
<!-- Search terms -->
<where>
<!-- Restrict to readable users -->
guacamole_connection_history.user_id IN (
<include refid="org.apache.guacamole.auth.jdbc.user.UserMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
<if test="identifier != null">
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name = #{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(guacamole_entity.name) = LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
(
guacamole_user_history.user_id IN (
SELECT user_id
FROM guacamole_user
JOIN guacamole_entity ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
POSITION(#{term.term,jdbcType=VARCHAR} IN guacamole_entity.name) > 0
</when>
<otherwise>
POSITION(LOWER(#{term.term,jdbcType=VARCHAR}) IN LOWER(guacamole_entity.name)) > 0
</otherwise>
</choose>
AND guacamole_entity.type = 'USER'::guacamole_entity_type
)
<if test="term.startDate != null and term.endDate != null">
OR start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP}
</if>
)
</foreach>
</where>
<!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
<!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate"
open="ORDER BY " separator=", ">
<choose>
<when test="sortPredicate.property == START_DATE">guacamole_user_history.start_date</when>
<otherwise>1</otherwise>
</choose>
<if test="sortPredicate.descending">DESC</if>
</foreach>
LIMIT #{limit,jdbcType=INTEGER}
</select>
</mapper>

View File

@@ -0,0 +1,329 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.usergroup.UserGroupMapper" >
<!-- Result mapper for user group objects -->
<resultMap id="UserGroupResultMap" type="org.apache.guacamole.auth.jdbc.usergroup.UserGroupModel" >
<!-- User group properties -->
<id column="user_group_id" property="objectID" jdbcType="INTEGER"/>
<result column="entity_id" property="entityID" jdbcType="INTEGER"/>
<result column="name" property="identifier" jdbcType="VARCHAR"/>
<result column="disabled" property="disabled" jdbcType="BOOLEAN"/>
<!-- Arbitrary attributes -->
<collection property="arbitraryAttributes" resultSet="arbitraryAttributes"
ofType="org.apache.guacamole.auth.jdbc.base.ArbitraryAttributeModel"
column="user_group_id" foreignColumn="user_group_id">
<result property="name" column="attribute_name" jdbcType="VARCHAR"/>
<result property="value" column="attribute_value" jdbcType="VARCHAR"/>
</collection>
</resultMap>
<!-- Select all group names -->
<select id="selectIdentifiers" resultType="string">
SELECT name
FROM guacamole_entity
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
</select>
<!--
* SQL fragment which lists the IDs of all user groups readable by the
* entity having the given entity ID. If group identifiers are provided,
* the IDs of the entities for all groups having those identifiers are
* tested, as well. Disabled groups are ignored.
*
* @param entityID
* The ID of the specific entity to test against.
*
* @param groups
* A collection of group identifiers to additionally test against.
* Though this functionality is optional, a collection must always be
* given, even if that collection is empty.
-->
<sql id="getReadableIDs">
SELECT DISTINCT guacamole_user_group_permission.affected_user_group_id
FROM guacamole_user_group_permission
WHERE
<include refid="org.apache.guacamole.auth.jdbc.base.EntityMapper.isRelatedEntity">
<property name="column" value="entity_id"/>
<property name="entityID" value="${entityID}"/>
<property name="groups" value="${groups}"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
AND permission = 'READ'
</sql>
<!-- Select names of all readable groups -->
<select id="selectReadableIdentifiers" resultType="string">
SELECT guacamole_entity.name
FROM guacamole_user_group
JOIN guacamole_entity ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND guacamole_user_group.user_group_id IN (
<include refid="org.apache.guacamole.auth.jdbc.usergroup.UserGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
</select>
<!-- Select multiple groups by name -->
<select id="select" resultMap="UserGroupResultMap"
resultSets="users,arbitraryAttributes">
SELECT
guacamole_user_group.user_group_id,
guacamole_entity.entity_id,
guacamole_entity.name,
disabled
FROM guacamole_user_group
JOIN guacamole_entity ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(guacamole_entity.name) IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
;
SELECT
guacamole_user_group_attribute.user_group_id,
guacamole_user_group_attribute.attribute_name,
guacamole_user_group_attribute.attribute_value
FROM guacamole_user_group_attribute
JOIN guacamole_user_group ON guacamole_user_group.user_group_id = guacamole_user_group_attribute.user_group_id
JOIN guacamole_entity ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(guacamole_entity.name) IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
;
</select>
<!-- Select multiple groups by name only if readable -->
<select id="selectReadable" resultMap="UserGroupResultMap"
resultSets="users,arbitraryAttributes">
SELECT
guacamole_user_group.user_group_id,
guacamole_entity.entity_id,
guacamole_entity.name,
disabled
FROM guacamole_user_group
JOIN guacamole_entity ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(guacamole_entity.name) IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
AND guacamole_user_group.user_group_id IN (
<include refid="org.apache.guacamole.auth.jdbc.usergroup.UserGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
SELECT
guacamole_user_group_attribute.user_group_id,
guacamole_user_group_attribute.attribute_name,
guacamole_user_group_attribute.attribute_value
FROM guacamole_user_group_attribute
JOIN guacamole_user_group ON guacamole_user_group.user_group_id = guacamole_user_group_attribute.user_group_id
JOIN guacamole_entity ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(guacamole_entity.name) IN
<foreach collection="identifiers" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
AND guacamole_user_group.user_group_id IN (
<include refid="org.apache.guacamole.auth.jdbc.usergroup.UserGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
);
</select>
<!-- Select single group by name -->
<select id="selectOne" resultMap="UserGroupResultMap"
resultSets="users,arbitraryAttributes">
SELECT
guacamole_user_group.user_group_id,
guacamole_entity.entity_id,
guacamole_entity.name,
disabled
FROM guacamole_user_group
JOIN guacamole_entity ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name = #{name,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(guacamole_entity.name) = LOWER(#{name,jdbcType=VARCHAR})
</otherwise>
</choose>
;
SELECT
guacamole_user_group_attribute.user_group_id,
guacamole_user_group_attribute.attribute_name,
guacamole_user_group_attribute.attribute_value
FROM guacamole_user_group_attribute
JOIN guacamole_user_group ON guacamole_user_group.user_group_id = guacamole_user_group_attribute.user_group_id
JOIN guacamole_entity ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name = #{name,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(guacamole_entity.name) = LOWER(#{name,jdbcType=VARCHAR})
</otherwise>
</choose>
;
</select>
<!-- Delete single group by name -->
<delete id="delete">
DELETE FROM guacamole_entity
WHERE type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
name = #{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(name) = LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</delete>
<!-- Insert single group -->
<insert id="insert" useGeneratedKeys="true" keyProperty="object.objectID"
parameterType="org.apache.guacamole.auth.jdbc.usergroup.UserGroupModel">
INSERT INTO guacamole_user_group (
entity_id,
disabled
)
VALUES (
#{object.entityID,jdbcType=VARCHAR},
#{object.disabled,jdbcType=BOOLEAN}
)
</insert>
<!-- Update single group -->
<update id="update" parameterType="org.apache.guacamole.auth.jdbc.usergroup.UserGroupModel">
UPDATE guacamole_user_group
SET disabled = #{object.disabled,jdbcType=BOOLEAN}
WHERE user_group_id = #{object.objectID,jdbcType=VARCHAR}
</update>
<!-- Delete attributes associated with group -->
<delete id="deleteAttributes">
DELETE FROM guacamole_user_group_attribute
WHERE user_group_id = #{object.objectID,jdbcType=INTEGER}
</delete>
<!-- Insert attributes for group -->
<insert id="insertAttributes" parameterType="org.apache.guacamole.auth.jdbc.base.ArbitraryAttributeModel">
INSERT INTO guacamole_user_group_attribute (
user_group_id,
attribute_name,
attribute_value
)
VALUES
<foreach collection="object.arbitraryAttributes" item="attribute" separator=",">
(#{object.objectID,jdbcType=INTEGER},
#{attribute.name,jdbcType=VARCHAR},
#{attribute.value,jdbcType=VARCHAR})
</foreach>
</insert>
</mapper>

View File

@@ -0,0 +1,117 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.usergroup.UserGroupMemberUserGroupMapper" >
<!-- Select the names of all member user groups -->
<select id="selectChildIdentifiers" resultType="string">
SELECT name
FROM guacamole_user_group_member
JOIN guacamole_entity ON guacamole_entity.entity_id = guacamole_user_group_member.member_entity_id
WHERE
guacamole_user_group_member.user_group_id = #{parent.objectID,jdbcType=INTEGER}
AND guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
</select>
<!-- Select the names of all readable member user groups -->
<select id="selectReadableChildIdentifiers" resultType="string">
SELECT guacamole_entity.name
FROM guacamole_user_group_member
JOIN guacamole_entity ON guacamole_entity.entity_id = guacamole_user_group_member.member_entity_id
JOIN guacamole_user_group ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE
guacamole_user_group.user_group_id IN (
<include refid="org.apache.guacamole.auth.jdbc.usergroup.UserGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
AND guacamole_user_group_member.user_group_id = #{parent.objectID,jdbcType=INTEGER}
AND guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
</select>
<!-- Delete member groups by name -->
<delete id="delete">
DELETE FROM guacamole_user_group_member
USING guacamole_entity
WHERE
user_group_id = #{parent.objectID,jdbcType=INTEGER}
AND guacamole_entity.entity_id = member_entity_id
AND guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(guacamole_entity.name) IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
</delete>
<!-- Insert member groups by name -->
<insert id="insert">
INSERT INTO guacamole_user_group_member (
user_group_id,
member_entity_id
)
SELECT DISTINCT
#{parent.objectID,jdbcType=INTEGER},
guacamole_entity.entity_id
FROM guacamole_entity
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
#{identifier}
</foreach>
</when>
<otherwise>
LOWER(guacamole_entity.name) IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier})
</foreach>
</otherwise>
</choose>
AND guacamole_entity.entity_id NOT IN (
SELECT guacamole_user_group_member.member_entity_id
FROM guacamole_user_group_member
WHERE guacamole_user_group_member.user_group_id = #{parent.objectID,jdbcType=INTEGER}
)
</insert>
</mapper>

View File

@@ -0,0 +1,124 @@
<?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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.usergroup.UserGroupMemberUserMapper" >
<!-- Select the username of all member users -->
<select id="selectChildIdentifiers" resultType="string">
SELECT name
FROM guacamole_user_group_member
JOIN guacamole_entity ON guacamole_entity.entity_id = guacamole_user_group_member.member_entity_id
WHERE
guacamole_user_group_member.user_group_id = #{parent.objectID,jdbcType=INTEGER}
AND guacamole_entity.type = 'USER'::guacamole_entity_type
</select>
<!-- Select the usernames of all readable member users -->
<select id="selectReadableChildIdentifiers" resultType="string">
SELECT guacamole_entity.name
FROM guacamole_user_group_member
JOIN guacamole_entity ON guacamole_entity.entity_id = guacamole_user_group_member.member_entity_id
JOIN guacamole_user ON guacamole_user.entity_id = guacamole_entity.entity_id
WHERE
guacamole_user.user_id IN (
<include refid="org.apache.guacamole.auth.jdbc.user.UserMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
AND guacamole_user_group_member.user_group_id = #{parent.objectID,jdbcType=INTEGER}
AND guacamole_entity.type = 'USER'::guacamole_entity_type
</select>
<!-- Delete member users by name -->
<delete id="delete">
DELETE FROM guacamole_user_group_member
USING guacamole_entity
WHERE
user_group_id = #{parent.objectID,jdbcType=INTEGER}
AND guacamole_entity.entity_id = member_entity_id
AND guacamole_entity.type = 'USER'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name
</when>
<otherwise>
LOWER(guacamole_entity.name)
</otherwise>
</choose>
IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
#{identifier,jdbcType=VARCHAR}
</when>
<otherwise>
LOWER(#{identifier,jdbcType=VARCHAR})
</otherwise>
</choose>
</foreach>
</delete>
<!-- Insert member users by name -->
<insert id="insert">
INSERT INTO guacamole_user_group_member (
user_group_id,
member_entity_id
)
SELECT DISTINCT
#{parent.objectID,jdbcType=INTEGER},
guacamole_entity.entity_id
FROM guacamole_entity
WHERE
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
guacamole_entity.name
</when>
<otherwise>
LOWER(guacamole_entity.name)
</otherwise>
</choose>
IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
<choose>
<when test="caseSensitivity.caseSensitiveUsernames()">
#{identifier}
</when>
<otherwise>
LOWER(#{identifier})
</otherwise>
</choose>
</foreach>
AND guacamole_entity.type = 'USER'::guacamole_entity_type
AND guacamole_entity.entity_id NOT IN (
SELECT guacamole_user_group_member.member_entity_id
FROM guacamole_user_group_member
WHERE guacamole_user_group_member.user_group_id = #{parent.objectID,jdbcType=INTEGER}
)
</insert>
</mapper>

View File

@@ -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" >
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<mapper namespace="org.apache.guacamole.auth.jdbc.usergroup.UserGroupParentUserGroupMapper" >
<!-- Select the names of all parent user groups -->
<select id="selectChildIdentifiers" resultType="string">
SELECT name
FROM guacamole_user_group_member
JOIN guacamole_user_group ON guacamole_user_group_member.user_group_id = guacamole_user_group.user_group_id
JOIN guacamole_entity ON guacamole_entity.entity_id = guacamole_user_group.entity_id
WHERE
guacamole_user_group_member.member_entity_id = #{parent.entityID,jdbcType=INTEGER}
AND guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
</select>
<!-- Select the names of all readable parent user groups -->
<select id="selectReadableChildIdentifiers" resultType="string">
SELECT guacamole_entity.name
FROM guacamole_user_group_member
JOIN guacamole_user_group ON guacamole_user_group_member.user_group_id = guacamole_user_group.user_group_id
JOIN guacamole_entity ON guacamole_entity.entity_id = guacamole_user_group.entity_id
WHERE
guacamole_user_group.user_group_id IN (
<include refid="org.apache.guacamole.auth.jdbc.usergroup.UserGroupMapper.getReadableIDs">
<property name="entityID" value="#{user.entityID,jdbcType=INTEGER}"/>
<property name="groups" value="effectiveGroups"/>
<property name="caseSensitivity" value="${caseSensitivity}"/>
</include>
)
AND guacamole_user_group_member.member_entity_id = #{parent.entityID,jdbcType=INTEGER}
AND guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
</select>
<!-- Delete parent groups by name -->
<delete id="delete">
DELETE FROM guacamole_user_group_member
USING guacamole_user_group, guacamole_entity
WHERE
member_entity_id = #{parent.entityID,jdbcType=INTEGER}
AND guacamole_user_group.user_group_id = guacamole_user_group_member.user_group_id
AND guacamole_entity.entity_id = guacamole_user_group.entity_id
AND guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(guacamole_entity.name) IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
</delete>
<!-- Insert parent groups by name -->
<insert id="insert">
INSERT INTO guacamole_user_group_member (
user_group_id,
member_entity_id
)
SELECT DISTINCT
guacamole_user_group.user_group_id,
#{parent.entityID,jdbcType=INTEGER}
FROM guacamole_user_group
JOIN guacamole_entity ON guacamole_user_group.entity_id = guacamole_entity.entity_id
WHERE guacamole_entity.type = 'USER_GROUP'::guacamole_entity_type
AND
<choose>
<when test="caseSensitivity.caseSensitiveGroupNames()">
guacamole_entity.name IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
#{identifier,jdbcType=VARCHAR}
</foreach>
</when>
<otherwise>
LOWER(guacamole_entity.name) IN
<foreach collection="children" item="identifier"
open="(" separator="," close=")">
LOWER(#{identifier,jdbcType=VARCHAR})
</foreach>
</otherwise>
</choose>
AND guacamole_user_group.user_group_id NOT IN (
SELECT guacamole_user_group_member.user_group_id
FROM guacamole_user_group_member
WHERE guacamole_user_group_member.member_entity_id = #{parent.entityID,jdbcType=INTEGER}
)
</insert>
</mapper>