You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by vn...@apache.org on 2018/02/01 18:32:44 UTC

[01/10] guacamole-client git commit: GUACAMOLE-96: Correct version number of upgrade scripts for next release (it will be 1.0.0, not 0.9.15).

Repository: guacamole-client
Updated Branches:
  refs/heads/master a050c1602 -> 07d030785


GUACAMOLE-96: Correct version number of upgrade scripts for next release (it will be 1.0.0, not 0.9.15).

Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/d5768ead
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/d5768ead
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/d5768ead

Branch: refs/heads/master
Commit: d5768ead6dc1044d3ee86b1dc05c280aaee80b01
Parents: 2d68576
Author: Michael Jumper <mj...@apache.org>
Authored: Tue Jan 30 13:24:32 2018 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Jan 31 15:26:16 2018 -0800

----------------------------------------------------------------------
 .../schema/upgrade/upgrade-pre-0.9.15.sql       | 106 ----------------
 .../schema/upgrade/upgrade-pre-1.0.0.sql        | 106 ++++++++++++++++
 .../schema/upgrade/upgrade-pre-0.9.15.sql       | 114 -----------------
 .../schema/upgrade/upgrade-pre-1.0.0.sql        | 114 +++++++++++++++++
 .../schema/upgrade/upgrade-pre-0.9.15.sql       | 127 -------------------
 .../schema/upgrade/upgrade-pre-1.0.0.sql        | 127 +++++++++++++++++++
 6 files changed, 347 insertions(+), 347 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/d5768ead/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.15.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.15.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.15.sql
