diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecord.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecord.java index 95b1a256d..ba4fbc694 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecord.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecord.java @@ -19,8 +19,9 @@ package org.apache.guacamole.auth.jdbc.base; - +import java.nio.ByteBuffer; import java.util.Date; +import java.util.UUID; import org.apache.guacamole.net.auth.ActivityRecord; /** @@ -33,16 +34,72 @@ public class ModeledActivityRecord implements ActivityRecord { */ private final ActivityRecordModel model; + /** + * The UUID uniquely identifies this record, or null if no such unique + * identifier exists. + */ + private final UUID uuid; + + /** + * Generates a UUID that uniquely identifies the record represented by the + * given ActivityRecordModel. The UUID generated is a type 3 name UUID and + * is guaranteed to be unique so long as the provided UUID namespace + * corresponds to the namespace of the record ID within the model. + *

+ * IMPORTANT: Changing this function such that different UUIDs will be + * generated for the same records relative to past releases can potentially + * break compatibility with established history record associations. Any + * such change should be made with great care to avoid breaking history + * functionality that may be provided by third-party extensions. + * + * @param namespace + * The UUID namespace of the type 3 name UUID to generate. This + * namespace should correspond to the source of IDs for the model + * such that the combination of this namespace with the numeric record + * ID will always be unique and deterministic across all activity + * records, regardless of record type. + * + * @param model + * The model object representing the activity record. + * + * @return + * The UUID uniquely identifies the record represented by the given + * model, or null if no such unique identifier can be generated (there + * is no corresponding record ID). + */ + private static UUID getUUID(UUID namespace, ActivityRecordModel model) { + + Integer id = model.getRecordID(); + if (id == null) + return null; + + // Convert record ID to a name UUID in the given namespace + return UUID.nameUUIDFromBytes(ByteBuffer.allocate(24) + .putLong(namespace.getMostSignificantBits()) + .putLong(namespace.getLeastSignificantBits()) + .putLong(id) + .array()); + + } + /** * Creates a new ModeledActivityRecord backed by the given model object. * Changes to this record will affect the backing model object, and changes * to the backing model object will affect this record. - * + * + * @param namespace + * The UUID namespace of the type 3 name UUID to generate for the + * record. This namespace should correspond to the source of IDs for + * the model such that the combination of this namespace with the + * numeric record ID will always be unique and deterministic across all + * activity records, regardless of record type. + * * @param model * The model object to use to back this activity record. */ - public ModeledActivityRecord(ActivityRecordModel model) { + public ModeledActivityRecord(UUID namespace, ActivityRecordModel model) { this.model = model; + this.uuid = getUUID(namespace, model); } @Override @@ -70,4 +127,9 @@ public class ModeledActivityRecord implements ActivityRecord { return false; } + @Override + public UUID getUUID() { + return uuid; + } + } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java index 2f559e930..baf005675 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java @@ -23,6 +23,7 @@ import com.google.inject.Inject; import java.util.Collection; import java.util.List; import java.util.Set; +import java.util.UUID; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm; import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate; @@ -38,6 +39,15 @@ import org.apache.guacamole.net.auth.ConnectionRecord; */ public class ConnectionRecordSet extends ModeledActivityRecordSet { + /** + * The namespace for the type 3 UUIDs generated for connection history + * records. This UUID namespace is itself a type 3 UUID within the "ns:OID" + * namespace for the OID "1.3.6.1.4.1.18060.18.2.1.2", which has been + * specifically allocated for Apache Guacamole database connection + * history records. + */ + public static final UUID UUID_NAMESPACE = UUID.fromString("8b55f070-95f4-3d31-93ee-9c5845e7aa40"); + /** * Service for managing connection objects. */ diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnectionRecord.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnectionRecord.java index 9f34385cf..b02ca14c1 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnectionRecord.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnectionRecord.java @@ -43,7 +43,7 @@ public class ModeledConnectionRecord extends ModeledActivityRecord * The model object to use to back this connection record. */ public ModeledConnectionRecord(ConnectionRecordModel model) { - super(model); + super(ConnectionRecordSet.UUID_NAMESPACE, model); this.model = model; } diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java index c5c9f6a6c..a1ccf1212 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java @@ -23,6 +23,7 @@ import com.google.inject.Inject; import java.util.Collection; import java.util.List; import java.util.Set; +import java.util.UUID; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm; import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate; @@ -38,6 +39,15 @@ import org.apache.guacamole.net.auth.AuthenticatedUser; */ public class UserRecordSet extends ModeledActivityRecordSet { + /** + * The namespace for the type 3 UUIDs generated for user history records. + * This UUID namespace is itself a type 3 UUID within the "ns:OID" + * namespace for the OID "1.3.6.1.4.1.18060.18.2.1.1", which has been + * specifically allocated for Apache Guacamole database user history + * records. + */ + public static final UUID UUID_NAMESPACE = UUID.fromString("e104741a-c949-3947-8d79-f3f2cdce7d6f"); + /** * Service for managing user objects. */ diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java index 6f6d05625..03010e835 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserService.java @@ -546,7 +546,7 @@ public class UserService extends ModeledDirectoryObjectService + @@ -40,6 +41,7 @@ SELECT + guacamole_connection_history.history_id, guacamole_connection_history.connection_id, guacamole_connection_history.connection_name, guacamole_connection_history.remote_host, @@ -159,6 +162,7 @@ SELECT + guacamole_user_history.history_id, guacamole_user_history.remote_host, guacamole_user_history.user_id, guacamole_user_history.username, @@ -97,6 +98,7 @@ SELECT + guacamole_user_history.history_id, guacamole_user_history.remote_host, guacamole_user_history.user_id, guacamole_user_history.username, diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml index 1dcf9506e..fa34eb315 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml @@ -25,6 +25,7 @@ + @@ -40,6 +41,7 @@ SELECT + guacamole_connection_history.history_id, guacamole_connection_history.connection_id, guacamole_connection_history.connection_name, guacamole_connection_history.remote_host, @@ -157,6 +160,7 @@ SELECT + guacamole_user_history.history_id, guacamole_user_history.remote_host, guacamole_user_history.user_id, guacamole_user_history.username, @@ -97,6 +98,7 @@ SELECT + guacamole_user_history.history_id, guacamole_user_history.remote_host, guacamole_user_history.user_id, guacamole_user_history.username, diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml index 0ea14cc85..18921a10d 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-sqlserver/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml @@ -25,6 +25,7 @@ + @@ -40,6 +41,7 @@ SELECT TOP (#{limit,jdbcType=INTEGER}) + [guacamole_connection_history].history_id, [guacamole_connection_history].connection_id, [guacamole_connection_history].connection_name, [guacamole_connection_history].remote_host, @@ -155,6 +158,7 @@ SELECT + [guacamole_user_history].history_id, [guacamole_user_history].remote_host, [guacamole_user_history].user_id, [guacamole_user_history].username, @@ -97,6 +98,7 @@ SELECT TOP (#{limit,jdbcType=INTEGER}) + [guacamole_user_history].history_id, [guacamole_user_history].remote_host, [guacamole_user_history].user_id, [guacamole_user_history].username,