mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-462: Generate consistent history record UUIDs based on database record IDs.
This commit is contained in:
@@ -19,8 +19,9 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.auth.jdbc.base;
|
package org.apache.guacamole.auth.jdbc.base;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
import org.apache.guacamole.net.auth.ActivityRecord;
|
import org.apache.guacamole.net.auth.ActivityRecord;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,16 +34,72 @@ public class ModeledActivityRecord implements ActivityRecord {
|
|||||||
*/
|
*/
|
||||||
private final ActivityRecordModel model;
|
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.
|
||||||
|
* <p>
|
||||||
|
* 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.
|
* Creates a new ModeledActivityRecord backed by the given model object.
|
||||||
* Changes to this record will affect the backing model object, and changes
|
* Changes to this record will affect the backing model object, and changes
|
||||||
* to the backing model object will affect this record.
|
* 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
|
* @param model
|
||||||
* The model object to use to back this activity record.
|
* The model object to use to back this activity record.
|
||||||
*/
|
*/
|
||||||
public ModeledActivityRecord(ActivityRecordModel model) {
|
public ModeledActivityRecord(UUID namespace, ActivityRecordModel model) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
|
this.uuid = getUUID(namespace, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -70,4 +127,9 @@ public class ModeledActivityRecord implements ActivityRecord {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUUID() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import com.google.inject.Inject;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
||||||
@@ -38,6 +39,15 @@ import org.apache.guacamole.net.auth.ConnectionRecord;
|
|||||||
*/
|
*/
|
||||||
public class ConnectionRecordSet extends ModeledActivityRecordSet<ConnectionRecord> {
|
public class ConnectionRecordSet extends ModeledActivityRecordSet<ConnectionRecord> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Service for managing connection objects.
|
||||||
*/
|
*/
|
||||||
|
@@ -43,7 +43,7 @@ public class ModeledConnectionRecord extends ModeledActivityRecord
|
|||||||
* The model object to use to back this connection record.
|
* The model object to use to back this connection record.
|
||||||
*/
|
*/
|
||||||
public ModeledConnectionRecord(ConnectionRecordModel model) {
|
public ModeledConnectionRecord(ConnectionRecordModel model) {
|
||||||
super(model);
|
super(ConnectionRecordSet.UUID_NAMESPACE, model);
|
||||||
this.model = model;
|
this.model = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@ import com.google.inject.Inject;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
||||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
||||||
@@ -38,6 +39,15 @@ import org.apache.guacamole.net.auth.AuthenticatedUser;
|
|||||||
*/
|
*/
|
||||||
public class UserRecordSet extends ModeledActivityRecordSet<ActivityRecord> {
|
public class UserRecordSet extends ModeledActivityRecordSet<ActivityRecord> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Service for managing user objects.
|
||||||
*/
|
*/
|
||||||
|
@@ -546,7 +546,7 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
|||||||
* A connection record object which is backed by the given model.
|
* A connection record object which is backed by the given model.
|
||||||
*/
|
*/
|
||||||
protected ActivityRecord getObjectInstance(ActivityRecordModel model) {
|
protected ActivityRecord getObjectInstance(ActivityRecordModel model) {
|
||||||
return new ModeledActivityRecord(model);
|
return new ModeledActivityRecord(UserRecordSet.UUID_NAMESPACE, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
<!-- Result mapper for system permissions -->
|
<!-- Result mapper for system permissions -->
|
||||||
<resultMap id="ConnectionRecordResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
|
<resultMap id="ConnectionRecordResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
|
||||||
|
<id column="history_id" property="recordID" jdbcType="INTEGER"/>
|
||||||
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
|
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
|
||||||
<result column="connection_name" property="connectionName" jdbcType="VARCHAR"/>
|
<result column="connection_name" property="connectionName" jdbcType="VARCHAR"/>
|
||||||
<result column="remote_host" property="remoteHost" jdbcType="VARCHAR"/>
|
<result column="remote_host" property="remoteHost" jdbcType="VARCHAR"/>
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
<select id="select" resultMap="ConnectionRecordResultMap">
|
<select id="select" resultMap="ConnectionRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_connection_history.history_id,
|
||||||
guacamole_connection_history.connection_id,
|
guacamole_connection_history.connection_id,
|
||||||
guacamole_connection_history.connection_name,
|
guacamole_connection_history.connection_name,
|
||||||
guacamole_connection_history.remote_host,
|
guacamole_connection_history.remote_host,
|
||||||
@@ -94,6 +96,7 @@
|
|||||||
<select id="search" resultMap="ConnectionRecordResultMap">
|
<select id="search" resultMap="ConnectionRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_connection_history.history_id,
|
||||||
guacamole_connection_history.connection_id,
|
guacamole_connection_history.connection_id,
|
||||||
guacamole_connection_history.connection_name,
|
guacamole_connection_history.connection_name,
|
||||||
guacamole_connection_history.remote_host,
|
guacamole_connection_history.remote_host,
|
||||||
@@ -159,6 +162,7 @@
|
|||||||
<select id="searchReadable" resultMap="ConnectionRecordResultMap">
|
<select id="searchReadable" resultMap="ConnectionRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_connection_history.history_id,
|
||||||
guacamole_connection_history.connection_id,
|
guacamole_connection_history.connection_id,
|
||||||
guacamole_connection_history.connection_name,
|
guacamole_connection_history.connection_name,
|
||||||
guacamole_connection_history.remote_host,
|
guacamole_connection_history.remote_host,
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
<select id="select" resultMap="UserRecordResultMap">
|
<select id="select" resultMap="UserRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_user_history.history_id,
|
||||||
guacamole_user_history.remote_host,
|
guacamole_user_history.remote_host,
|
||||||
guacamole_user_history.user_id,
|
guacamole_user_history.user_id,
|
||||||
guacamole_user_history.username,
|
guacamole_user_history.username,
|
||||||
@@ -97,6 +98,7 @@
|
|||||||
<select id="search" resultMap="UserRecordResultMap">
|
<select id="search" resultMap="UserRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_user_history.history_id,
|
||||||
guacamole_user_history.remote_host,
|
guacamole_user_history.remote_host,
|
||||||
guacamole_user_history.user_id,
|
guacamole_user_history.user_id,
|
||||||
guacamole_user_history.username,
|
guacamole_user_history.username,
|
||||||
@@ -153,6 +155,7 @@
|
|||||||
<select id="searchReadable" resultMap="UserRecordResultMap">
|
<select id="searchReadable" resultMap="UserRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_user_history.history_id,
|
||||||
guacamole_user_history.remote_host,
|
guacamole_user_history.remote_host,
|
||||||
guacamole_user_history.user_id,
|
guacamole_user_history.user_id,
|
||||||
guacamole_user_history.username,
|
guacamole_user_history.username,
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
<!-- Result mapper for system permissions -->
|
<!-- Result mapper for system permissions -->
|
||||||
<resultMap id="ConnectionRecordResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
|
<resultMap id="ConnectionRecordResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
|
||||||
|
<id column="history_id" property="recordID" jdbcType="INTEGER"/>
|
||||||
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
|
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
|
||||||
<result column="connection_name" property="connectionName" jdbcType="VARCHAR"/>
|
<result column="connection_name" property="connectionName" jdbcType="VARCHAR"/>
|
||||||
<result column="remote_host" property="remoteHost" jdbcType="VARCHAR"/>
|
<result column="remote_host" property="remoteHost" jdbcType="VARCHAR"/>
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
<select id="select" resultMap="ConnectionRecordResultMap">
|
<select id="select" resultMap="ConnectionRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_connection_history.history_id,
|
||||||
guacamole_connection_history.connection_id,
|
guacamole_connection_history.connection_id,
|
||||||
guacamole_connection_history.connection_name,
|
guacamole_connection_history.connection_name,
|
||||||
guacamole_connection_history.remote_host,
|
guacamole_connection_history.remote_host,
|
||||||
@@ -94,6 +96,7 @@
|
|||||||
<select id="search" resultMap="ConnectionRecordResultMap">
|
<select id="search" resultMap="ConnectionRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_connection_history.history_id,
|
||||||
guacamole_connection_history.connection_id,
|
guacamole_connection_history.connection_id,
|
||||||
guacamole_connection_history.connection_name,
|
guacamole_connection_history.connection_name,
|
||||||
guacamole_connection_history.remote_host,
|
guacamole_connection_history.remote_host,
|
||||||
@@ -157,6 +160,7 @@
|
|||||||
<select id="searchReadable" resultMap="ConnectionRecordResultMap">
|
<select id="searchReadable" resultMap="ConnectionRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_connection_history.history_id,
|
||||||
guacamole_connection_history.connection_id,
|
guacamole_connection_history.connection_id,
|
||||||
guacamole_connection_history.connection_name,
|
guacamole_connection_history.connection_name,
|
||||||
guacamole_connection_history.remote_host,
|
guacamole_connection_history.remote_host,
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
<select id="select" resultMap="UserRecordResultMap">
|
<select id="select" resultMap="UserRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_user_history.history_id,
|
||||||
guacamole_user_history.remote_host,
|
guacamole_user_history.remote_host,
|
||||||
guacamole_user_history.user_id,
|
guacamole_user_history.user_id,
|
||||||
guacamole_user_history.username,
|
guacamole_user_history.username,
|
||||||
@@ -97,6 +98,7 @@
|
|||||||
<select id="search" resultMap="UserRecordResultMap">
|
<select id="search" resultMap="UserRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_user_history.history_id,
|
||||||
guacamole_user_history.remote_host,
|
guacamole_user_history.remote_host,
|
||||||
guacamole_user_history.user_id,
|
guacamole_user_history.user_id,
|
||||||
guacamole_user_history.username,
|
guacamole_user_history.username,
|
||||||
@@ -153,6 +155,7 @@
|
|||||||
<select id="searchReadable" resultMap="UserRecordResultMap">
|
<select id="searchReadable" resultMap="UserRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
guacamole_user_history.history_id,
|
||||||
guacamole_user_history.remote_host,
|
guacamole_user_history.remote_host,
|
||||||
guacamole_user_history.user_id,
|
guacamole_user_history.user_id,
|
||||||
guacamole_user_history.username,
|
guacamole_user_history.username,
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
<!-- Result mapper for system permissions -->
|
<!-- Result mapper for system permissions -->
|
||||||
<resultMap id="ConnectionRecordResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
|
<resultMap id="ConnectionRecordResultMap" type="org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel">
|
||||||
|
<id column="history_id" property="recordID" jdbcType="INTEGER"/>
|
||||||
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
|
<result column="connection_id" property="connectionIdentifier" jdbcType="INTEGER"/>
|
||||||
<result column="connection_name" property="connectionName" jdbcType="VARCHAR"/>
|
<result column="connection_name" property="connectionName" jdbcType="VARCHAR"/>
|
||||||
<result column="remote_host" property="remoteHost" jdbcType="VARCHAR"/>
|
<result column="remote_host" property="remoteHost" jdbcType="VARCHAR"/>
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
<select id="select" resultMap="ConnectionRecordResultMap">
|
<select id="select" resultMap="ConnectionRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
[guacamole_connection_history].history_id,
|
||||||
[guacamole_connection_history].connection_id,
|
[guacamole_connection_history].connection_id,
|
||||||
[guacamole_connection_history].connection_name,
|
[guacamole_connection_history].connection_name,
|
||||||
[guacamole_connection_history].remote_host,
|
[guacamole_connection_history].remote_host,
|
||||||
@@ -94,6 +96,7 @@
|
|||||||
<select id="search" resultMap="ConnectionRecordResultMap">
|
<select id="search" resultMap="ConnectionRecordResultMap">
|
||||||
|
|
||||||
SELECT TOP (#{limit,jdbcType=INTEGER})
|
SELECT TOP (#{limit,jdbcType=INTEGER})
|
||||||
|
[guacamole_connection_history].history_id,
|
||||||
[guacamole_connection_history].connection_id,
|
[guacamole_connection_history].connection_id,
|
||||||
[guacamole_connection_history].connection_name,
|
[guacamole_connection_history].connection_name,
|
||||||
[guacamole_connection_history].remote_host,
|
[guacamole_connection_history].remote_host,
|
||||||
@@ -155,6 +158,7 @@
|
|||||||
<select id="searchReadable" resultMap="ConnectionRecordResultMap">
|
<select id="searchReadable" resultMap="ConnectionRecordResultMap">
|
||||||
|
|
||||||
SELECT TOP (#{limit,jdbcType=INTEGER})
|
SELECT TOP (#{limit,jdbcType=INTEGER})
|
||||||
|
[guacamole_connection_history].history_id,
|
||||||
[guacamole_connection_history].connection_id,
|
[guacamole_connection_history].connection_id,
|
||||||
[guacamole_connection_history].connection_name,
|
[guacamole_connection_history].connection_name,
|
||||||
[guacamole_connection_history].remote_host,
|
[guacamole_connection_history].remote_host,
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
<select id="select" resultMap="UserRecordResultMap">
|
<select id="select" resultMap="UserRecordResultMap">
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
|
[guacamole_user_history].history_id,
|
||||||
[guacamole_user_history].remote_host,
|
[guacamole_user_history].remote_host,
|
||||||
[guacamole_user_history].user_id,
|
[guacamole_user_history].user_id,
|
||||||
[guacamole_user_history].username,
|
[guacamole_user_history].username,
|
||||||
@@ -97,6 +98,7 @@
|
|||||||
<select id="search" resultMap="UserRecordResultMap">
|
<select id="search" resultMap="UserRecordResultMap">
|
||||||
|
|
||||||
SELECT TOP (#{limit,jdbcType=INTEGER})
|
SELECT TOP (#{limit,jdbcType=INTEGER})
|
||||||
|
[guacamole_user_history].history_id,
|
||||||
[guacamole_user_history].remote_host,
|
[guacamole_user_history].remote_host,
|
||||||
[guacamole_user_history].user_id,
|
[guacamole_user_history].user_id,
|
||||||
[guacamole_user_history].username,
|
[guacamole_user_history].username,
|
||||||
@@ -151,6 +153,7 @@
|
|||||||
<select id="searchReadable" resultMap="UserRecordResultMap">
|
<select id="searchReadable" resultMap="UserRecordResultMap">
|
||||||
|
|
||||||
SELECT TOP (#{limit,jdbcType=INTEGER})
|
SELECT TOP (#{limit,jdbcType=INTEGER})
|
||||||
|
[guacamole_user_history].history_id,
|
||||||
[guacamole_user_history].remote_host,
|
[guacamole_user_history].remote_host,
|
||||||
[guacamole_user_history].user_id,
|
[guacamole_user_history].user_id,
|
||||||
[guacamole_user_history].username,
|
[guacamole_user_history].username,
|
||||||
|
Reference in New Issue
Block a user