deleted file mode 100644
index 2979f53..0000000
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.15.sql
+++ /dev/null
@@ -1,106 +0,0 @@
---
--- 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.
---
-
---
--- 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`         int(11)       NOT NULL,
-  `attribute_name`  varchar(128)  NOT NULL,
-  `attribute_value` varchar(4096) NOT NULL,
-
-  PRIMARY KEY (user_id, attribute_name),
-  KEY `user_id` (`user_id`),
-
-  CONSTRAINT guacamole_user_attribute_ibfk_1
-    FOREIGN KEY (user_id)
-    REFERENCES guacamole_user (user_id) ON DELETE CASCADE
-
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- 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`   int(11)       NOT NULL,
-  `attribute_name`  varchar(128)  NOT NULL,
-  `attribute_value` varchar(4096) NOT NULL,
-
-  PRIMARY KEY (connection_id, attribute_name),
-  KEY `connection_id` (`connection_id`),
-
-  CONSTRAINT guacamole_connection_attribute_ibfk_1
-    FOREIGN KEY (connection_id)
-    REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
-
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- 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` int(11)       NOT NULL,
-  `attribute_name`      varchar(128)  NOT NULL,
-  `attribute_value`     varchar(4096) NOT NULL,
-
-  PRIMARY KEY (connection_group_id, attribute_name),
-  KEY `connection_group_id` (`connection_group_id`),
-
-  CONSTRAINT guacamole_connection_group_attribute_ibfk_1
-    FOREIGN KEY (connection_group_id)
-    REFERENCES guacamole_connection_group (connection_group_id) ON DELETE CASCADE
-
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
---
--- 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` int(11)       NOT NULL,
-  `attribute_name`     varchar(128)  NOT NULL,
-  `attribute_value`    varchar(4096) NOT NULL,
-
-  PRIMARY KEY (sharing_profile_id, attribute_name),
-  KEY `sharing_profile_id` (`sharing_profile_id`),
-
-  CONSTRAINT guacamole_sharing_profile_attribute_ibfk_1
-    FOREIGN KEY (sharing_profile_id)
-    REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
-
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/d5768ead/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-1.0.0.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-1.0.0.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-1.0.0.sql
new file mode 100644
index 0000000..2979f53
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-1.0.0.sql
@@ -0,0 +1,106 @@
+--
+-- 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.
+--
+
+--
+-- 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`         int(11)       NOT NULL,
+  `attribute_name`  varchar(128)  NOT NULL,
+  `attribute_value` varchar(4096) NOT NULL,
+
+  PRIMARY KEY (user_id, attribute_name),
+  KEY `user_id` (`user_id`),
+
+  CONSTRAINT guacamole_user_attribute_ibfk_1
+    FOREIGN KEY (user_id)
+    REFERENCES guacamole_user (user_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 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`   int(11)       NOT NULL,
+  `attribute_name`  varchar(128)  NOT NULL,
+  `attribute_value` varchar(4096) NOT NULL,
+
+  PRIMARY KEY (connection_id, attribute_name),
+  KEY `connection_id` (`connection_id`),
+
+  CONSTRAINT guacamole_connection_attribute_ibfk_1
+    FOREIGN KEY (connection_id)
+    REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 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` int(11)       NOT NULL,
+  `attribute_name`      varchar(128)  NOT NULL,
+  `attribute_value`     varchar(4096) NOT NULL,
+
+  PRIMARY KEY (connection_group_id, attribute_name),
+  KEY `connection_group_id` (`connection_group_id`),
+
+  CONSTRAINT guacamole_connection_group_attribute_ibfk_1
+    FOREIGN KEY (connection_group_id)
+    REFERENCES guacamole_connection_group (connection_group_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 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` int(11)       NOT NULL,
+  `attribute_name`     varchar(128)  NOT NULL,
+  `attribute_value`    varchar(4096) NOT NULL,
+
+  PRIMARY KEY (sharing_profile_id, attribute_name),
+  KEY `sharing_profile_id` (`sharing_profile_id`),
+
+  CONSTRAINT guacamole_sharing_profile_attribute_ibfk_1
+    FOREIGN KEY (sharing_profile_id)
+    REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/d5768ead/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.15.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.15.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.15.sql
deleted file mode 100644
index db115c2..0000000
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.15.sql
+++ /dev/null
@@ -1,114 +0,0 @@
---
--- 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.
---
-
---
--- 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 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);

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/d5768ead/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-1.0.0.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-1.0.0.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-1.0.0.sql
new file mode 100644
index 0000000..db115c2
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-1.0.0.sql
@@ -0,0 +1,114 @@
+--
+-- 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.
+--
+
+--
+-- 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 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);

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/d5768ead/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-0.9.15.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-0.9.15.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-0.9.15.sql
deleted file mode 100644
index cb02dd5..0000000
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-0.9.15.sql
+++ /dev/null
@@ -1,127 +0,0 @@
---
--- 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.
---
-
---
--- 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]         [int]            NOT NULL,
-    [attribute_name]  [nvarchar](128)  NOT NULL,
-    [attribute_value] [nvarchar](4000) NOT NULL,
-
-    CONSTRAINT [PK_guacamole_user_attribute]
-        PRIMARY KEY CLUSTERED ([user_id], [attribute_name]),
-
-    CONSTRAINT [FK_guacamole_user_attribute_user_id]
-        FOREIGN KEY ([user_id])
-        REFERENCES [guacamole_user] ([user_id])
-        ON DELETE CASCADE
-
-);
-
-CREATE NONCLUSTERED INDEX [IX_guacamole_user_attribute_user_id]
-    ON [guacamole_user_attribute] ([user_id])
-    INCLUDE ([attribute_name], [attribute_value]);
-GO
-
---
--- 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]   [int]            NOT NULL,
-    [attribute_name]  [nvarchar](128)  NOT NULL,
-    [attribute_value] [nvarchar](4000) NOT NULL,
-
-    PRIMARY KEY (connection_id, attribute_name),
-
-    CONSTRAINT [FK_guacamole_connection_attribute_connection_id]
-        FOREIGN KEY ([connection_id])
-        REFERENCES [guacamole_connection] ([connection_id])
-        ON DELETE CASCADE
-
-);
-
-CREATE NONCLUSTERED INDEX [IX_guacamole_connection_attribute_connection_id]
-    ON [guacamole_connection_attribute] ([connection_id])
-    INCLUDE ([attribute_name], [attribute_value]);
-GO
-
---
--- 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] [int]            NOT NULL,
-    [attribute_name]      [nvarchar](128)  NOT NULL,
-    [attribute_value]     [nvarchar](4000) NOT NULL,
-
-    PRIMARY KEY (connection_group_id, attribute_name),
-
-    CONSTRAINT [FK_guacamole_connection_group_attribute_connection_group_id]
-        FOREIGN KEY ([connection_group_id])
-        REFERENCES [guacamole_connection_group] ([connection_group_id])
-        ON DELETE CASCADE
-
-);
-
-CREATE NONCLUSTERED INDEX [IX_guacamole_connection_group_attribute_connection_group_id]
-    ON [guacamole_connection_group_attribute] ([connection_group_id])
-    INCLUDE ([attribute_name], [attribute_value]);
-GO
-
---
--- 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] [int]            NOT NULL,
-    [attribute_name]     [nvarchar](128)  NOT NULL,
-    [attribute_value]    [nvarchar](4000) NOT NULL,
-
-    PRIMARY KEY (sharing_profile_id, attribute_name),
-
-    CONSTRAINT [FK_guacamole_sharing_profile_attribute_sharing_profile_id]
-        FOREIGN KEY ([sharing_profile_id])
-        REFERENCES [guacamole_sharing_profile] ([sharing_profile_id])
-        ON DELETE CASCADE
-
-);
-
-CREATE NONCLUSTERED INDEX [IX_guacamole_sharing_profile_attribute_sharing_profile_id]
-    ON [guacamole_sharing_profile_attribute] ([sharing_profile_id])
-    INCLUDE ([attribute_name], [attribute_value]);
-GO

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/d5768ead/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-1.0.0.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-1.0.0.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-1.0.0.sql
new file mode 100644
index 0000000..cb02dd5
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-1.0.0.sql
@@ -0,0 +1,127 @@
+--
+-- 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.
+--
+
+--
+-- 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]         [int]            NOT NULL,
+    [attribute_name]  [nvarchar](128)  NOT NULL,
+    [attribute_value] [nvarchar](4000) NOT NULL,
+
+    CONSTRAINT [PK_guacamole_user_attribute]
+        PRIMARY KEY CLUSTERED ([user_id], [attribute_name]),
+
+    CONSTRAINT [FK_guacamole_user_attribute_user_id]
+        FOREIGN KEY ([user_id])
+        REFERENCES [guacamole_user] ([user_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_user_attribute_user_id]
+    ON [guacamole_user_attribute] ([user_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO
+
+--
+-- 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]   [int]            NOT NULL,
+    [attribute_name]  [nvarchar](128)  NOT NULL,
+    [attribute_value] [nvarchar](4000) NOT NULL,
+
+    PRIMARY KEY (connection_id, attribute_name),
+
+    CONSTRAINT [FK_guacamole_connection_attribute_connection_id]
+        FOREIGN KEY ([connection_id])
+        REFERENCES [guacamole_connection] ([connection_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_connection_attribute_connection_id]
+    ON [guacamole_connection_attribute] ([connection_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO
+
+--
+-- 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] [int]            NOT NULL,
+    [attribute_name]      [nvarchar](128)  NOT NULL,
+    [attribute_value]     [nvarchar](4000) NOT NULL,
+
+    PRIMARY KEY (connection_group_id, attribute_name),
+
+    CONSTRAINT [FK_guacamole_connection_group_attribute_connection_group_id]
+        FOREIGN KEY ([connection_group_id])
+        REFERENCES [guacamole_connection_group] ([connection_group_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_connection_group_attribute_connection_group_id]
+    ON [guacamole_connection_group_attribute] ([connection_group_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO
+
+--
+-- 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] [int]            NOT NULL,
+    [attribute_name]     [nvarchar](128)  NOT NULL,
+    [attribute_value]    [nvarchar](4000) NOT NULL,
+
+    PRIMARY KEY (sharing_profile_id, attribute_name),
+
+    CONSTRAINT [FK_guacamole_sharing_profile_attribute_sharing_profile_id]
+        FOREIGN KEY ([sharing_profile_id])
+        REFERENCES [guacamole_sharing_profile] ([sharing_profile_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_sharing_profile_attribute_sharing_profile_id]
+    ON [guacamole_sharing_profile_attribute] ([sharing_profile_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO


[02/10] guacamole-client git commit: GUACAMOLE-96: Map base JDBC support for arbitrary attributes to SQL Server tables.

Posted by vn...@apache.org.
GUACAMOLE-96: Map base JDBC support for arbitrary attributes to SQL Server tables.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/2d685766
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/2d685766
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/2d685766

Branch: refs/heads/master
Commit: 2d685766c01212f80602e5f00d85a6b8ed8a8ae2
Parents: 6a834a1
Author: Michael Jumper <mj...@apache.org>
Authored: Sat Nov 25 12:29:39 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Jan 31 15:26:16 2018 -0800

----------------------------------------------------------------------
 .../schema/001-create-schema.sql                | 110 ++++++++++++++++
 .../schema/upgrade/upgrade-pre-0.9.15.sql       | 127 +++++++++++++++++++
 .../auth/jdbc/connection/ConnectionMapper.xml   |  58 ++++++++-
 .../connectiongroup/ConnectionGroupMapper.xml   |  58 ++++++++-
 .../sharingprofile/SharingProfileMapper.xml     |  69 +++++++++-
 .../guacamole/auth/jdbc/user/UserMapper.xml     |  80 +++++++++++-
 6 files changed, 488 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/2d685766/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/001-create-schema.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/001-create-schema.sql
index 060503a..ee10dda 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/001-create-schema.sql
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/001-create-schema.sql
@@ -242,6 +242,115 @@ CREATE NONCLUSTERED INDEX [IX_guacamole_sharing_profile_primary_connection_id]
 GO
 
 --
+-- 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]         [int]            NOT NULL,
+    [attribute_name]  [nvarchar](128)  NOT NULL,
+    [attribute_value] [nvarchar](4000) NOT NULL,
+
+    CONSTRAINT [PK_guacamole_user_attribute]
+        PRIMARY KEY CLUSTERED ([user_id], [attribute_name]),
+
+    CONSTRAINT [FK_guacamole_user_attribute_user_id]
+        FOREIGN KEY ([user_id])
+        REFERENCES [guacamole_user] ([user_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_user_attribute_user_id]
+    ON [guacamole_user_attribute] ([user_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO
+
+--
+-- 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]   [int]            NOT NULL,
+    [attribute_name]  [nvarchar](128)  NOT NULL,
+    [attribute_value] [nvarchar](4000) NOT NULL,
+
+    PRIMARY KEY (connection_id, attribute_name),
+
+    CONSTRAINT [FK_guacamole_connection_attribute_connection_id]
+        FOREIGN KEY ([connection_id])
+        REFERENCES [guacamole_connection] ([connection_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_connection_attribute_connection_id]
+    ON [guacamole_connection_attribute] ([connection_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO
+
+--
+-- 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] [int]            NOT NULL,
+    [attribute_name]      [nvarchar](128)  NOT NULL,
+    [attribute_value]     [nvarchar](4000) NOT NULL,
+
+    PRIMARY KEY (connection_group_id, attribute_name),
+
+    CONSTRAINT [FK_guacamole_connection_group_attribute_connection_group_id]
+        FOREIGN KEY ([connection_group_id])
+        REFERENCES [guacamole_connection_group] ([connection_group_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_connection_group_attribute_connection_group_id]
+    ON [guacamole_connection_group_attribute] ([connection_group_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO
+
+--
+-- 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] [int]            NOT NULL,
+    [attribute_name]     [nvarchar](128)  NOT NULL,
+    [attribute_value]    [nvarchar](4000) NOT NULL,
+
+    PRIMARY KEY (sharing_profile_id, attribute_name),
+
+    CONSTRAINT [FK_guacamole_sharing_profile_attribute_sharing_profile_id]
+        FOREIGN KEY ([sharing_profile_id])
+        REFERENCES [guacamole_sharing_profile] ([sharing_profile_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_sharing_profile_attribute_sharing_profile_id]
+    ON [guacamole_sharing_profile_attribute] ([sharing_profile_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO
+
+--
 -- Table of connection parameters. Each parameter is simply a name/value pair
 -- associated with a connection.
 --
@@ -683,3 +792,4 @@ AS BEGIN
 
 END
 GO
+

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/2d685766/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-0.9.15.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-0.9.15.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-0.9.15.sql
new file mode 100644
index 0000000..cb02dd5
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/schema/upgrade/upgrade-pre-0.9.15.sql
@@ -0,0 +1,127 @@
+--
+-- 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.
+--
+
+--
+-- 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]         [int]            NOT NULL,
+    [attribute_name]  [nvarchar](128)  NOT NULL,
+    [attribute_value] [nvarchar](4000) NOT NULL,
+
+    CONSTRAINT [PK_guacamole_user_attribute]
+        PRIMARY KEY CLUSTERED ([user_id], [attribute_name]),
+
+    CONSTRAINT [FK_guacamole_user_attribute_user_id]
+        FOREIGN KEY ([user_id])
+        REFERENCES [guacamole_user] ([user_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_user_attribute_user_id]
+    ON [guacamole_user_attribute] ([user_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO
+
+--
+-- 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]   [int]            NOT NULL,
+    [attribute_name]  [nvarchar](128)  NOT NULL,
+    [attribute_value] [nvarchar](4000) NOT NULL,
+
+    PRIMARY KEY (connection_id, attribute_name),
+
+    CONSTRAINT [FK_guacamole_connection_attribute_connection_id]
+        FOREIGN KEY ([connection_id])
+        REFERENCES [guacamole_connection] ([connection_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_connection_attribute_connection_id]
+    ON [guacamole_connection_attribute] ([connection_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO
+
+--
+-- 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] [int]            NOT NULL,
+    [attribute_name]      [nvarchar](128)  NOT NULL,
+    [attribute_value]     [nvarchar](4000) NOT NULL,
+
+    PRIMARY KEY (connection_group_id, attribute_name),
+
+    CONSTRAINT [FK_guacamole_connection_group_attribute_connection_group_id]
+        FOREIGN KEY ([connection_group_id])
+        REFERENCES [guacamole_connection_group] ([connection_group_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_connection_group_attribute_connection_group_id]
+    ON [guacamole_connection_group_attribute] ([connection_group_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO
+
+--
+-- 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] [int]            NOT NULL,
+    [attribute_name]     [nvarchar](128)  NOT NULL,
+    [attribute_value]    [nvarchar](4000) NOT NULL,
+
+    PRIMARY KEY (sharing_profile_id, attribute_name),
+
+    CONSTRAINT [FK_guacamole_sharing_profile_attribute_sharing_profile_id]
+        FOREIGN KEY ([sharing_profile_id])
+        REFERENCES [guacamole_sharing_profile] ([sharing_profile_id])
+        ON DELETE CASCADE
+
+);
+
+CREATE NONCLUSTERED INDEX [IX_guacamole_sharing_profile_attribute_sharing_profile_id]
+    ON [guacamole_sharing_profile_attribute] ([sharing_profile_id])
+    INCLUDE ([attribute_name], [attribute_value]);
+GO

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/2d685766/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
index 19c3912..fb61757 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
@@ -47,6 +47,14 @@
             <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 -->
@@ -87,7 +95,7 @@
 
     <!-- Select multiple connections by identifier -->
     <select id="select" resultMap="ConnectionResultMap"
-            resultSets="connections,sharingProfiles">
+            resultSets="connections,sharingProfiles,arbitraryAttributes">
 
         SELECT
             [guacamole_connection].connection_id,
@@ -121,11 +129,22 @@
                 #{identifier,jdbcType=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}
+            </foreach>;
+
     </select>
 
     <!-- Select multiple connections by identifier only if readable -->
     <select id="selectReadable" resultMap="ConnectionResultMap"
-            resultSets="connections,sharingProfiles">
+            resultSets="connections,sharingProfiles,arbitraryAttributes">
 
         SELECT
             [guacamole_connection].connection_id,
@@ -165,6 +184,20 @@
             AND user_id = #{user.objectID,jdbcType=INTEGER}
             AND permission = 'READ';
 
+        SELECT
+            [guacamole_connection_attribute].connection_id,
+            attribute_name,
+            attribute_value
+        FROM [guacamole_connection_attribute]
+        JOIN [guacamole_connection_permission] ON [guacamole_connection_permission].connection_id = [guacamole_connection_attribute].connection_id
+        WHERE [guacamole_connection_attribute].connection_id IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=INTEGER}
+            </foreach>
+            AND user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
+
     </select>
 
     <!-- Select single connection by name -->
@@ -248,4 +281,25 @@
         WHERE connection_id = #{object.objectID,jdbcType=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>

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/2d685766/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
index 452c0a8..f75943e 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
@@ -48,6 +48,14 @@
             <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 -->
@@ -88,7 +96,7 @@
 
     <!-- Select multiple connection groups by identifier -->
     <select id="select" resultMap="ConnectionGroupResultMap"
-            resultSets="connectionGroups,childConnectionGroups,childConnections">
+            resultSets="connectionGroups,childConnectionGroups,childConnections,arbitraryAttributes">
 
         SELECT
             connection_group_id,
@@ -121,11 +129,22 @@
                 #{identifier,jdbcType=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}
+            </foreach>;
+
     </select>
 
     <!-- Select multiple connection groups by identifier only if readable -->
     <select id="selectReadable" resultMap="ConnectionGroupResultMap"
-            resultSets="connectionGroups,childConnectionGroups,childConnections">
+            resultSets="connectionGroups,childConnectionGroups,childConnections,arbitraryAttributes">
 
         SELECT
             [guacamole_connection_group].connection_group_id,
@@ -167,6 +186,20 @@
             AND user_id = #{user.objectID,jdbcType=INTEGER}
             AND permission = 'READ';
 
+        SELECT
+            [guacamole_connection_group_attribute].connection_group_id,
+            attribute_name,
+            attribute_value
+        FROM [guacamole_connection_group_attribute]
+        JOIN [guacamole_connection_group_permission] ON [guacamole_connection_group_permission].connection_group_id = [guacamole_connection_group_attribute].connection_group_id
+        WHERE [guacamole_connection_group_attribute].connection_group_id IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=INTEGER}
+            </foreach>
+            AND user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
+
     </select>
 
     <!-- Select single connection group by name -->
@@ -229,4 +262,25 @@
         WHERE connection_group_id = #{object.objectID,jdbcType=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>

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/2d685766/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
index 3b4ba09..0b3212f 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
@@ -25,9 +25,20 @@
 
     <!-- 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 -->
@@ -46,7 +57,8 @@
     </select>
 
     <!-- Select multiple sharing profiles by identifier -->
-    <select id="select" resultMap="SharingProfileResultMap">
+    <select id="select" resultMap="SharingProfileResultMap"
+            resultSets="sharingProfiles,arbitraryAttributes">
 
         SELECT
             sharing_profile_id,
@@ -57,12 +69,24 @@
             <foreach collection="identifiers" item="identifier"
                      open="(" separator="," close=")">
                 #{identifier,jdbcType=INTEGER}
-            </foreach>
+            </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}
+            </foreach>;
 
     </select>
 
     <!-- Select multiple sharing profiles by identifier only if readable -->
-    <select id="selectReadable" resultMap="SharingProfileResultMap">
+    <select id="selectReadable" resultMap="SharingProfileResultMap"
+            resultSets="sharingProfiles,arbitraryAttributes">
 
         SELECT
             [guacamole_sharing_profile].sharing_profile_id,
@@ -76,7 +100,21 @@
                 #{identifier,jdbcType=INTEGER}
             </foreach>
             AND user_id = #{user.objectID,jdbcType=INTEGER}
-            AND permission = 'READ'
+            AND permission = 'READ';
+
+        SELECT
+            [guacamole_sharing_profile_attribute].sharing_profile_id,
+            attribute_name,
+            attribute_value
+        FROM [guacamole_sharing_profile_attribute]
+        JOIN [guacamole_sharing_profile_permission] ON [guacamole_sharing_profile_permission].sharing_profile_id = [guacamole_sharing_profile_attribute].sharing_profile_id
+        WHERE [guacamole_sharing_profile_attribute].sharing_profile_id IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=INTEGER}
+            </foreach>
+            AND user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
 
     </select>
 
@@ -123,4 +161,25 @@
         WHERE sharing_profile_id = #{object.objectID,jdbcType=INTEGER}
     </update>
 
-</mapper>
+    <!-- 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>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/2d685766/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
index 24db013..e9c5b02 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
@@ -25,6 +25,8 @@
 
     <!-- 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="username"            property="identifier"         jdbcType="VARCHAR"/>
         <result column="password_hash"       property="passwordHash"       jdbcType="BINARY"/>
@@ -42,6 +44,15 @@
         <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 -->
@@ -61,7 +72,8 @@
     </select>
 
     <!-- Select multiple users by username -->
-    <select id="select" resultMap="UserResultMap">
+    <select id="select" resultMap="UserResultMap"
+            resultSets="users,arbitraryAttributes">
 
         SELECT
             [guacamole_user].user_id,
@@ -92,10 +104,23 @@
                 #{identifier,jdbcType=VARCHAR}
             </foreach>;
 
+        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
+        WHERE username IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=INTEGER}
+            </foreach>;
+
     </select>
 
     <!-- Select multiple users by username only if readable -->
-    <select id="selectReadable" resultMap="UserResultMap">
+    <select id="selectReadable" resultMap="UserResultMap"
+            resultSets="users,arbitraryAttributes">
 
         SELECT
             [guacamole_user].user_id,
@@ -127,12 +152,28 @@
                 #{identifier,jdbcType=VARCHAR}
             </foreach>
             AND [guacamole_user_permission].user_id = #{user.objectID,jdbcType=INTEGER}
-            AND permission = 'READ'
+            AND permission = 'READ';
+
+        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_user_permission] ON affected_user_id = [guacamole_user].user_id
+        WHERE username IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=INTEGER}
+            </foreach>
+            AND [guacamole_user_permission].user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
 
     </select>
 
     <!-- Select single user by username -->
-    <select id="selectOne" resultMap="UserResultMap">
+    <select id="selectOne" resultMap="UserResultMap"
+            resultSets="users,arbitraryAttributes">
 
         SELECT
             [guacamole_user].user_id,
@@ -159,7 +200,15 @@
         FROM [guacamole_user]
         LEFT JOIN [guacamole_user_history] ON [guacamole_user_history].user_id = [guacamole_user].user_id
         WHERE
-            [guacamole_user].username = #{username,jdbcType=VARCHAR}
+            [guacamole_user].username = #{username,jdbcType=VARCHAR};
+
+        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
+        WHERE username = #{username,jdbcType=VARCHAR};
 
     </select>
 
@@ -230,4 +279,25 @@
         WHERE user_id = #{object.objectID,jdbcType=VARCHAR}
     </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>


[10/10] guacamole-client git commit: GUACAMOLE-96: Merge allow extensions to voluntarily store each other's data.

Posted by vn...@apache.org.
GUACAMOLE-96: Merge allow extensions to voluntarily store each other's data.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/07d03078
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/07d03078
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/07d03078

Branch: refs/heads/master
Commit: 07d03078559f689c71af6b44bb6de6bdf4a13932
Parents: a050c16 d5768ea
Author: Nick Couchman <vn...@apache.org>
Authored: Thu Feb 1 13:31:46 2018 -0500
Committer: Nick Couchman <vn...@apache.org>
Committed: Thu Feb 1 13:31:46 2018 -0500

----------------------------------------------------------------------
 .../auth/jdbc/base/ArbitraryAttributeMap.java   | 162 +++++++++++++++++++
 .../auth/jdbc/base/ArbitraryAttributeModel.java | 104 ++++++++++++
 .../auth/jdbc/base/ModeledDirectoryObject.java  |  54 ++++++-
 .../jdbc/base/ModeledDirectoryObjectMapper.java |  25 ++-
 .../base/ModeledDirectoryObjectService.java     |  12 ++
 .../guacamole/auth/jdbc/base/ObjectModel.java   |  66 +++++++-
 .../auth/jdbc/connection/ModeledConnection.java |  28 +++-
 .../connectiongroup/ModeledConnectionGroup.java |  24 ++-
 .../sharingprofile/ModeledSharingProfile.java   |  10 --
 .../guacamole/auth/jdbc/user/ModeledUser.java   |  33 +++-
 .../schema/001-create-schema.sql                |  88 ++++++++++
 .../schema/upgrade/upgrade-pre-1.0.0.sql        | 106 ++++++++++++
 .../auth/jdbc/connection/ConnectionMapper.xml   |  58 ++++++-
 .../connectiongroup/ConnectionGroupMapper.xml   |  58 ++++++-
 .../sharingprofile/SharingProfileMapper.xml     |  67 +++++++-
 .../guacamole/auth/jdbc/user/UserMapper.xml     |  84 +++++++++-
 .../schema/001-create-schema.sql                |  96 +++++++++++
 .../schema/upgrade/upgrade-pre-1.0.0.sql        | 114 +++++++++++++
 .../auth/jdbc/connection/ConnectionMapper.xml   |  58 ++++++-
 .../connectiongroup/ConnectionGroupMapper.xml   |  58 ++++++-
 .../sharingprofile/SharingProfileMapper.xml     |  67 +++++++-
 .../guacamole/auth/jdbc/user/UserMapper.xml     |  82 +++++++++-
 .../schema/001-create-schema.sql                | 110 +++++++++++++
 .../schema/upgrade/upgrade-pre-1.0.0.sql        | 127 +++++++++++++++
 .../auth/jdbc/connection/ConnectionMapper.xml   |  58 ++++++-
 .../connectiongroup/ConnectionGroupMapper.xml   |  58 ++++++-
 .../sharingprofile/SharingProfileMapper.xml     |  69 +++++++-
 .../guacamole/auth/jdbc/user/UserMapper.xml     |  80 ++++++++-
 .../apache/guacamole/net/auth/Attributes.java   |  59 +++++++
 .../apache/guacamole/net/auth/Connection.java   |  24 +--
 .../guacamole/net/auth/ConnectionGroup.java     |  24 +--
 .../guacamole/net/auth/SharingProfile.java      |  23 +--
 .../org/apache/guacamole/net/auth/User.java     |  24 +--
 .../ActiveConnectionObjectTranslator.java       |   9 +-
 .../ActiveConnectionResource.java               |   2 +-
 .../connection/ConnectionObjectTranslator.java  |  13 +-
 .../rest/connection/ConnectionResource.java     |   2 +-
 .../ConnectionGroupObjectTranslator.java        |  14 +-
 .../ConnectionGroupResource.java                |   2 +-
 .../rest/directory/DirectoryObjectResource.java |  17 +-
 .../directory/DirectoryObjectTranslator.java    |  76 ++++++++-
 .../rest/directory/DirectoryResource.java       |   3 +
 .../SharingProfileObjectTranslator.java         |  14 +-
 .../sharingprofile/SharingProfileResource.java  |   2 +-
 .../rest/user/UserObjectTranslator.java         |  13 +-
 .../guacamole/rest/user/UserResource.java       |   2 +-
 46 files changed, 2110 insertions(+), 169 deletions(-)
----------------------------------------------------------------------



[05/10] guacamole-client git commit: GUACAMOLE-96: Document semantics of voluntary attribute storage and guaranteed sanitization.

Posted by vn...@apache.org.
GUACAMOLE-96: Document semantics of voluntary attribute storage and guaranteed sanitization.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/79936c4c
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/79936c4c
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/79936c4c

Branch: refs/heads/master
Commit: 79936c4c419e602a824376a933661590e593a9c9
Parents: 7725565
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Oct 29 13:09:45 2017 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Jan 31 15:26:16 2018 -0800

----------------------------------------------------------------------
 .../java/org/apache/guacamole/net/auth/Connection.java | 13 +++++++++++--
 .../org/apache/guacamole/net/auth/ConnectionGroup.java | 13 +++++++++++--
 .../org/apache/guacamole/net/auth/SharingProfile.java  | 11 ++++++++++-
 .../main/java/org/apache/guacamole/net/auth/User.java  | 13 +++++++++++--
 4 files changed, 43 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/79936c4c/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java
index 85fd168..313d89e 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java
@@ -95,8 +95,17 @@ public interface Connection extends Identifiable, Connectable {
 
     /**
      * Sets the given attributes. If an attribute within the map is not
-     * supported, it will simply be dropped. Any attributes not within the
-     * given map will be left untouched.
+     * supported, it will simply be dropped. Any attributes not within the given
+     * map will be left untouched. Attributes which are not declared within
+     * getConnectionAttributes() of the associated UserContext MUST NOT be
+     * submitted, but other extensions may manipulate the declared attributes
+     * through decorate() and redecorate().
+     *
+     * Implementations may optionally allow storage of unsupported attributes.
+     * Extensions which rely on other extensions to store their attribute
+     * values should verify that such storage is supported by first testing
+     * that the attribute value is retrievable via getAttributes() after being
+     * set.
      *
      * @param attributes
      *     A map of all attribute identifiers to their corresponding values.

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/79936c4c/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/ConnectionGroup.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/ConnectionGroup.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/ConnectionGroup.java
index 8e34e41..04b494a 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/ConnectionGroup.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/ConnectionGroup.java
@@ -137,8 +137,17 @@ public interface ConnectionGroup extends Identifiable, Connectable {
 
     /**
      * Sets the given attributes. If an attribute within the map is not
-     * supported, it will simply be dropped. Any attributes not within the
-     * given map will be left untouched.
+     * supported, it will simply be dropped. Any attributes not within the given
+     * map will be left untouched. Attributes which are not declared within
+     * getConnectionGroupAttributes() of the associated UserContext MUST NOT be
+     * submitted, but other extensions may manipulate the declared attributes
+     * through decorate() and redecorate().
+     *
+     * Implementations may optionally allow storage of unsupported attributes.
+     * Extensions which rely on other extensions to store their attribute
+     * values should verify that such storage is supported by first testing
+     * that the attribute value is retrievable via getAttributes() after being
+     * set.
      *
      * @param attributes
      *     A map of all attribute identifiers to their corresponding values.

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/79936c4c/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/SharingProfile.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/SharingProfile.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/SharingProfile.java
index f9ec34c..3b4ec65 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/SharingProfile.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/SharingProfile.java
@@ -107,7 +107,16 @@ public interface SharingProfile extends Identifiable {
     /**
      * Sets the given attributes. If an attribute within the map is not
      * supported, it will simply be dropped. Any attributes not within the
-     * given map will be left untouched.
+     * given map will be left untouched. Attributes which are not declared
+     * within getSharingProfileAttributes() of the associated UserContext MUST
+     * NOT be submitted, but other extensions may manipulate the declared
+     * attributes through decorate() and redecorate().
+     *
+     * Implementations may optionally allow storage of unsupported attributes.
+     * Extensions which rely on other extensions to store their attribute
+     * values should verify that such storage is supported by first testing
+     * that the attribute value is retrievable via getAttributes() after being
+     * set.
      *
      * @param attributes
      *     A map of all attribute identifiers to their corresponding values.

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/79936c4c/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java
index f7bd61c..49e1f99 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java
@@ -94,8 +94,17 @@ public interface User extends Identifiable {
 
     /**
      * Sets the given attributes. If an attribute within the map is not
-     * supported, it will simply be dropped. Any attributes not within the
-     * given map will be left untouched.
+     * supported, it will simply be dropped. Any attributes not within the given
+     * map will be left untouched. Attributes which are not declared within
+     * getUserAttributes() of the associated UserContext MUST NOT be submitted,
+     * but other extensions may manipulate the declared attributes through
+     * decorate() and redecorate().
+     * 
+     * Implementations may optionally allow storage of unsupported attributes.
+     * Extensions which rely on other extensions to store their attribute
+     * values should verify that such storage is supported by first testing
+     * that the attribute value is retrievable via getAttributes() after being
+     * set.
      *
      * @param attributes
      *     A map of all attribute identifiers to their corresponding values.


[06/10] guacamole-client git commit: GUACAMOLE-96: Add base support within JDBC auth for storage of arbitrary attributes from other extensions.

Posted by vn...@apache.org.
GUACAMOLE-96: Add base support within JDBC auth for storage of arbitrary attributes from other extensions.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/b6de402c
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/b6de402c
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/b6de402c

Branch: refs/heads/master
Commit: b6de402c0c1fbcaa2d6e95ebbc99baef9165bbe9
Parents: a3cee15
Author: Michael Jumper <mj...@apache.org>
Authored: Wed Nov 22 12:29:58 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Jan 31 15:26:16 2018 -0800

----------------------------------------------------------------------
 .../auth/jdbc/base/ArbitraryAttributeMap.java   | 162 +++++++++++++++++++
 .../auth/jdbc/base/ArbitraryAttributeModel.java | 104 ++++++++++++
 .../auth/jdbc/base/ModeledDirectoryObject.java  |  33 ++--
 .../jdbc/base/ModeledDirectoryObjectMapper.java |  25 ++-
 .../base/ModeledDirectoryObjectService.java     |  12 ++
 .../guacamole/auth/jdbc/base/ObjectModel.java   |  49 ++++--
 6 files changed, 354 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/b6de402c/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ArbitraryAttributeMap.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ArbitraryAttributeMap.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ArbitraryAttributeMap.java
new file mode 100644
index 0000000..e2cb438
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ArbitraryAttributeMap.java
@@ -0,0 +1,162 @@
+/*
+ * 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.jdbc.base;
+
+import java.util.AbstractCollection;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * Map of arbitrary attribute name/value pairs which can alternatively be
+ * exposed as a collection of model objects.
+ */
+public class ArbitraryAttributeMap extends HashMap<String, String> {
+
+    /**
+     * Creates a new ArbitraryAttributeMap containing the name/value pairs
+     * within the given collection of model objects.
+     *
+     * @param models
+     *     The model objects of all attributes which should be stored in the
+     *     new map as name/value pairs.
+     *
+     * @return
+     *     A new ArbitraryAttributeMap containing the name/value pairs within
+     *     the given collection of model objects.
+     */
+    public static ArbitraryAttributeMap fromModelCollection(Collection<ArbitraryAttributeModel> models) {
+
+        // Add all name/value pairs from the given collection to the map
+        ArbitraryAttributeMap map = new ArbitraryAttributeMap();
+        for (ArbitraryAttributeModel model : models)
+            map.put(model.getName(), model.getValue());
+
+        return map;
+
+    }
+
+    /**
+     * Returns a collection of model objects which mirrors the contents of this
+     * ArbitraryAttributeMap. Each name/value pair within the map is reflected
+     * by a corresponding model object within the returned collection. Removing
+     * a model object from the collection removes the corresponding name/value
+     * pair from the map. Adding a new model object to the collection adds a
+     * corresponding name/value pair to the map. Changes to a model object
+     * within the collection are NOT reflected on the map, however.
+     *
+     * @return
+     *     A collection of model objects which mirrors the contents of this
+     *     ArbitraryAttributeMap.
+     */
+    public Collection<ArbitraryAttributeModel> toModelCollection() {
+        return new AbstractCollection<ArbitraryAttributeModel>() {
+
+            @Override
+            public void clear() {
+                ArbitraryAttributeMap.this.clear();
+            }
+
+            @Override
+            public boolean remove(Object o) {
+
+                // The Collection view of an ArbitraryAttributeMap can contain
+                // only ArbitraryAttributeModel objects
+                if (!(o instanceof ArbitraryAttributeModel))
+                    return false;
+
+                // The attribute should be removed only if the value matches
+                ArbitraryAttributeModel model = (ArbitraryAttributeModel) o;
+                return ArbitraryAttributeMap.this.remove(model.getName(),
+                        model.getValue());
+
+            }
+
+            @Override
+            public boolean add(ArbitraryAttributeModel e) {
+
+                String newValue = e.getValue();
+                String oldValue = put(e.getName(), newValue);
+
+                // If null value is being added, collection changed only if
+                // old value was non-null
+                if (newValue == null)
+                    return oldValue != null;
+
+                // Collection changed if value changed
+                return !newValue.equals(oldValue);
+
+            }
+
+            @Override
+            public boolean contains(Object o) {
+
+                // The Collection view of an ArbitraryAttributeMap can contain
+                // only ArbitraryAttributeModel objects
+                if (!(o instanceof ArbitraryAttributeModel))
+                    return false;
+
+                // No need to check the value of the attribute if the attribute
+                // is not even present
+                ArbitraryAttributeModel model = (ArbitraryAttributeModel) o;
+                String value = get(model.getName());
+                if (value == null)
+                    return false;
+
+                // The name/value pair is present only if the value matches
+                return value.equals(model.getValue());
+
+            }
+
+            @Override
+            public Iterator<ArbitraryAttributeModel> iterator() {
+
+                // Get iterator over all string name/value entries
+                final Iterator<Entry<String, String>> iterator = entrySet().iterator();
+
+                // Dynamically translate each string name/value entry into a
+                // corresponding attribute model object as iteration continues
+                return new Iterator<ArbitraryAttributeModel>() {
+
+                    @Override
+                    public boolean hasNext() {
+                        return iterator.hasNext();
+                    }
+
+                    @Override
+                    public ArbitraryAttributeModel next() {
+                        Entry<String, String> entry = iterator.next();
+                        return new ArbitraryAttributeModel(entry.getKey(),
+                                entry.getValue());
+                    }
+
+                };
+
+            }
+
+            @Override
+            public int size() {
+                return ArbitraryAttributeMap.this.size();
+            }
+
+        };
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/b6de402c/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ArbitraryAttributeModel.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ArbitraryAttributeModel.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ArbitraryAttributeModel.java
new file mode 100644
index 0000000..b064b54
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ArbitraryAttributeModel.java
@@ -0,0 +1,104 @@
+/*
+ * 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.jdbc.base;
+
+/**
+ * A single attribute name/value pair belonging to a object which implements
+ * the Attributes interface, such as a Connection or User. Attributes stored
+ * as raw name/value pairs are the attributes which are given to the database
+ * authentication extension for storage by other extensions. Attributes which
+ * are directly supported by the database authentication extension have defined
+ * columns and properties with proper types, constraints, etc.
+ */
+public class ArbitraryAttributeModel {
+
+    /**
+     * The name of the attribute.
+     */
+    private String name;
+
+    /**
+     * The value the attribute is set to.
+     */
+    private String value;
+
+    /**
+     * Creates a new ArbitraryAttributeModel with its name and value both set
+     * to null.
+     */
+    public ArbitraryAttributeModel() {
+    }
+
+    /**
+     * Creates a new ArbitraryAttributeModel with its name and value
+     * initialized to the given values.
+     *
+     * @param name
+     *     The name of the attribute.
+     *
+     * @param value
+     *     The value the attribute is set to.
+     */
+    public ArbitraryAttributeModel(String name, String value) {
+        this.name = name;
+        this.value = value;
+    }
+
+    /**
+     * Returns the name of this attribute.
+     *
+     * @return
+     *     The name of this attribute.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the name of this attribute.
+     *
+     * @param name
+     *     The name of this attribute.
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Returns the value of this attribute.
+     *
+     * @return
+     *     The value of this attribute.
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * Sets the value of this attribute.
+     *
+     * @param value
+     *     The value of this attribute.
+     */
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/b6de402c/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObject.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObject.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObject.java
index e13445b..ddeda92 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObject.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObject.java
@@ -65,35 +65,32 @@ public abstract class ModeledDirectoryObject<ModelType extends ObjectModel>
 
     @Override
     public Map<String, String> getAttributes() {
-
-        // If no arbitrary attributes are defined, just return an empty map
-        Map<String, String> arbitraryAttributes = getModel().getArbitraryAttributes();
-        if (arbitraryAttributes == null)
-            return new HashMap<String, String>();
-
-        // Otherwise include any defined arbitrary attributes
-        return new HashMap<String, String>(arbitraryAttributes);
-
+        return new HashMap<String, String>(getModel().getArbitraryAttributeMap());
     }
 
     @Override
     public void setAttributes(Map<String, String> attributes) {
 
+        ArbitraryAttributeMap arbitraryAttributes = getModel().getArbitraryAttributeMap();
+
         // Get set of all supported attribute names
         Set<String> supportedAttributes = getSupportedAttributeNames();
 
-        // Initialize model with empty map if no such map is already present
-        Map<String, String> arbitraryAttributes = getModel().getArbitraryAttributes();
-        if (arbitraryAttributes == null) {
-            arbitraryAttributes = new HashMap<String, String>();
-            getModel().setArbitraryAttributes(arbitraryAttributes);
-        }
-
         // Store remaining attributes only if not directly mapped to model
         for (Map.Entry<String, String> attribute : attributes.entrySet()) {
+
             String name = attribute.getKey();
-            if (!supportedAttributes.contains(name))
-                arbitraryAttributes.put(name, attribute.getValue());
+            String value = attribute.getValue();
+
+            // Handle null attributes as explicit removal of that attribute,
+            // as the underlying model cannot store null attribute values
+            if (!supportedAttributes.contains(name)) {
+                if (value == null)
+                    arbitraryAttributes.remove(name);
+                else
+                    arbitraryAttributes.put(name, value);
+            }
+
         }
 
     }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/b6de402c/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
index ebd95d9..4431e8f 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectMapper.java
@@ -132,5 +132,28 @@ public interface ModeledDirectoryObjectMapper<ModelType> {
      *     The number of rows updated.
      */
     int update(@Param("object") ModelType object);
-    
+
+    /**
+     * Deletes any arbitrary attributes currently associated with the given
+     * object in the database.
+     *
+     * @param object
+     *     The object whose arbitrary attributes should be deleted.
+     *
+     * @return
+     *     The number of rows deleted.
+     */
+    int deleteAttributes(@Param("object") ModelType object);
+
+    /**
+     * Inserts all arbitrary attributes associated with the given object.
+     *
+     * @param object
+     *     The object whose arbitrary attributes should be inserted.
+     *
+     * @return
+     *     The number of rows inserted.
+     */
+    int insertAttributes(@Param("object") ModelType object);
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/b6de402c/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
index 2c1402e..21508c4 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObjectService.java
@@ -32,6 +32,7 @@ import org.apache.guacamole.auth.jdbc.user.UserModel;
 import org.apache.guacamole.net.auth.Identifiable;
 import org.apache.guacamole.net.auth.permission.ObjectPermission;
 import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
+import org.mybatis.guice.transactional.Transactional;
 
 /**
  * Service which provides convenience methods for creating, retrieving, and
@@ -446,6 +447,7 @@ public abstract class ModeledDirectoryObjectService<InternalType extends Modeled
     }
 
     @Override
+    @Transactional
     public InternalType createObject(ModeledAuthenticatedUser user, ExternalType object)
         throws GuacamoleException {
 
@@ -461,6 +463,10 @@ public abstract class ModeledDirectoryObjectService<InternalType extends Modeled
         // Add implicit permissions
         getPermissionMapper().insert(getImplicitPermissions(user, model));
 
+        // Add any arbitrary attributes
+        if (model.hasArbitraryAttributes())
+            getObjectMapper().insertAttributes(model);
+
         return getObjectInstance(user, model);
 
     }
@@ -477,6 +483,7 @@ public abstract class ModeledDirectoryObjectService<InternalType extends Modeled
     }
 
     @Override
+    @Transactional
     public void updateObject(ModeledAuthenticatedUser user, InternalType object)
         throws GuacamoleException {
 
@@ -486,6 +493,11 @@ public abstract class ModeledDirectoryObjectService<InternalType extends Modeled
         // Update object
         getObjectMapper().update(model);
 
+        // Replace any existing arbitrary attributes
+        getObjectMapper().deleteAttributes(model);
+        if (model.hasArbitraryAttributes())
+            getObjectMapper().insertAttributes(model);
+
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/b6de402c/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectModel.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectModel.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectModel.java
index 3841f6f..c3052b1 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectModel.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectModel.java
@@ -19,7 +19,7 @@
 
 package org.apache.guacamole.auth.jdbc.base;
 
-import java.util.Map;
+import java.util.Collection;
 
 /**
  * Object representation of a Guacamole object, such as a user or connection,
@@ -41,7 +41,8 @@ public abstract class ObjectModel {
      * Map of all arbitrary attributes associated with this object but not
      * directly mapped to a particular column.
      */
-    private Map<String, String> arbitraryAttributes;
+    private ArbitraryAttributeMap arbitraryAttributes =
+            new ArbitraryAttributeMap();
 
     /**
      * Creates a new, empty object.
@@ -102,23 +103,47 @@ public abstract class ObjectModel {
      *     with this model which do not otherwise have explicit mappings to
      *     properties.
      */
-    public Map<String, String> getArbitraryAttributes() {
+    public ArbitraryAttributeMap getArbitraryAttributeMap() {
         return arbitraryAttributes;
     }
 
     /**
-     * Sets all arbitrary attribute name/value pairs associated with this
-     * model. The provided map should contain only attributes which are not
-     * explicitly supported by the model, as any explicitly-supported
-     * attributes should instead be mapped to corresponding properties.
+     * Returns whether at least one arbitrary attribute name/value pair has
+     * been associated with this object.
+     *
+     * @return
+     *     true if this object has at least one arbitrary attribute set, false
+     *     otherwise.
+     */
+    public boolean hasArbitraryAttributes() {
+        return !arbitraryAttributes.isEmpty();
+    }
+
+    /**
+     * Returns a Collection view of the equivalent attribute model objects
+     * which make up the map of arbitrary attribute name/value pairs returned
+     * by getArbitraryAttributeMap(). Additions and removals on the returned
+     * Collection directly affect the attribute map.
+     *
+     * @return
+     *      A Collection view of the map returned by
+     *      getArbitraryAttributeMap().
+     */
+    public Collection<ArbitraryAttributeModel> getArbitraryAttributes() {
+        return arbitraryAttributes.toModelCollection();
+    }
+
+    /**
+     * Replaces all arbitrary attributes associated with this object with the
+     * attribute name/value pairs within the given collection of model objects.
      *
      * @param arbitraryAttributes
-     *     A map of attribute name/value pairs for all attributes associated
-     *     with this model which do not otherwise have explicit mappings to
-     *     properties.
+     *     The Collection of model objects containing the attribute name/value
+     *     pairs which should replace all currently-stored arbitrary attributes,
+     *     if any.
      */
-    public void setArbitraryAttributes(Map<String, String> arbitraryAttributes) {
-        this.arbitraryAttributes = arbitraryAttributes;
+    public void setArbitraryAttributes(Collection<ArbitraryAttributeModel> arbitraryAttributes) {
+        this.arbitraryAttributes = ArbitraryAttributeMap.fromModelCollection(arbitraryAttributes);
     }
 
 }


[09/10] guacamole-client git commit: GUACAMOLE-96: Map base JDBC support for arbitrary attributes to PostgreSQL tables.

Posted by vn...@apache.org.
GUACAMOLE-96: Map base JDBC support for arbitrary attributes to PostgreSQL tables.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/49473356
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/49473356
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/49473356

Branch: refs/heads/master
Commit: 494733569f3b39ff0f73df42a5068b4c6bdade94
Parents: b6de402
Author: Michael Jumper <mj...@apache.org>
Authored: Wed Nov 22 16:47:56 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Jan 31 15:26:16 2018 -0800

----------------------------------------------------------------------
 .../schema/001-create-schema.sql                |  96 ++++++++++++++++
 .../schema/upgrade/upgrade-pre-0.9.15.sql       | 114 +++++++++++++++++++
 .../auth/jdbc/connection/ConnectionMapper.xml   |  58 +++++++++-
 .../connectiongroup/ConnectionGroupMapper.xml   |  58 +++++++++-
 .../sharingprofile/SharingProfileMapper.xml     |  67 ++++++++++-
 .../guacamole/auth/jdbc/user/UserMapper.xml     |  82 ++++++++++++-
 6 files changed, 461 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/49473356/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql
index 97780a5..ddd3566 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/001-create-schema.sql
@@ -252,6 +252,102 @@ 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 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
 -- specific access to a connection.
 --

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/49473356/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.15.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.15.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.15.sql
new file mode 100644
index 0000000..db115c2
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.15.sql
@@ -0,0 +1,114 @@
+--
+-- 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.
+--
+
+--
+-- 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 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);

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/49473356/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
index dc8fdd4..0b109f6 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
@@ -47,6 +47,14 @@
             <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 -->
@@ -87,7 +95,7 @@
 
     <!-- Select multiple connections by identifier -->
     <select id="select" resultMap="ConnectionResultMap"
-            resultSets="connections,sharingProfiles">
+            resultSets="connections,sharingProfiles,arbitraryAttributes">
 
         SELECT
             guacamole_connection.connection_id,
@@ -119,11 +127,22 @@
                 #{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">
+            resultSets="connections,sharingProfiles,arbitraryAttributes">
 
         SELECT
             guacamole_connection.connection_id,
@@ -161,6 +180,20 @@
             AND user_id = #{user.objectID,jdbcType=INTEGER}
             AND permission = 'READ';
 
+        SELECT
+            guacamole_connection_attribute.connection_id,
+            attribute_name,
+            attribute_value
+        FROM guacamole_connection_attribute
+        JOIN guacamole_connection_permission ON guacamole_connection_permission.connection_id = guacamole_connection_attribute.connection_id
+        WHERE guacamole_connection_attribute.connection_id IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=INTEGER}::integer
+            </foreach>
+            AND user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
+
     </select>
 
     <!-- Select single connection by name -->
@@ -242,4 +275,25 @@
         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>

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/49473356/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
index 0a41b3d..7cc4ac7 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
@@ -48,6 +48,14 @@
             <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 -->
@@ -88,7 +96,7 @@
 
     <!-- Select multiple connection groups by identifier -->
     <select id="select" resultMap="ConnectionGroupResultMap"
-            resultSets="connectionGroups,childConnectionGroups,childConnections">
+            resultSets="connectionGroups,childConnectionGroups,childConnections,arbitraryAttributes">
 
         SELECT
             connection_group_id,
@@ -121,11 +129,22 @@
                 #{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">
+            resultSets="connectionGroups,childConnectionGroups,childConnections,arbitraryAttributes">
 
         SELECT
             guacamole_connection_group.connection_group_id,
@@ -167,6 +186,20 @@
             AND user_id = #{user.objectID,jdbcType=INTEGER}
             AND permission = 'READ';
 
+        SELECT
+            guacamole_connection_group_attribute.connection_group_id,
+            attribute_name,
+            attribute_value
+        FROM guacamole_connection_group_attribute
+        JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group_attribute.connection_group_id
+        WHERE guacamole_connection_group_attribute.connection_group_id IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=INTEGER}::integer
+            </foreach>
+            AND user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
+
     </select>
 
     <!-- Select single connection group by name -->
@@ -229,4 +262,25 @@
         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>

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/49473356/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
index 0af4937..801d6e3 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
@@ -25,9 +25,20 @@
 
     <!-- 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 -->
@@ -46,7 +57,8 @@
     </select>
 
     <!-- Select multiple sharing profiles by identifier -->
-    <select id="select" resultMap="SharingProfileResultMap">
+    <select id="select" resultMap="SharingProfileResultMap"
+            resultSets="sharingProfiles,arbitraryAttributes">
 
         SELECT
             sharing_profile_id,
@@ -57,12 +69,24 @@
             <foreach collection="identifiers" item="identifier"
                      open="(" separator="," close=")">
                 #{identifier,jdbcType=INTEGER}::integer
-            </foreach>
+            </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">
+    <select id="selectReadable" resultMap="SharingProfileResultMap"
+            resultSets="sharingProfiles,arbitraryAttributes">
 
         SELECT
             guacamole_sharing_profile.sharing_profile_id,
@@ -76,7 +100,21 @@
                 #{identifier,jdbcType=INTEGER}::integer
             </foreach>
             AND user_id = #{user.objectID,jdbcType=INTEGER}
-            AND permission = 'READ'
+            AND permission = 'READ';
+
+        SELECT
+            guacamole_sharing_profile_attribute.sharing_profile_id,
+            attribute_name,
+            attribute_value
+        FROM guacamole_sharing_profile_attribute
+        JOIN guacamole_sharing_profile_permission ON guacamole_sharing_profile_permission.sharing_profile_id = guacamole_sharing_profile_attribute.sharing_profile_id
+        WHERE guacamole_sharing_profile_attribute.sharing_profile_id IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=INTEGER}::integer
+            </foreach>
+            AND user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
 
     </select>
 
@@ -123,4 +161,25 @@
         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>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/49473356/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
index c106a8f..e183fe2 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
@@ -25,6 +25,8 @@
 
     <!-- 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="username"            property="identifier"         jdbcType="VARCHAR"/>
         <result column="password_hash"       property="passwordHash"       jdbcType="BINARY"/>
@@ -42,6 +44,15 @@
         <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 -->
@@ -61,7 +72,8 @@
     </select>
 
     <!-- Select multiple users by username -->
-    <select id="select" resultMap="UserResultMap">
+    <select id="select" resultMap="UserResultMap"
+            resultSets="users,arbitraryAttributes">
 
         SELECT
             guacamole_user.user_id,
@@ -88,12 +100,25 @@
                      open="(" separator="," close=")">
                 #{identifier,jdbcType=VARCHAR}
             </foreach>
-        GROUP BY guacamole_user.user_id
+        GROUP BY guacamole_user.user_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
+        WHERE username IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=VARCHAR}
+            </foreach>;
 
     </select>
 
     <!-- Select multiple users by username only if readable -->
-    <select id="selectReadable" resultMap="UserResultMap">
+    <select id="selectReadable" resultMap="UserResultMap"
+            resultSets="users,arbitraryAttributes">
 
         SELECT
             guacamole_user.user_id,
@@ -123,12 +148,28 @@
             </foreach>
             AND guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
             AND permission = 'READ'
-        GROUP BY guacamole_user.user_id
+        GROUP BY guacamole_user.user_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_user_permission ON affected_user_id = guacamole_user.user_id
+        WHERE username IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=VARCHAR}
+            </foreach>
+            AND guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
 
     </select>
 
     <!-- Select single user by username -->
-    <select id="selectOne" resultMap="UserResultMap">
+    <select id="selectOne" resultMap="UserResultMap"
+            resultSets="users,arbitraryAttributes">
 
         SELECT
             guacamole_user.user_id,
@@ -152,7 +193,15 @@
         LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
         WHERE
             guacamole_user.username = #{username,jdbcType=VARCHAR}
-        GROUP BY guacamole_user.user_id
+        GROUP BY guacamole_user.user_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
+        WHERE username = #{username,jdbcType=VARCHAR};
 
     </select>
 
@@ -223,4 +272,25 @@
         WHERE user_id = #{object.objectID,jdbcType=VARCHAR}
     </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>


[08/10] guacamole-client git commit: GUACAMOLE-96: Extract Attributes interface from objects which provide getAttributes() / setAttributes().

Posted by vn...@apache.org.
GUACAMOLE-96: Extract Attributes interface from objects which provide getAttributes() / setAttributes().


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/fff14117
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/fff14117
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/fff14117

Branch: refs/heads/master
Commit: fff14117681d333c6b93fa274235df7c3ddb25ee
Parents: 79936c4
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Oct 29 15:33:10 2017 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Jan 31 15:26:16 2018 -0800

----------------------------------------------------------------------
 .../apache/guacamole/net/auth/Attributes.java   | 59 ++++++++++++++++++++
 .../apache/guacamole/net/auth/Connection.java   | 33 +----------
 .../guacamole/net/auth/ConnectionGroup.java     | 33 +----------
 .../guacamole/net/auth/SharingProfile.java      | 32 +----------
 .../org/apache/guacamole/net/auth/User.java     | 33 +----------
 5 files changed, 63 insertions(+), 127 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/fff14117/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Attributes.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Attributes.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Attributes.java
new file mode 100644
index 0000000..050017d
--- /dev/null
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Attributes.java
@@ -0,0 +1,59 @@
+/*
+ * 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.net.auth;
+
+import java.util.Map;
+
+/**
+ * An object which is associated with a set of arbitrary attributes, defined
+ * as name/value pairs.
+ */
+public interface Attributes {
+
+    /**
+     * Returns all attributes associated with this object. The returned map
+     * may not be modifiable.
+     *
+     * @return
+     *     A map of all attribute identifiers to their corresponding values,
+     *     for all attributes associated with this object, which may not be
+     *     modifiable.
+     */
+    Map<String, String> getAttributes();
+
+    /**
+     * Sets the given attributes. If an attribute within the map is not
+     * supported, it will simply be dropped. Any attributes not within the given
+     * map will be left untouched. Attributes which are not declared within the
+     * associated UserContext MUST NOT be submitted, but other extensions may
+     * manipulate the declared attributes through decorate() and redecorate().
+     *
+     * Implementations may optionally allow storage of unsupported attributes.
+     * Extensions which rely on other extensions to store their attribute
+     * values should verify that such storage is supported by first testing
+     * that the attribute value is retrievable via getAttributes() after being
+     * set.
+     *
+     * @param attributes
+     *     A map of all attribute identifiers to their corresponding values.
+     */
+    void setAttributes(Map<String, String> attributes);
+
+}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/fff14117/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java
index 313d89e..5b1d13d 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java
@@ -21,7 +21,6 @@ package org.apache.guacamole.net.auth;
 
 import java.util.Date;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.protocol.GuacamoleConfiguration;
@@ -32,7 +31,7 @@ import org.apache.guacamole.protocol.GuacamoleConfiguration;
  * backing GuacamoleConfiguration may be intentionally obfuscated or tokenized
  * to protect sensitive configuration information.
  */
-public interface Connection extends Identifiable, Connectable {
+public interface Connection extends Identifiable, Connectable, Attributes {
 
     /**
      * Returns the name assigned to this Connection.
@@ -83,36 +82,6 @@ public interface Connection extends Identifiable, Connectable {
     public void setConfiguration(GuacamoleConfiguration config);
 
     /**
-     * Returns all attributes associated with this connection. The returned map
-     * may not be modifiable.
-     *
-     * @return
-     *     A map of all attribute identifiers to their corresponding values,
-     *     for all attributes associated with this connection, which may not be
-     *     modifiable.
-     */
-    Map<String, String> getAttributes();
-
-    /**
-     * Sets the given attributes. If an attribute within the map is not
-     * supported, it will simply be dropped. Any attributes not within the given
-     * map will be left untouched. Attributes which are not declared within
-     * getConnectionAttributes() of the associated UserContext MUST NOT be
-     * submitted, but other extensions may manipulate the declared attributes
-     * through decorate() and redecorate().
-     *
-     * Implementations may optionally allow storage of unsupported attributes.
-     * Extensions which rely on other extensions to store their attribute
-     * values should verify that such storage is supported by first testing
-     * that the attribute value is retrievable via getAttributes() after being
-     * set.
-     *
-     * @param attributes
-     *     A map of all attribute identifiers to their corresponding values.
-     */
-    void setAttributes(Map<String, String> attributes);
-
-    /**
      * Returns the date and time that this connection was last used. If the
      * connection was never used, the time that the connection was last used is
      * unknown, or this information is not visible to the current user, this

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/fff14117/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/ConnectionGroup.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/ConnectionGroup.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/ConnectionGroup.java
index 04b494a..74412de 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/ConnectionGroup.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/ConnectionGroup.java
@@ -19,7 +19,6 @@
 
 package org.apache.guacamole.net.auth;
 
-import java.util.Map;
 import java.util.Set;
 import org.apache.guacamole.GuacamoleException;
 
@@ -27,7 +26,7 @@ import org.apache.guacamole.GuacamoleException;
  * Represents a connection group, which can contain both other connection groups
  * as well as connections.
  */
-public interface ConnectionGroup extends Identifiable, Connectable {
+public interface ConnectionGroup extends Identifiable, Connectable, Attributes {
   
     /**
      * All legal types of connection group.
@@ -124,34 +123,4 @@ public interface ConnectionGroup extends Identifiable, Connectable {
     public Set<String> getConnectionGroupIdentifiers()
             throws GuacamoleException;
 
-    /**
-     * Returns all attributes associated with this connection group. The
-     * returned map may not be modifiable.
-     *
-     * @return
-     *     A map of all attribute identifiers to their corresponding values,
-     *     for all attributes associated with this connection group, which may
-     *     not be modifiable.
-     */
-    Map<String, String> getAttributes();
-
-    /**
-     * Sets the given attributes. If an attribute within the map is not
-     * supported, it will simply be dropped. Any attributes not within the given
-     * map will be left untouched. Attributes which are not declared within
-     * getConnectionGroupAttributes() of the associated UserContext MUST NOT be
-     * submitted, but other extensions may manipulate the declared attributes
-     * through decorate() and redecorate().
-     *
-     * Implementations may optionally allow storage of unsupported attributes.
-     * Extensions which rely on other extensions to store their attribute
-     * values should verify that such storage is supported by first testing
-     * that the attribute value is retrievable via getAttributes() after being
-     * set.
-     *
-     * @param attributes
-     *     A map of all attribute identifiers to their corresponding values.
-     */
-    void setAttributes(Map<String, String> attributes);
-
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/fff14117/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/SharingProfile.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/SharingProfile.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/SharingProfile.java
index 3b4ec65..2d4c432 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/SharingProfile.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/SharingProfile.java
@@ -25,7 +25,7 @@ import java.util.Map;
  * Represents the semantics which apply to an existing connection when shared,
  * along with a human-readable name and unique identifier.
  */
-public interface SharingProfile extends Identifiable {
+public interface SharingProfile extends Identifiable, Attributes {
 
     /**
      * Returns the human-readable name assigned to this SharingProfile.
@@ -93,34 +93,4 @@ public interface SharingProfile extends Identifiable {
      */
     public void setParameters(Map<String, String> parameters);
 
-    /**
-     * Returns all attributes associated with this sharing profile. The returned
-     * map may not be modifiable.
-     *
-     * @return
-     *     A map of all attribute identifiers to their corresponding values,
-     *     for all attributes associated with this sharing profile, which may
-     *     not be modifiable.
-     */
-    Map<String, String> getAttributes();
-
-    /**
-     * Sets the given attributes. If an attribute within the map is not
-     * supported, it will simply be dropped. Any attributes not within the
-     * given map will be left untouched. Attributes which are not declared
-     * within getSharingProfileAttributes() of the associated UserContext MUST
-     * NOT be submitted, but other extensions may manipulate the declared
-     * attributes through decorate() and redecorate().
-     *
-     * Implementations may optionally allow storage of unsupported attributes.
-     * Extensions which rely on other extensions to store their attribute
-     * values should verify that such storage is supported by first testing
-     * that the attribute value is retrievable via getAttributes() after being
-     * set.
-     *
-     * @param attributes
-     *     A map of all attribute identifiers to their corresponding values.
-     */
-    void setAttributes(Map<String, String> attributes);
-
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/fff14117/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java
----------------------------------------------------------------------
diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java
index 49e1f99..a39a772 100644
--- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java
+++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java
@@ -21,7 +21,6 @@ package org.apache.guacamole.net.auth;
 
 import java.util.Date;
 import java.util.List;
-import java.util.Map;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
 import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
@@ -30,7 +29,7 @@ import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
 /**
  * A user of the Guacamole web application.
  */
-public interface User extends Identifiable {
+public interface User extends Identifiable, Attributes {
 
     /**
      * All standard attribute names with semantics defined by the Guacamole web
@@ -82,36 +81,6 @@ public interface User extends Identifiable {
     public void setPassword(String password);
 
     /**
-     * Returns all attributes associated with this user. The returned map may
-     * not be modifiable.
-     *
-     * @return
-     *     A map of all attribute identifiers to their corresponding values,
-     *     for all attributes associated with this user, which may not be
-     *     modifiable.
-     */
-    Map<String, String> getAttributes();
-
-    /**
-     * Sets the given attributes. If an attribute within the map is not
-     * supported, it will simply be dropped. Any attributes not within the given
-     * map will be left untouched. Attributes which are not declared within
-     * getUserAttributes() of the associated UserContext MUST NOT be submitted,
-     * but other extensions may manipulate the declared attributes through
-     * decorate() and redecorate().
-     * 
-     * Implementations may optionally allow storage of unsupported attributes.
-     * Extensions which rely on other extensions to store their attribute
-     * values should verify that such storage is supported by first testing
-     * that the attribute value is retrievable via getAttributes() after being
-     * set.
-     *
-     * @param attributes
-     *     A map of all attribute identifiers to their corresponding values.
-     */
-    void setAttributes(Map<String, String> attributes);
-
-    /**
      * Returns the date and time that this user was last active. If the user
      * was never active, the time that the user was last active is unknown, or
      * this information is not visible to the current user, this may be null.


[03/10] guacamole-client git commit: GUACAMOLE-96: Add object- and model-level support for storage of arbitrary attributes.

Posted by vn...@apache.org.
GUACAMOLE-96: Add object- and model-level support for storage of arbitrary attributes.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/a3cee158
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/a3cee158
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/a3cee158

Branch: refs/heads/master
Commit: a3cee158cb771582dc9e7172cf8b3428204600ff
Parents: fff1411
Author: Michael Jumper <mj...@apache.org>
Authored: Sat Nov 18 16:42:13 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Jan 31 15:26:16 2018 -0800

----------------------------------------------------------------------
 .../auth/jdbc/base/ModeledDirectoryObject.java  | 57 +++++++++++++++++++-
 .../guacamole/auth/jdbc/base/ObjectModel.java   | 41 +++++++++++++-
 .../auth/jdbc/connection/ModeledConnection.java | 28 +++++++++-
 .../connectiongroup/ModeledConnectionGroup.java | 24 ++++++++-
 .../sharingprofile/ModeledSharingProfile.java   | 10 ----
 .../guacamole/auth/jdbc/user/ModeledUser.java   | 33 +++++++++++-
 6 files changed, 175 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a3cee158/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObject.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObject.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObject.java
index 0d15373..e13445b 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObject.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledDirectoryObject.java
@@ -19,6 +19,11 @@
 
 package org.apache.guacamole.auth.jdbc.base;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import org.apache.guacamole.net.auth.Attributes;
 import org.apache.guacamole.net.auth.Identifiable;
 
 /**
@@ -31,7 +36,7 @@ import org.apache.guacamole.net.auth.Identifiable;
  *     The type of model object that corresponds to this object.
  */
 public abstract class ModeledDirectoryObject<ModelType extends ObjectModel>
-    extends ModeledObject<ModelType> implements Identifiable {
+    extends ModeledObject<ModelType> implements Identifiable, Attributes {
 
     @Override
     public String getIdentifier() {
@@ -43,4 +48,54 @@ public abstract class ModeledDirectoryObject<ModelType extends ObjectModel>
         getModel().setIdentifier(identifier);
     }
 
+    /**
+     * Returns the names of all attributes explicitly supported by this object.
+     * Attributes named here have associated mappings within the backing model
+     * object, and thus should not be included in the arbitrary attribute
+     * storage. Any attributes set which do not match these names, such as those
+     * set via other extensions, will be added to arbitrary attribute storage.
+     *
+     * @return
+     *     A read-only Set of the names of all attributes explicitly supported
+     *     (mapped to a property of the backing model) by this object.
+     */
+    public Set<String> getSupportedAttributeNames() {
+        return Collections.<String>emptySet();
+    }
+
+    @Override
+    public Map<String, String> getAttributes() {
+
+        // If no arbitrary attributes are defined, just return an empty map
+        Map<String, String> arbitraryAttributes = getModel().getArbitraryAttributes();
+        if (arbitraryAttributes == null)
+            return new HashMap<String, String>();
+
+        // Otherwise include any defined arbitrary attributes
+        return new HashMap<String, String>(arbitraryAttributes);
+
+    }
+
+    @Override
+    public void setAttributes(Map<String, String> attributes) {
+
+        // Get set of all supported attribute names
+        Set<String> supportedAttributes = getSupportedAttributeNames();
+
+        // Initialize model with empty map if no such map is already present
+        Map<String, String> arbitraryAttributes = getModel().getArbitraryAttributes();
+        if (arbitraryAttributes == null) {
+            arbitraryAttributes = new HashMap<String, String>();
+            getModel().setArbitraryAttributes(arbitraryAttributes);
+        }
+
+        // Store remaining attributes only if not directly mapped to model
+        for (Map.Entry<String, String> attribute : attributes.entrySet()) {
+            String name = attribute.getKey();
+            if (!supportedAttributes.contains(name))
+                arbitraryAttributes.put(name, attribute.getValue());
+        }
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a3cee158/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectModel.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectModel.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectModel.java
index 833c0d9..3841f6f 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectModel.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ObjectModel.java
@@ -19,6 +19,8 @@
 
 package org.apache.guacamole.auth.jdbc.base;
 
+import java.util.Map;
+
 /**
  * Object representation of a Guacamole object, such as a user or connection,
  * as represented in the database.
@@ -34,7 +36,13 @@ public abstract class ObjectModel {
      * The unique identifier which identifies this object.
      */
     private String identifier;
-    
+
+    /**
+     * Map of all arbitrary attributes associated with this object but not
+     * directly mapped to a particular column.
+     */
+    private Map<String, String> arbitraryAttributes;
+
     /**
      * Creates a new, empty object.
      */
@@ -82,4 +90,35 @@ public abstract class ObjectModel {
         this.objectID = objectID;
     }
 
+    /**
+     * Returns a map of attribute name/value pairs for all attributes associated
+     * with this model which do not have explicit mappings to actual model
+     * properties. All other attributes (those which are explicitly supported
+     * by the model) should instead be mapped to properties with corresponding
+     * and properly-typed columns.
+     *
+     * @return
+     *     A map of attribute name/value pairs for all attributes associated
+     *     with this model which do not otherwise have explicit mappings to
+     *     properties.
+     */
+    public Map<String, String> getArbitraryAttributes() {
+        return arbitraryAttributes;
+    }
+
+    /**
+     * Sets all arbitrary attribute name/value pairs associated with this
+     * model. The provided map should contain only attributes which are not
+     * explicitly supported by the model, as any explicitly-supported
+     * attributes should instead be mapped to corresponding properties.
+     *
+     * @param arbitraryAttributes
+     *     A map of attribute name/value pairs for all attributes associated
+     *     with this model which do not otherwise have explicit mappings to
+     *     properties.
+     */
+    public void setArbitraryAttributes(Map<String, String> arbitraryAttributes) {
+        this.arbitraryAttributes = arbitraryAttributes;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a3cee158/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
index eb392bc..660212c 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java
@@ -25,7 +25,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -158,6 +158,21 @@ public class ModeledConnection extends ModeledChildDirectoryObject<ConnectionMod
     ));
 
     /**
+     * The names of all attributes which are explicitly supported by this
+     * extension's Connection objects.
+     */
+    public static final Set<String> ATTRIBUTE_NAMES =
+            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
+                GUACD_HOSTNAME_NAME,
+                GUACD_PORT_NAME,
+                GUACD_ENCRYPTION_NAME,
+                MAX_CONNECTIONS_NAME,
+                MAX_CONNECTIONS_PER_USER_NAME,
+                CONNECTION_WEIGHT,
+                FAILOVER_ONLY_NAME
+            )));
+
+    /**
      * The environment of the Guacamole server.
      */
     @Inject
@@ -254,9 +269,15 @@ public class ModeledConnection extends ModeledChildDirectoryObject<ConnectionMod
     }
 
     @Override
+    public Set<String> getSupportedAttributeNames() {
+        return ATTRIBUTE_NAMES;
+    }
+
+    @Override
     public Map<String, String> getAttributes() {
 
-        Map<String, String> attributes = new HashMap<String, String>();
+        // Include any defined arbitrary attributes
+        Map<String, String> attributes = super.getAttributes();
 
         // Set connection limit attribute
         attributes.put(MAX_CONNECTIONS_NAME, NumericField.format(getModel().getMaxConnections()));
@@ -305,6 +326,9 @@ public class ModeledConnection extends ModeledChildDirectoryObject<ConnectionMod
     @Override
     public void setAttributes(Map<String, String> attributes) {
 
+        // Set arbitrary attributes
+        super.setAttributes(attributes);
+
         // Translate connection limit attribute
         try { getModel().setMaxConnections(NumericField.parse(attributes.get(MAX_CONNECTIONS_NAME))); }
         catch (NumberFormatException e) {

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a3cee158/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ModeledConnectionGroup.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ModeledConnectionGroup.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ModeledConnectionGroup.java
index 7e65c7f..3aac52d 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ModeledConnectionGroup.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connectiongroup/ModeledConnectionGroup.java
@@ -23,7 +23,7 @@ import com.google.inject.Inject;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import org.apache.guacamole.GuacamoleException;
@@ -90,6 +90,17 @@ public class ModeledConnectionGroup extends ModeledChildDirectoryObject<Connecti
     ));
 
     /**
+     * The names of all attributes which are explicitly supported by this
+     * extension's ConnectionGroup objects.
+     */
+    public static final Set<String> ATTRIBUTE_NAMES =
+            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
+                MAX_CONNECTIONS_NAME,
+                MAX_CONNECTIONS_PER_USER_NAME,
+                ENABLE_SESSION_AFFINITY
+            )));
+
+    /**
      * The environment of the Guacamole server.
      */
     @Inject
@@ -157,9 +168,15 @@ public class ModeledConnectionGroup extends ModeledChildDirectoryObject<Connecti
     }
 
     @Override
+    public Set<String> getSupportedAttributeNames() {
+        return ATTRIBUTE_NAMES;
+    }
+
+    @Override
     public Map<String, String> getAttributes() {
 
-        Map<String, String> attributes = new HashMap<String, String>();
+        // Include any defined arbitrary attributes
+        Map<String, String> attributes = super.getAttributes();
 
         // Set connection limit attribute
         attributes.put(MAX_CONNECTIONS_NAME, NumericField.format(getModel().getMaxConnections()));
@@ -177,6 +194,9 @@ public class ModeledConnectionGroup extends ModeledChildDirectoryObject<Connecti
     @Override
     public void setAttributes(Map<String, String> attributes) {
 
+        // Set arbitrary attributes
+        super.setAttributes(attributes);
+
         // Translate connection limit attribute
         try { getModel().setMaxConnections(NumericField.parse(attributes.get(MAX_CONNECTIONS_NAME))); }
         catch (NumberFormatException e) {

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a3cee158/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/ModeledSharingProfile.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/ModeledSharingProfile.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/ModeledSharingProfile.java
index 19c70bb..1acbd79 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/ModeledSharingProfile.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharingprofile/ModeledSharingProfile.java
@@ -95,14 +95,4 @@ public class ModeledSharingProfile
         this.parameters = parameters;
     }
 
-    @Override
-    public Map<String, String> getAttributes() {
-        return Collections.<String, String>emptyMap();
-    }
-
-    @Override
-    public void setAttributes(Map<String, String> attributes) {
-        // Do nothing - no attributes
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/a3cee158/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
index 5ffc458..b295655 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java
@@ -28,9 +28,10 @@ import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TimeZone;
 import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObject;
 import org.apache.guacamole.auth.jdbc.security.PasswordEncryptionService;
@@ -145,6 +146,25 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
     ));
 
     /**
+     * The names of all attributes which are explicitly supported by this
+     * extension's User objects.
+     */
+    public static final Set<String> ATTRIBUTE_NAMES =
+            Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
+                User.Attribute.FULL_NAME,
+                User.Attribute.EMAIL_ADDRESS,
+                User.Attribute.ORGANIZATION,
+                User.Attribute.ORGANIZATIONAL_ROLE,
+                DISABLED_ATTRIBUTE_NAME,
+                EXPIRED_ATTRIBUTE_NAME,
+                ACCESS_WINDOW_START_ATTRIBUTE_NAME,
+                ACCESS_WINDOW_END_ATTRIBUTE_NAME,
+                VALID_FROM_ATTRIBUTE_NAME,
+                VALID_UNTIL_ATTRIBUTE_NAME,
+                TIMEZONE_ATTRIBUTE_NAME
+            )));
+
+    /**
      * Service for managing users.
      */
     @Inject
@@ -548,9 +568,15 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
     }
 
     @Override
+    public Set<String> getSupportedAttributeNames() {
+        return ATTRIBUTE_NAMES;
+    }
+
+    @Override
     public Map<String, String> getAttributes() {
 
-        Map<String, String> attributes = new HashMap<String, String>();
+        // Include any defined arbitrary attributes
+        Map<String, String> attributes = super.getAttributes();
 
         // Always include unrestricted attributes
         putUnrestrictedAttributes(attributes);
@@ -565,6 +591,9 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
     @Override
     public void setAttributes(Map<String, String> attributes) {
 
+        // Set arbitrary attributes
+        super.setAttributes(attributes);
+
         // Always assign unrestricted attributes
         setUnrestrictedAttributes(attributes);
 


[07/10] guacamole-client git commit: GUACAMOLE-96: Map base JDBC support for arbitrary attributes to MySQL tables.

Posted by vn...@apache.org.
GUACAMOLE-96: Map base JDBC support for arbitrary attributes to MySQL tables.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/6a834a10
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/6a834a10
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/6a834a10

Branch: refs/heads/master
Commit: 6a834a1066ad65c63d64a4aa13c64ffba6acb9b0
Parents: 4947335
Author: Michael Jumper <mj...@apache.org>
Authored: Sat Nov 25 11:41:54 2017 -0800
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Jan 31 15:26:16 2018 -0800

----------------------------------------------------------------------
 .../schema/001-create-schema.sql                |  88 +++++++++++++++
 .../schema/upgrade/upgrade-pre-0.9.15.sql       | 106 +++++++++++++++++++
 .../auth/jdbc/connection/ConnectionMapper.xml   |  58 +++++++++-
 .../connectiongroup/ConnectionGroupMapper.xml   |  58 +++++++++-
 .../sharingprofile/SharingProfileMapper.xml     |  67 +++++++++++-
 .../guacamole/auth/jdbc/user/UserMapper.xml     |  84 +++++++++++++--
 6 files changed, 446 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/6a834a10/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql
index f26d2cc..76711f1 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql
@@ -186,6 +186,94 @@ CREATE TABLE guacamole_sharing_profile_parameter (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
 --
+-- 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`         int(11)       NOT NULL,
+  `attribute_name`  varchar(128)  NOT NULL,
+  `attribute_value` varchar(4096) NOT NULL,
+
+  PRIMARY KEY (user_id, attribute_name),
+  KEY `user_id` (`user_id`),
+
+  CONSTRAINT guacamole_user_attribute_ibfk_1
+    FOREIGN KEY (user_id)
+    REFERENCES guacamole_user (user_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 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`   int(11)       NOT NULL,
+  `attribute_name`  varchar(128)  NOT NULL,
+  `attribute_value` varchar(4096) NOT NULL,
+
+  PRIMARY KEY (connection_id, attribute_name),
+  KEY `connection_id` (`connection_id`),
+
+  CONSTRAINT guacamole_connection_attribute_ibfk_1
+    FOREIGN KEY (connection_id)
+    REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 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` int(11)       NOT NULL,
+  `attribute_name`      varchar(128)  NOT NULL,
+  `attribute_value`     varchar(4096) NOT NULL,
+
+  PRIMARY KEY (connection_group_id, attribute_name),
+  KEY `connection_group_id` (`connection_group_id`),
+
+  CONSTRAINT guacamole_connection_group_attribute_ibfk_1
+    FOREIGN KEY (connection_group_id)
+    REFERENCES guacamole_connection_group (connection_group_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 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` int(11)       NOT NULL,
+  `attribute_name`     varchar(128)  NOT NULL,
+  `attribute_value`    varchar(4096) NOT NULL,
+
+  PRIMARY KEY (sharing_profile_id, attribute_name),
+  KEY `sharing_profile_id` (`sharing_profile_id`),
+
+  CONSTRAINT guacamole_sharing_profile_attribute_ibfk_1
+    FOREIGN KEY (sharing_profile_id)
+    REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
 -- Table of connection permissions. Each connection permission grants a user
 -- specific access to a connection.
 --

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/6a834a10/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.15.sql
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.15.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.15.sql
new file mode 100644
index 0000000..2979f53
--- /dev/null
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.15.sql
@@ -0,0 +1,106 @@
+--
+-- 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.
+--
+
+--
+-- 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`         int(11)       NOT NULL,
+  `attribute_name`  varchar(128)  NOT NULL,
+  `attribute_value` varchar(4096) NOT NULL,
+
+  PRIMARY KEY (user_id, attribute_name),
+  KEY `user_id` (`user_id`),
+
+  CONSTRAINT guacamole_user_attribute_ibfk_1
+    FOREIGN KEY (user_id)
+    REFERENCES guacamole_user (user_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 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`   int(11)       NOT NULL,
+  `attribute_name`  varchar(128)  NOT NULL,
+  `attribute_value` varchar(4096) NOT NULL,
+
+  PRIMARY KEY (connection_id, attribute_name),
+  KEY `connection_id` (`connection_id`),
+
+  CONSTRAINT guacamole_connection_attribute_ibfk_1
+    FOREIGN KEY (connection_id)
+    REFERENCES guacamole_connection (connection_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 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` int(11)       NOT NULL,
+  `attribute_name`      varchar(128)  NOT NULL,
+  `attribute_value`     varchar(4096) NOT NULL,
+
+  PRIMARY KEY (connection_group_id, attribute_name),
+  KEY `connection_group_id` (`connection_group_id`),
+
+  CONSTRAINT guacamole_connection_group_attribute_ibfk_1
+    FOREIGN KEY (connection_group_id)
+    REFERENCES guacamole_connection_group (connection_group_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- 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` int(11)       NOT NULL,
+  `attribute_name`     varchar(128)  NOT NULL,
+  `attribute_value`    varchar(4096) NOT NULL,
+
+  PRIMARY KEY (sharing_profile_id, attribute_name),
+  KEY `sharing_profile_id` (`sharing_profile_id`),
+
+  CONSTRAINT guacamole_sharing_profile_attribute_ibfk_1
+    FOREIGN KEY (sharing_profile_id)
+    REFERENCES guacamole_sharing_profile (sharing_profile_id) ON DELETE CASCADE
+
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/6a834a10/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
index cbffdd4..e5fd2f0 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionMapper.xml
@@ -47,6 +47,14 @@
             <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 -->
@@ -87,7 +95,7 @@
 
     <!-- Select multiple connections by identifier -->
     <select id="select" resultMap="ConnectionResultMap"
-            resultSets="connections,sharingProfiles">
+            resultSets="connections,sharingProfiles,arbitraryAttributes">
 
         SELECT
             guacamole_connection.connection_id,
@@ -119,11 +127,22 @@
                 #{identifier,jdbcType=VARCHAR}
             </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=VARCHAR}
+            </foreach>;
+
     </select>
 
     <!-- Select multiple connections by identifier only if readable -->
     <select id="selectReadable" resultMap="ConnectionResultMap"
-            resultSets="connections,sharingProfiles">
+            resultSets="connections,sharingProfiles,arbitraryAttributes">
 
         SELECT
             guacamole_connection.connection_id,
@@ -161,6 +180,20 @@
             AND user_id = #{user.objectID,jdbcType=INTEGER}
             AND permission = 'READ';
 
+        SELECT
+            guacamole_connection_attribute.connection_id,
+            attribute_name,
+            attribute_value
+        FROM guacamole_connection_attribute
+        JOIN guacamole_connection_permission ON guacamole_connection_permission.connection_id = guacamole_connection_attribute.connection_id
+        WHERE guacamole_connection_attribute.connection_id IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=VARCHAR}
+            </foreach>
+            AND user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
+
     </select>
 
     <!-- Select single connection by name -->
@@ -242,4 +275,25 @@
         WHERE connection_id = #{object.objectID,jdbcType=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>

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/6a834a10/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
index f2ef3c2..e02a046 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connectiongroup/ConnectionGroupMapper.xml
@@ -48,6 +48,14 @@
             <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 -->
@@ -88,7 +96,7 @@
 
     <!-- Select multiple connection groups by identifier -->
     <select id="select" resultMap="ConnectionGroupResultMap"
-            resultSets="connectionGroups,childConnectionGroups,childConnections">
+            resultSets="connectionGroups,childConnectionGroups,childConnections,arbitraryAttributes">
 
         SELECT
             connection_group_id,
@@ -121,11 +129,22 @@
                 #{identifier,jdbcType=VARCHAR}
             </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=VARCHAR}
+            </foreach>;
+
     </select>
 
     <!-- Select multiple connection groups by identifier only if readable -->
     <select id="selectReadable" resultMap="ConnectionGroupResultMap"
-            resultSets="connectionGroups,childConnectionGroups,childConnections">
+            resultSets="connectionGroups,childConnectionGroups,childConnections,arbitraryAttributes">
 
         SELECT
             guacamole_connection_group.connection_group_id,
@@ -167,6 +186,20 @@
             AND user_id = #{user.objectID,jdbcType=INTEGER}
             AND permission = 'READ';
 
+        SELECT
+            guacamole_connection_group_attribute.connection_group_id,
+            attribute_name,
+            attribute_value
+        FROM guacamole_connection_group_attribute
+        JOIN guacamole_connection_group_permission ON guacamole_connection_group_permission.connection_group_id = guacamole_connection_group_attribute.connection_group_id
+        WHERE guacamole_connection_group_attribute.connection_group_id IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=VARCHAR}
+            </foreach>
+            AND user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
+
     </select>
 
     <!-- Select single connection group by name -->
@@ -229,4 +262,25 @@
         WHERE connection_group_id = #{object.objectID,jdbcType=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>

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/6a834a10/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
index 49bb337..ef89913 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/sharingprofile/SharingProfileMapper.xml
@@ -25,9 +25,20 @@
 
     <!-- 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 -->
@@ -46,7 +57,8 @@
     </select>
 
     <!-- Select multiple sharing profiles by identifier -->
-    <select id="select" resultMap="SharingProfileResultMap">
+    <select id="select" resultMap="SharingProfileResultMap"
+            resultSets="sharingProfiles,arbitraryAttributes">
 
         SELECT
             sharing_profile_id,
@@ -57,12 +69,24 @@
             <foreach collection="identifiers" item="identifier"
                      open="(" separator="," close=")">
                 #{identifier,jdbcType=VARCHAR}
-            </foreach>
+            </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=VARCHAR}
+            </foreach>;
 
     </select>
 
     <!-- Select multiple sharing profiles by identifier only if readable -->
-    <select id="selectReadable" resultMap="SharingProfileResultMap">
+    <select id="selectReadable" resultMap="SharingProfileResultMap"
+            resultSets="sharingProfiles,arbitraryAttributes">
 
         SELECT
             guacamole_sharing_profile.sharing_profile_id,
@@ -76,7 +100,21 @@
                 #{identifier,jdbcType=VARCHAR}
             </foreach>
             AND user_id = #{user.objectID,jdbcType=INTEGER}
-            AND permission = 'READ'
+            AND permission = 'READ';
+
+        SELECT
+            guacamole_sharing_profile_attribute.sharing_profile_id,
+            attribute_name,
+            attribute_value
+        FROM guacamole_sharing_profile_attribute
+        JOIN guacamole_sharing_profile_permission ON guacamole_sharing_profile_permission.sharing_profile_id = guacamole_sharing_profile_attribute.sharing_profile_id
+        WHERE guacamole_sharing_profile_attribute.sharing_profile_id IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=VARCHAR}
+            </foreach>
+            AND user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
 
     </select>
 
@@ -123,4 +161,25 @@
         WHERE sharing_profile_id = #{object.objectID,jdbcType=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>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/6a834a10/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
----------------------------------------------------------------------
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
index c9e4f70..e183fe2 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/user/UserMapper.xml
@@ -25,6 +25,8 @@
 
     <!-- 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="username"            property="identifier"         jdbcType="VARCHAR"/>
         <result column="password_hash"       property="passwordHash"       jdbcType="BINARY"/>
@@ -42,6 +44,15 @@
         <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 -->
@@ -61,7 +72,8 @@
     </select>
 
     <!-- Select multiple users by username -->
-    <select id="select" resultMap="UserResultMap">
+    <select id="select" resultMap="UserResultMap"
+            resultSets="users,arbitraryAttributes">
 
         SELECT
             guacamole_user.user_id,
@@ -88,12 +100,25 @@
                      open="(" separator="," close=")">
                 #{identifier,jdbcType=VARCHAR}
             </foreach>
-        GROUP BY guacamole_user.user_id
+        GROUP BY guacamole_user.user_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
+        WHERE username IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=VARCHAR}
+            </foreach>;
 
     </select>
 
     <!-- Select multiple users by username only if readable -->
-    <select id="selectReadable" resultMap="UserResultMap">
+    <select id="selectReadable" resultMap="UserResultMap"
+            resultSets="users,arbitraryAttributes">
 
         SELECT
             guacamole_user.user_id,
@@ -123,12 +148,28 @@
             </foreach>
             AND guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
             AND permission = 'READ'
-        GROUP BY guacamole_user.user_id
+        GROUP BY guacamole_user.user_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_user_permission ON affected_user_id = guacamole_user.user_id
+        WHERE username IN
+            <foreach collection="identifiers" item="identifier"
+                     open="(" separator="," close=")">
+                #{identifier,jdbcType=VARCHAR}
+            </foreach>
+            AND guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
+            AND permission = 'READ';
 
     </select>
 
     <!-- Select single user by username -->
-    <select id="selectOne" resultMap="UserResultMap">
+    <select id="selectOne" resultMap="UserResultMap"
+            resultSets="users,arbitraryAttributes">
 
         SELECT
             guacamole_user.user_id,
@@ -152,7 +193,15 @@
         LEFT JOIN guacamole_user_history ON guacamole_user_history.user_id = guacamole_user.user_id
         WHERE
             guacamole_user.username = #{username,jdbcType=VARCHAR}
-        GROUP BY guacamole_user.user_id
+        GROUP BY guacamole_user.user_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
+        WHERE username = #{username,jdbcType=VARCHAR};
 
     </select>
 
@@ -223,4 +272,25 @@
         WHERE user_id = #{object.objectID,jdbcType=VARCHAR}
     </update>
 
-</mapper>
\ No newline at end of file
+    <!-- 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>


[04/10] guacamole-client git commit: GUACAMOLE-96: Restrict submitted attributes to those explicitly declared by the UserContext.

Posted by vn...@apache.org.
GUACAMOLE-96: Restrict submitted attributes to those explicitly declared by the UserContext.


Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/77255652
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/77255652
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/77255652

Branch: refs/heads/master
Commit: 77255652bf532b8f28baf687a6bfb10979cfa266
Parents: a050c16
Author: Michael Jumper <mj...@apache.org>
Authored: Sun Oct 29 12:59:50 2017 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Wed Jan 31 15:26:16 2018 -0800

----------------------------------------------------------------------
 .../ActiveConnectionObjectTranslator.java       |  9 ++-
 .../ActiveConnectionResource.java               |  2 +-
 .../connection/ConnectionObjectTranslator.java  | 13 +++-
 .../rest/connection/ConnectionResource.java     |  2 +-
 .../ConnectionGroupObjectTranslator.java        | 14 +++-
 .../ConnectionGroupResource.java                |  2 +-
 .../rest/directory/DirectoryObjectResource.java | 17 ++++-
 .../directory/DirectoryObjectTranslator.java    | 76 ++++++++++++++++++--
 .../rest/directory/DirectoryResource.java       |  3 +
 .../SharingProfileObjectTranslator.java         | 14 +++-
 .../sharingprofile/SharingProfileResource.java  |  2 +-
 .../rest/user/UserObjectTranslator.java         | 13 +++-
 .../guacamole/rest/user/UserResource.java       |  2 +-
 13 files changed, 153 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionObjectTranslator.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionObjectTranslator.java b/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionObjectTranslator.java
index d59f8c5..712a82f 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionObjectTranslator.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionObjectTranslator.java
@@ -22,6 +22,7 @@ package org.apache.guacamole.rest.activeconnection;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.GuacamoleUnsupportedException;
 import org.apache.guacamole.net.auth.ActiveConnection;
+import org.apache.guacamole.net.auth.UserContext;
 import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
 
 /**
@@ -30,7 +31,7 @@ import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
  * toExternalObject() is implemented here.
  */
 public class ActiveConnectionObjectTranslator
-        implements DirectoryObjectTranslator<ActiveConnection, APIActiveConnection> {
+        extends DirectoryObjectTranslator<ActiveConnection, APIActiveConnection> {
 
     @Override
     public APIActiveConnection toExternalObject(ActiveConnection object)
@@ -56,4 +57,10 @@ public class ActiveConnectionObjectTranslator
 
     }
 
+    @Override
+    public void filterExternalObject(UserContext context,
+            APIActiveConnection object) throws GuacamoleException {
+        // Nothing to filter on ActiveConnections (no attributes)
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionResource.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionResource.java
index e72e674..47ba3d4 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/activeconnection/ActiveConnectionResource.java
@@ -89,7 +89,7 @@ public class ActiveConnectionResource
             @Assisted Directory<ActiveConnection> directory,
             @Assisted ActiveConnection activeConnection,
             DirectoryObjectTranslator<ActiveConnection, APIActiveConnection> translator) {
-        super(directory, activeConnection, translator);
+        super(userContext, directory, activeConnection, translator);
         this.userContext = userContext;
         this.activeConnection = activeConnection;
     }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionObjectTranslator.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionObjectTranslator.java b/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionObjectTranslator.java
index 112c71a..416fb4a 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionObjectTranslator.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionObjectTranslator.java
@@ -21,6 +21,7 @@ package org.apache.guacamole.rest.connection;
 
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.net.auth.Connection;
+import org.apache.guacamole.net.auth.UserContext;
 import org.apache.guacamole.protocol.GuacamoleConfiguration;
 import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
 
@@ -29,7 +30,7 @@ import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
  * objects.
  */
 public class ConnectionObjectTranslator
-        implements DirectoryObjectTranslator<Connection, APIConnection> {
+        extends DirectoryObjectTranslator<Connection, APIConnection> {
 
     @Override
     public APIConnection toExternalObject(Connection object)
@@ -59,4 +60,14 @@ public class ConnectionObjectTranslator
 
     }
 
+    @Override
+    public void filterExternalObject(UserContext userContext,
+            APIConnection object) throws GuacamoleException {
+
+        // Filter object attributes by defined schema
+        object.setAttributes(filterAttributes(
+                userContext.getConnectionAttributes(), object.getAttributes()));
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java
index b1ddcfc..0b63b66 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java
@@ -100,7 +100,7 @@ public class ConnectionResource extends DirectoryObjectResource<Connection, APIC
             @Assisted Directory<Connection> directory,
             @Assisted Connection connection,
             DirectoryObjectTranslator<Connection, APIConnection> translator) {
-        super(directory, connection, translator);
+        super(userContext, directory, connection, translator);
         this.userContext = userContext;
         this.connection = connection;
     }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupObjectTranslator.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupObjectTranslator.java b/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupObjectTranslator.java
index 18de4dc..3c0ed38 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupObjectTranslator.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupObjectTranslator.java
@@ -21,6 +21,7 @@ package org.apache.guacamole.rest.connectiongroup;
 
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.net.auth.ConnectionGroup;
+import org.apache.guacamole.net.auth.UserContext;
 import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
 
 /**
@@ -28,7 +29,7 @@ import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
  * APIConnectionGroup objects.
  */
 public class ConnectionGroupObjectTranslator
-        implements DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup> {
+        extends DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup> {
 
     @Override
     public APIConnectionGroup toExternalObject(ConnectionGroup object)
@@ -53,4 +54,15 @@ public class ConnectionGroupObjectTranslator
 
     }
 
+    @Override
+    public void filterExternalObject(UserContext userContext,
+            APIConnectionGroup object) throws GuacamoleException {
+
+        // Filter object attributes by defined schema
+        object.setAttributes(filterAttributes(
+                userContext.getConnectionGroupAttributes(),
+                object.getAttributes()));
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupResource.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupResource.java
index 9e7c986..f91b8eb 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/connectiongroup/ConnectionGroupResource.java
@@ -79,7 +79,7 @@ public class ConnectionGroupResource
             @Assisted Directory<ConnectionGroup> directory,
             @Assisted ConnectionGroup connectionGroup,
             DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup> translator) {
-        super(directory, connectionGroup, translator);
+        super(userContext, directory, connectionGroup, translator);
         this.userContext = userContext;
         this.connectionGroup = connectionGroup;
     }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectResource.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectResource.java
index b5277b3..7b354a2 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectResource.java
@@ -29,6 +29,7 @@ import org.apache.guacamole.GuacamoleClientException;
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.net.auth.Directory;
 import org.apache.guacamole.net.auth.Identifiable;
+import org.apache.guacamole.net.auth.UserContext;
 
 /**
  * A REST resource which abstracts the operations available on an existing
@@ -51,6 +52,12 @@ import org.apache.guacamole.net.auth.Identifiable;
 public abstract class DirectoryObjectResource<InternalType extends Identifiable, ExternalType> {
 
     /**
+     * The UserContext associated with the Directory containing the object
+     * represented by this DirectoryObjectResource.
+     */
+    private final UserContext userContext;
+
+    /**
      * The Directory which contains the object represented by this
      * DirectoryObjectResource.
      */
@@ -71,6 +78,9 @@ public abstract class DirectoryObjectResource<InternalType extends Identifiable,
      * Creates a new DirectoryObjectResource which exposes the operations
      * available for the given object.
      *
+     * @param userContext
+     *     The UserContext associated with the given Directory.
+     *
      * @param directory
      *     The Directory which contains the given object.
      *
@@ -81,8 +91,10 @@ public abstract class DirectoryObjectResource<InternalType extends Identifiable,
      *     A DirectoryObjectTranslator implementation which handles the type of
      *     object given.
      */
-    public DirectoryObjectResource(Directory<InternalType> directory, InternalType object,
+    public DirectoryObjectResource(UserContext userContext,
+            Directory<InternalType> directory, InternalType object,
             DirectoryObjectTranslator<InternalType, ExternalType> translator) {
+        this.userContext = userContext;
         this.directory = directory;
         this.object = object;
         this.translator = translator;
@@ -121,6 +133,9 @@ public abstract class DirectoryObjectResource<InternalType extends Identifiable,
         if (modifiedObject == null)
             throw new GuacamoleClientException("Data must be submitted when updating objects.");
 
+        // Filter/sanitize object contents
+        translator.filterExternalObject(userContext, modifiedObject);
+
         // Perform update
         translator.applyExternalChanges(object, modifiedObject);
         directory.update(object);

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectTranslator.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectTranslator.java b/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectTranslator.java
index b8355bf..f3fe755 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectTranslator.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryObjectTranslator.java
@@ -19,8 +19,14 @@
 
 package org.apache.guacamole.rest.directory;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.guacamole.GuacamoleException;
+import org.apache.guacamole.form.Field;
+import org.apache.guacamole.form.Form;
 import org.apache.guacamole.net.auth.Identifiable;
+import org.apache.guacamole.net.auth.UserContext;
 
 /**
  * Provides bidirectional conversion between REST-specific objects and the
@@ -35,7 +41,7 @@ import org.apache.guacamole.net.auth.Identifiable;
  *     deserialized as JSON) between REST clients and resource implementations
  *     when representing the InternalType.
  */
-public interface DirectoryObjectTranslator<InternalType extends Identifiable, ExternalType> {
+public abstract class DirectoryObjectTranslator<InternalType extends Identifiable, ExternalType> {
 
     /**
      * Converts the given object to an object which is intended to be used in
@@ -51,7 +57,7 @@ public interface DirectoryObjectTranslator<InternalType extends Identifiable, Ex
      * @throws GuacamoleException
      *     If the provided object cannot be converted for any reason.
      */
-    ExternalType toExternalObject(InternalType object)
+    public abstract ExternalType toExternalObject(InternalType object)
             throws GuacamoleException;
 
     /**
@@ -69,7 +75,7 @@ public interface DirectoryObjectTranslator<InternalType extends Identifiable, Ex
      * @throws GuacamoleException
      *     If the provided object cannot be converted for any reason.
      */
-    InternalType toInternalObject(ExternalType object)
+    public abstract InternalType toInternalObject(ExternalType object)
             throws GuacamoleException;
 
     /**
@@ -87,7 +93,67 @@ public interface DirectoryObjectTranslator<InternalType extends Identifiable, Ex
      * @throws GuacamoleException
      *     If the provided modifications cannot be applied for any reason.
      */
-    void applyExternalChanges(InternalType existingObject, ExternalType object)
-            throws GuacamoleException;
+    public abstract void applyExternalChanges(InternalType existingObject,
+            ExternalType object) throws GuacamoleException;
+
+    /**
+     * Applies filtering to the contents of the given external object which
+     * came from an untrusted source. Implementations MUST sanitize the
+     * contents of the external object as necessary to guarantee that the
+     * object conforms to declared schema, such as the attributes declared for
+     * each object type at the UserContext level.
+     *
+     * @param userContext
+     *     The UserContext associated with the object being filtered.
+     *
+     * @param object
+     *     The object to modify such that it strictly conforms to the declared
+     *     schema.
+     *
+     * @throws GuacamoleException
+     *     If the object cannot be filtered due to an error.
+     */
+    public abstract void filterExternalObject(UserContext userContext,
+            ExternalType object) throws GuacamoleException;
+
+    /**
+     * Filters the given map of attribute name/value pairs, producing a new
+     * map containing only attributes defined as fields within the given schema.
+     *
+     * @param schema
+     *     The schema whose fields should be used to filter the given map of
+     *     attributes.
+     *
+     * @param attributes
+     *     The map of attribute name/value pairs to filter.
+     *
+     * @return
+     *     A new map containing only the attributes defined as fields within
+     *     the given schema.
+     */
+    public Map<String, String> filterAttributes(Collection<Form> schema,
+            Map<String, String> attributes) {
+
+        Map<String, String> filtered = new HashMap<String, String>();
+
+        // Grab all attribute value strictly for defined fields
+        for (Form form : schema) {
+            for (Field field : form.getFields()) {
+
+                // Pull the associated attribute value from given map
+                String attributeName = field.getName();
+                String attributeValue = attributes.get(attributeName);
+
+                // Include attribute value within filtered map only if
+                // (1) defined and (2) present within provided map
+                if (attributeValue != null)
+                    filtered.put(attributeName, attributeValue);
+
+            }
+        }
+
+        return filtered;
+
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java
index 2af0e26..3cbd481 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/directory/DirectoryResource.java
@@ -222,6 +222,9 @@ public abstract class DirectoryResource<InternalType extends Identifiable, Exter
         if (object == null)
             throw new GuacamoleClientException("Data must be submitted when creating objects.");
 
+        // Filter/sanitize object contents
+        translator.filterExternalObject(userContext, object);
+
         // Create the new object within the directory
         directory.add(translator.toInternalObject(object));
 

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/sharingprofile/SharingProfileObjectTranslator.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/sharingprofile/SharingProfileObjectTranslator.java b/guacamole/src/main/java/org/apache/guacamole/rest/sharingprofile/SharingProfileObjectTranslator.java
index 2cbe1bf..601f219 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/sharingprofile/SharingProfileObjectTranslator.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/sharingprofile/SharingProfileObjectTranslator.java
@@ -21,6 +21,7 @@ package org.apache.guacamole.rest.sharingprofile;
 
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.net.auth.SharingProfile;
+import org.apache.guacamole.net.auth.UserContext;
 import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
 
 /**
@@ -28,7 +29,7 @@ import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
  * APISharingProfile objects.
  */
 public class SharingProfileObjectTranslator
-        implements DirectoryObjectTranslator<SharingProfile, APISharingProfile> {
+        extends DirectoryObjectTranslator<SharingProfile, APISharingProfile> {
 
     @Override
     public APISharingProfile toExternalObject(SharingProfile object)
@@ -53,4 +54,15 @@ public class SharingProfileObjectTranslator
 
     }
 
+    @Override
+    public void filterExternalObject(UserContext userContext,
+            APISharingProfile object) throws GuacamoleException {
+
+        // Filter object attributes by defined schema
+        object.setAttributes(filterAttributes(
+                userContext.getSharingProfileAttributes(),
+                object.getAttributes()));
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/sharingprofile/SharingProfileResource.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/sharingprofile/SharingProfileResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/sharingprofile/SharingProfileResource.java
index 1f18d0f..7b96de9 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/sharingprofile/SharingProfileResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/sharingprofile/SharingProfileResource.java
@@ -82,7 +82,7 @@ public class SharingProfileResource
             @Assisted Directory<SharingProfile> directory,
             @Assisted SharingProfile sharingProfile,
             DirectoryObjectTranslator<SharingProfile, APISharingProfile> translator) {
-        super(directory, sharingProfile, translator);
+        super(userContext, directory, sharingProfile, translator);
         this.userContext = userContext;
         this.sharingProfile = sharingProfile;
     }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/user/UserObjectTranslator.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserObjectTranslator.java b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserObjectTranslator.java
index 35bce66..8536b35 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserObjectTranslator.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserObjectTranslator.java
@@ -21,13 +21,14 @@ package org.apache.guacamole.rest.user;
 
 import org.apache.guacamole.GuacamoleException;
 import org.apache.guacamole.net.auth.User;
+import org.apache.guacamole.net.auth.UserContext;
 import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
 
 /**
  * Translator which converts between User objects and APIUser objects.
  */
 public class UserObjectTranslator
-        implements DirectoryObjectTranslator<User, APIUser> {
+        extends DirectoryObjectTranslator<User, APIUser> {
 
     @Override
     public APIUser toExternalObject(User object)
@@ -54,4 +55,14 @@ public class UserObjectTranslator
 
     }
 
+    @Override
+    public void filterExternalObject(UserContext userContext, APIUser object)
+            throws GuacamoleException {
+
+        // Filter object attributes by defined schema
+        object.setAttributes(filterAttributes(userContext.getUserAttributes(),
+                object.getAttributes()));
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/77255652/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java
----------------------------------------------------------------------
diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java
index 75a49db..06bab9f 100644
--- a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java
+++ b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java
@@ -92,7 +92,7 @@ public class UserResource
             @Assisted Directory<User> directory,
             @Assisted User user,
             DirectoryObjectTranslator<User, APIUser> translator) {
-        super(directory, user, translator);
+        super(userContext, directory, user, translator);
         this.userContext = userContext;
         this.directory = directory;
         this.user = user;