GUACAMOLE-1123: Add RecordMapper support for searching history limited by the identifier of a record.

This commit is contained in:
Virtually Nick
2020-08-22 20:48:58 -04:00
parent f00f6d6935
commit 54b80f94bf
11 changed files with 475 additions and 305 deletions

View File

@@ -62,7 +62,11 @@ public interface ConnectionRecordMapper {
* the data they are associated with is is readable by any particular user. * the data they are associated with is is readable by any particular user.
* This should only be called on behalf of a system administrator. If * This should only be called on behalf of a system administrator. If
* records are needed by a non-administrative user who must have explicit * records are needed by a non-administrative user who must have explicit
* read rights, use searchReadable() instead. * read rights, use {@link searchReadable()} instead.
*
* @param identifier
* The optional connection identifier to which records should be limited,
* or null if all records should be retrieved.
* *
* @param terms * @param terms
* The search terms that must match the returned records. * The search terms that must match the returned records.
@@ -77,7 +81,8 @@ public interface ConnectionRecordMapper {
* @return * @return
* The results of the search performed with the given parameters. * The results of the search performed with the given parameters.
*/ */
List<ConnectionRecordModel> search(@Param("terms") Collection<ActivityRecordSearchTerm> terms, List<ConnectionRecordModel> search(@Param("identifier") String identifier,
@Param("terms") Collection<ActivityRecordSearchTerm> terms,
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates, @Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
@Param("limit") int limit); @Param("limit") int limit);
@@ -86,7 +91,12 @@ public interface ConnectionRecordMapper {
* the given terms, sorted by the given predicates. Only records that are * the given terms, sorted by the given predicates. Only records that are
* associated with data explicitly readable by the given user will be * associated with data explicitly readable by the given user will be
* returned. If records are needed by a system administrator (who, by * returned. If records are needed by a system administrator (who, by
* definition, does not need explicit read rights), use search() instead. * definition, does not need explicit read rights), use {@link search()}
* instead.
*
* @param identifier
* The optional connection identifier for which records should be
* retrieved, or null if all readable records should be retrieved.
* *
* @param user * @param user
* The user whose permissions should determine whether a record is * The user whose permissions should determine whether a record is
@@ -111,7 +121,8 @@ public interface ConnectionRecordMapper {
* @return * @return
* The results of the search performed with the given parameters. * The results of the search performed with the given parameters.
*/ */
List<ConnectionRecordModel> searchReadable(@Param("user") UserModel user, List<ConnectionRecordModel> searchReadable(@Param("identifier") String identifier,
@Param("user") UserModel user,
@Param("terms") Collection<ActivityRecordSearchTerm> terms, @Param("terms") Collection<ActivityRecordSearchTerm> terms,
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates, @Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
@Param("limit") int limit, @Param("limit") int limit,

View File

@@ -213,7 +213,7 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
Map<String, String> parameters = connection.getConfiguration().getParameters(); Map<String, String> parameters = connection.getConfiguration().getParameters();
// Convert parameters to model objects // Convert parameters to model objects
Collection<ConnectionParameterModel> parameterModels = new ArrayList<ConnectionParameterModel>(parameters.size()); Collection<ConnectionParameterModel> parameterModels = new ArrayList<>(parameters.size());
for (Map.Entry<String, String> parameterEntry : parameters.entrySet()) { for (Map.Entry<String, String> parameterEntry : parameters.entrySet()) {
// Get parameter name and value // Get parameter name and value
@@ -329,7 +329,7 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
public Map<String, String> retrieveParameters(ModeledAuthenticatedUser user, public Map<String, String> retrieveParameters(ModeledAuthenticatedUser user,
String identifier) { String identifier) {
Map<String, String> parameterMap = new HashMap<String, String>(); Map<String, String> parameterMap = new HashMap<>();
// Determine whether we have permission to read parameters // Determine whether we have permission to read parameters
boolean canRetrieveParameters; boolean canRetrieveParameters;
@@ -382,7 +382,7 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
protected List<ConnectionRecord> getObjectInstances(List<ConnectionRecordModel> models) { protected List<ConnectionRecord> getObjectInstances(List<ConnectionRecordModel> models) {
// Create new list of records by manually converting each model // Create new list of records by manually converting each model
List<ConnectionRecord> objects = new ArrayList<ConnectionRecord>(models.size()); List<ConnectionRecord> objects = new ArrayList<>(models.size());
for (ConnectionRecordModel model : models) for (ConnectionRecordModel model : models)
objects.add(getObjectInstance(model)); objects.add(getObjectInstance(model));
@@ -412,27 +412,69 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
String identifier = connection.getIdentifier(); String identifier = connection.getIdentifier();
// Retrieve history only if READ permission is granted // Get current active connections.
if (hasObjectPermission(user, identifier, ObjectPermission.Type.READ)) { List<ConnectionRecord> records = new ArrayList<>(tunnelService.getActiveConnections(connection));
// Retrieve history
List<ConnectionRecordModel> models = connectionRecordMapper.select(identifier);
// Get currently-active connections
List<ConnectionRecord> records = new ArrayList<ConnectionRecord>(tunnelService.getActiveConnections(connection));
Collections.reverse(records); Collections.reverse(records);
// Add past connections from model objects // Add in the history records.
for (ConnectionRecordModel model : models) records.addAll(retrieveHistory(identifier, user, Collections.emptyList(),
records.add(getObjectInstance(model)); Collections.emptyList(), Integer.MAX_VALUE));
// Return converted history list
return records; return records;
} }
// The user does not have permission to read the history /**
throw new GuacamoleSecurityException("Permission denied."); * Retrieves the connection history records matching the given criteria.
* Retrieves up to <code>limit</code> connection history records matching
* the given terms and sorted by the given predicates. Only history records
* associated with data that the given user can read are returned.
*
* @param identifier
* The optional connection identifier for which history records should
* be retrieved, or null if all readable records should be retrieved.
*
* @param user
* The user retrieving the connection history.
*
* @param requiredContents
* The search terms that must be contained somewhere within each of the
* returned records.
*
* @param sortPredicates
* A list of predicates to sort the returned records by, in order of
* priority.
*
* @param limit
* The maximum number of records that should be returned.
*
* @return
* The connection history of the given connection, including any
* active connections.
*
* @throws GuacamoleException
* If permission to read the connection history is denied.
*/
public List<ConnectionRecord> retrieveHistory(String identifier,
ModeledAuthenticatedUser user,
Collection<ActivityRecordSearchTerm> requiredContents,
List<ActivityRecordSortPredicate> sortPredicates, int limit)
throws GuacamoleException {
List<ConnectionRecordModel> searchResults;
// Bypass permission checks if the user is privileged
if (user.isPrivileged())
searchResults = connectionRecordMapper.search(identifier, requiredContents,
sortPredicates, limit);
// Otherwise only return explicitly readable history records
else
searchResults = connectionRecordMapper.searchReadable(identifier,
user.getUser().getModel(), requiredContents, sortPredicates,
limit, user.getEffectiveUserGroups());
return getObjectInstances(searchResults);
} }
@@ -468,20 +510,7 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
List<ActivityRecordSortPredicate> sortPredicates, int limit) List<ActivityRecordSortPredicate> sortPredicates, int limit)
throws GuacamoleException { throws GuacamoleException {
List<ConnectionRecordModel> searchResults; return retrieveHistory(null, user, requiredContents, sortPredicates, limit);
// Bypass permission checks if the user is privileged
if (user.isPrivileged())
searchResults = connectionRecordMapper.search(requiredContents,
sortPredicates, limit);
// Otherwise only return explicitly readable history records
else
searchResults = connectionRecordMapper.searchReadable(
user.getUser().getModel(), requiredContents, sortPredicates,
limit, user.getEffectiveUserGroups());
return getObjectInstances(searchResults);
} }

View File

@@ -73,7 +73,11 @@ public interface UserRecordMapper {
* the data they are associated with is is readable by any particular user. * the data they are associated with is is readable by any particular user.
* This should only be called on behalf of a system administrator. If * This should only be called on behalf of a system administrator. If
* records are needed by a non-administrative user who must have explicit * records are needed by a non-administrative user who must have explicit
* read rights, use searchReadable() instead. * read rights, use {@link searchReadable()} instead.
*
* @param username
* The optional username to which records should be limited, or null
* if all records should be retrieved.
* *
* @param terms * @param terms
* The search terms that must match the returned records. * The search terms that must match the returned records.
@@ -88,7 +92,8 @@ public interface UserRecordMapper {
* @return * @return
* The results of the search performed with the given parameters. * The results of the search performed with the given parameters.
*/ */
List<ActivityRecordModel> search(@Param("terms") Collection<ActivityRecordSearchTerm> terms, List<ActivityRecordModel> search(@Param("username") String username,
@Param("terms") Collection<ActivityRecordSearchTerm> terms,
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates, @Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
@Param("limit") int limit); @Param("limit") int limit);
@@ -97,7 +102,12 @@ public interface UserRecordMapper {
* the given terms, sorted by the given predicates. Only records that are * the given terms, sorted by the given predicates. Only records that are
* associated with data explicitly readable by the given user will be * associated with data explicitly readable by the given user will be
* returned. If records are needed by a system administrator (who, by * returned. If records are needed by a system administrator (who, by
* definition, does not need explicit read rights), use search() instead. * definition, does not need explicit read rights), use {@link search()}
* instead.
*
* @param username
* The optional username to which records should be limited, or null
* if all readable records should be retrieved.
* *
* @param user * @param user
* The user whose permissions should determine whether a record is * The user whose permissions should determine whether a record is
@@ -122,7 +132,8 @@ public interface UserRecordMapper {
* @return * @return
* The results of the search performed with the given parameters. * The results of the search performed with the given parameters.
*/ */
List<ActivityRecordModel> searchReadable(@Param("user") UserModel user, List<ActivityRecordModel> searchReadable(@Param("username") String username,
@Param("user") UserModel user,
@Param("terms") Collection<ActivityRecordSearchTerm> terms, @Param("terms") Collection<ActivityRecordSearchTerm> terms,
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates, @Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
@Param("limit") int limit, @Param("limit") int limit,

View File

@@ -32,7 +32,6 @@ import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectService; import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectService;
import org.apache.guacamole.GuacamoleClientException; import org.apache.guacamole.GuacamoleClientException;
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.GuacamoleSecurityException;
import org.apache.guacamole.GuacamoleUnsupportedException; import org.apache.guacamole.GuacamoleUnsupportedException;
import org.apache.guacamole.auth.jdbc.base.ActivityRecordModel; import org.apache.guacamole.auth.jdbc.base.ActivityRecordModel;
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm; import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
@@ -582,12 +581,61 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
String username = user.getIdentifier(); String username = user.getIdentifier();
// Retrieve history only if READ permission is granted return retrieveHistory(username, authenticatedUser, Collections.emptyList(),
if (hasObjectPermission(authenticatedUser, username, ObjectPermission.Type.READ)) Collections.emptyList(), Integer.MAX_VALUE);
return getObjectInstances(userRecordMapper.select(username));
// The user does not have permission to read the history }
throw new GuacamoleSecurityException("Permission denied.");
/**
* Retrieves user login history records matching the given criteria.
* Retrieves up to <code>limit</code> user history records matching the
* given terms and sorted by the given predicates. Only history records
* associated with data that the given user can read are returned.
*
* @param username
* The optional username to which history records should be limited, or
* null if all readable records should be retrieved.
*
* @param user
* The user retrieving the login history.
*
* @param requiredContents
* The search terms that must be contained somewhere within each of the
* returned records.
*
* @param sortPredicates
* A list of predicates to sort the returned records by, in order of
* priority.
*
* @param limit
* The maximum number of records that should be returned.
*
* @return
* The login history of the given user, including any active sessions.
*
* @throws GuacamoleException
* If permission to read the user login history is denied.
*/
public List<ActivityRecord> retrieveHistory(String username,
ModeledAuthenticatedUser user,
Collection<ActivityRecordSearchTerm> requiredContents,
List<ActivityRecordSortPredicate> sortPredicates, int limit)
throws GuacamoleException {
List<ActivityRecordModel> searchResults;
// Bypass permission checks if the user is privileged
if (user.isPrivileged())
searchResults = userRecordMapper.search(username, requiredContents,
sortPredicates, limit);
// Otherwise only return explicitly readable history records
else
searchResults = userRecordMapper.searchReadable(username,
user.getUser().getModel(),
requiredContents, sortPredicates, limit, user.getEffectiveUserGroups());
return getObjectInstances(searchResults);
} }
@@ -622,19 +670,7 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
List<ActivityRecordSortPredicate> sortPredicates, int limit) List<ActivityRecordSortPredicate> sortPredicates, int limit)
throws GuacamoleException { throws GuacamoleException {
List<ActivityRecordModel> searchResults; return retrieveHistory(null, user, requiredContents, sortPredicates, limit);
// Bypass permission checks if the user is privileged
if (user.isPrivileged())
searchResults = userRecordMapper.search(requiredContents,
sortPredicates, limit);
// Otherwise only return explicitly readable history records
else
searchResults = userRecordMapper.searchReadable(user.getUser().getModel(),
requiredContents, sortPredicates, limit, user.getEffectiveUserGroups());
return getObjectInstances(searchResults);
} }

View File

@@ -108,8 +108,13 @@
LEFT JOIN guacamole_user ON guacamole_connection_history.user_id = guacamole_user.user_id LEFT JOIN guacamole_user ON guacamole_connection_history.user_id = guacamole_user.user_id
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="identifier != null">
guacamole_connection_history.connection_id = #{identifier,jdbcType=VARCHAR}
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
guacamole_connection_history.user_id IN ( guacamole_connection_history.user_id IN (
@@ -131,6 +136,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
@@ -186,8 +193,13 @@
AND guacamole_user_permission.permission = 'READ' AND guacamole_user_permission.permission = 'READ'
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="identifier != null">
guacamole_connection_history.connection_id = #{identifier,jdbcType=VARCHAR}
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
guacamole_connection_history.user_id IN ( guacamole_connection_history.user_id IN (
@@ -212,6 +224,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>

View File

@@ -105,8 +105,13 @@
FROM guacamole_user_history FROM guacamole_user_history
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="username != null">
guacamole_user_history.username = #{username,jdbcType=VARCHAR}
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
guacamole_user_history.user_id IN ( guacamole_user_history.user_id IN (
@@ -125,6 +130,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
@@ -164,8 +171,13 @@
AND guacamole_user_permission.permission = 'READ' AND guacamole_user_permission.permission = 'READ'
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="username != null">
guacamole_entity.name = #{username,jdbcType=VARCHAR}
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
guacamole_user_history.user_id IN ( guacamole_user_history.user_id IN (
@@ -184,6 +196,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>

View File

@@ -106,8 +106,13 @@
FROM guacamole_connection_history FROM guacamole_connection_history
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="identifier != null">
guacamole_connection_history.connection_id = #{identifier,jdbcType=INTEGER}::integer
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
guacamole_connection_history.user_id IN ( guacamole_connection_history.user_id IN (
@@ -129,6 +134,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
@@ -184,8 +191,13 @@
AND guacamole_user_permission.permission = 'READ' AND guacamole_user_permission.permission = 'READ'
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="identifier != null">
guacamole_connection_history.connection_id = #{identifier,jdbcType=INTEGER}::integer
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
guacamole_connection_history.user_id IN ( guacamole_connection_history.user_id IN (
@@ -210,6 +222,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>

View File

@@ -105,8 +105,13 @@
FROM guacamole_user_history FROM guacamole_user_history
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="username != null">
guacamole_user_history.username = #{username,jdbcType=VARCHAR}
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
guacamole_user_history.user_id IN ( guacamole_user_history.user_id IN (
@@ -125,6 +130,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
@@ -164,8 +171,12 @@
AND guacamole_user_permission.permission = 'READ' AND guacamole_user_permission.permission = 'READ'
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND "> <if test="username != null">
guacamole_entity.name = #{username,jdbcType=VARCHAR}
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
guacamole_user_history.user_id IN ( guacamole_user_history.user_id IN (
@@ -184,6 +195,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>

View File

@@ -106,8 +106,13 @@
FROM [guacamole_connection_history] FROM [guacamole_connection_history]
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="identifier != null">
[guacamole_connection_history].connection_id = #{identifier,jdbcType=INTEGER}
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
[guacamole_connection_history].user_id IN ( [guacamole_connection_history].user_id IN (
@@ -129,6 +134,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
@@ -182,8 +189,13 @@
AND [guacamole_user_permission].permission = 'READ' AND [guacamole_user_permission].permission = 'READ'
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="identifier != null">
[guacamole_connection_history].connection_id = #{identifier,jdbcType=INTEGER}
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
[guacamole_connection_history].user_id IN ( [guacamole_connection_history].user_id IN (
@@ -208,6 +220,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>

View File

@@ -105,8 +105,13 @@
FROM [guacamole_user_history] FROM [guacamole_user_history]
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="username != null">
[guacamole_user_history].username = #{username,jdbcType=VARCHAR}
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
[guacamole_user_history].user_id IN ( [guacamole_user_history].user_id IN (
@@ -125,6 +130,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
@@ -162,8 +169,13 @@
AND [guacamole_user_permission].permission = 'READ' AND [guacamole_user_permission].permission = 'READ'
<!-- Search terms --> <!-- Search terms -->
<foreach collection="terms" item="term" <where>
open="WHERE " separator=" AND ">
<if test="username != null">
[guacamole_entity].name = #{username,jdbcType=VARCHAR}
</if>
<foreach collection="terms" item="term" open=" AND " separator=" AND ">
( (
[guacamole_user_history].user_id IN ( [guacamole_user_history].user_id IN (
@@ -182,6 +194,8 @@
) )
</foreach> </foreach>
</where>
<!-- Bind sort property enum values for sake of readability --> <!-- Bind sort property enum values for sake of readability -->
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/> <bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>

View File

@@ -156,7 +156,7 @@ public class ConnectionResource extends DirectoryObjectResource<Connection, APIC
throws GuacamoleException { throws GuacamoleException {
// Retrieve the requested connection's history // Retrieve the requested connection's history
List<APIConnectionRecord> apiRecords = new ArrayList<APIConnectionRecord>(); List<APIConnectionRecord> apiRecords = new ArrayList<>();
for (ConnectionRecord record : connection.getHistory()) for (ConnectionRecord record : connection.getHistory())
apiRecords.add(new APIConnectionRecord(record)); apiRecords.add(new APIConnectionRecord(record));
@@ -184,7 +184,7 @@ public class ConnectionResource extends DirectoryObjectResource<Connection, APIC
// Produce subset of all SharingProfiles, containing only those which // Produce subset of all SharingProfiles, containing only those which
// are associated with this connection // are associated with this connection
Directory<SharingProfile> sharingProfiles = new DirectoryView<SharingProfile>( Directory<SharingProfile> sharingProfiles = new DirectoryView<>(
userContext.getSharingProfileDirectory(), userContext.getSharingProfileDirectory(),
connection.getSharingProfileIdentifiers() connection.getSharingProfileIdentifiers()
); );