GUAC-1193: Add searchReadable() query, limited by available permissions.

This commit is contained in:
Michael Jumper
2015-10-08 16:32:55 -07:00
parent b02fdb673a
commit 9b99fd7323
3 changed files with 197 additions and 11 deletions

View File

@@ -22,9 +22,10 @@
package org.glyptodon.guacamole.auth.jdbc.connection;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.ibatis.annotations.Param;
import org.glyptodon.guacamole.auth.jdbc.user.UserModel;
/**
* Mapper for connection record objects.
@@ -60,7 +61,11 @@ public interface ConnectionRecordMapper {
/**
* Searches for up to <code>limit</code> connection records that contain
* the given terms, sorted by the given predicates.
* the given terms, sorted by the given predicates, regardless of whether
* 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
* records are needed by a non-administrative user who must have explicit
* read rights, use searchReadable() instead.
*
* @param terms
* The search terms that must match the returned records.
@@ -75,7 +80,36 @@ public interface ConnectionRecordMapper {
* @return
* The results of the search performed with the given parameters.
*/
List<ConnectionRecordModel> search(@Param("terms") Set<ConnectionRecordSearchTerm> terms,
List<ConnectionRecordModel> search(@Param("terms") Collection<ConnectionRecordSearchTerm> terms,
@Param("sortPredicates") List<ConnectionRecordSortPredicate> sortPredicates,
@Param("limit") int limit);
/**
* Searches for up to <code>limit</code> connection records that contain
* the given terms, sorted by the given predicates. Only records that are
* associated with data explicitly readable by the given user will be
* returned. If records are needed by a system administrator (who, by
* definition, does not need explicit read rights), use search() instead.
*
* @param user
* The user whose permissions should determine whether a record is
* returned.
*
* @param terms
* The search terms that must match 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 results of the search performed with the given parameters.
*/
List<ConnectionRecordModel> searchReadable(@Param("user") UserModel user,
@Param("terms") Collection<ConnectionRecordSearchTerm> terms,
@Param("sortPredicates") List<ConnectionRecordSortPredicate> sortPredicates,
@Param("limit") int limit);

View File

@@ -136,4 +136,80 @@
</select>
<!-- Search for specific connection records -->
<select id="searchReadable" resultMap="ConnectionRecordResultMap">
SELECT
guacamole_connection_history.connection_id,
guacamole_connection_history.user_id,
guacamole_user.username,
guacamole_connection_history.start_date,
guacamole_connection_history.end_date
FROM guacamole_connection_history
JOIN guacamole_connection ON guacamole_connection_history.connection_id = guacamole_connection.connection_id
JOIN guacamole_user ON guacamole_connection_history.user_id = guacamole_user.user_id
<!-- Restrict to readable connections -->
JOIN guacamole_connection_permission ON
guacamole_connection_history.connection_id = guacamole_connection_permission.connection_id
AND guacamole_connection_permission.user_id = #{user.objectID,jdbcType=INTEGER}
AND guacamole_connection_permission.permission = 'READ'
<!-- Restrict to readable users -->
JOIN guacamole_user_permission ON
guacamole_connection_history.user_id = guacamole_user_permission.affected_user_id
AND guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
AND guacamole_user_permission.permission = 'READ'
<!-- Search terms -->
<foreach collection="terms" item="term"
open="WHERE " separator=" AND ">
<bind name="termPattern" value="'%' + term.term + '%'" />
(
guacamole_connection_history.user_id IN (
SELECT user_id
FROM guacamole_user
WHERE username LIKE #{termPattern,jdbcType=VARCHAR}
)
OR guacamole_connection_history.connection_id IN (
SELECT connection_id
FROM guacamole_connection
WHERE connection_name LIKE #{termPattern,jdbcType=VARCHAR}
)
<if test="term.startDate != null and term.endDate != null">
OR (
(start_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
AND (end_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
)
</if>
)
</foreach>
<!-- Bind sort property enum values for sake of readability -->
<bind name="CONNECTION_NAME" value="@org.glyptodon.guacamole.net.auth.ConnectionRecordSet$SortableProperty@CONNECTION_NAME"/>
<bind name="USER_IDENTIFIER" value="@org.glyptodon.guacamole.net.auth.ConnectionRecordSet$SortableProperty@USER_IDENTIFIER"/>
<bind name="START_DATE" value="@org.glyptodon.guacamole.net.auth.ConnectionRecordSet$SortableProperty@START_DATE"/>
<bind name="END_DATE" value="@org.glyptodon.guacamole.net.auth.ConnectionRecordSet$SortableProperty@END_DATE"/>
<!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate"
open="ORDER BY " separator=", ">
<choose>
<when test="sortPredicate.property == CONNECTION_NAME">guacamole_connection.connection_name</when>
<when test="sortPredicate.property == USER_IDENTIFIER">guacamole_user.username</when>
<when test="sortPredicate.property == START_DATE">guacamole_connection_history.start_date</when>
<when test="sortPredicate.property == END_DATE">guacamole_connection_history.end_date</when>
<otherwise>1</otherwise>
</choose>
<if test="sortPredicate.descending">DESC</if>
</foreach>
LIMIT #{limit,jdbcType=INTEGER}
</select>
</mapper>

View File

@@ -136,4 +136,80 @@
</select>
<!-- Search for specific connection records -->
<select id="searchReadable" resultMap="ConnectionRecordResultMap">
SELECT
guacamole_connection_history.connection_id,
guacamole_connection_history.user_id,
guacamole_user.username,
guacamole_connection_history.start_date,
guacamole_connection_history.end_date
FROM guacamole_connection_history
JOIN guacamole_connection ON guacamole_connection_history.connection_id = guacamole_connection.connection_id
JOIN guacamole_user ON guacamole_connection_history.user_id = guacamole_user.user_id
<!-- Restrict to readable connections -->
JOIN guacamole_connection_permission ON
guacamole_connection_history.connection_id = guacamole_connection_permission.connection_id
AND guacamole_connection_permission.user_id = #{user.objectID,jdbcType=INTEGER}
AND guacamole_connection_permission.permission = 'READ'
<!-- Restrict to readable users -->
JOIN guacamole_user_permission ON
guacamole_connection_history.user_id = guacamole_user_permission.affected_user_id
AND guacamole_user_permission.user_id = #{user.objectID,jdbcType=INTEGER}
AND guacamole_user_permission.permission = 'READ'
<!-- Search terms -->
<foreach collection="terms" item="term"
open="WHERE " separator=" AND ">
<bind name="termPattern" value="'%' + term.term + '%'" />
(
guacamole_connection_history.user_id IN (
SELECT user_id
FROM guacamole_user
WHERE username LIKE #{termPattern,jdbcType=VARCHAR}
)
OR guacamole_connection_history.connection_id IN (
SELECT connection_id
FROM guacamole_connection
WHERE connection_name LIKE #{termPattern,jdbcType=VARCHAR}
)
<if test="term.startDate != null and term.endDate != null">
OR (
(start_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
AND (end_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
)
</if>
)
</foreach>
<!-- Bind sort property enum values for sake of readability -->
<bind name="CONNECTION_NAME" value="@org.glyptodon.guacamole.net.auth.ConnectionRecordSet$SortableProperty@CONNECTION_NAME"/>
<bind name="USER_IDENTIFIER" value="@org.glyptodon.guacamole.net.auth.ConnectionRecordSet$SortableProperty@USER_IDENTIFIER"/>
<bind name="START_DATE" value="@org.glyptodon.guacamole.net.auth.ConnectionRecordSet$SortableProperty@START_DATE"/>
<bind name="END_DATE" value="@org.glyptodon.guacamole.net.auth.ConnectionRecordSet$SortableProperty@END_DATE"/>
<!-- Sort predicates -->
<foreach collection="sortPredicates" item="sortPredicate"
open="ORDER BY " separator=", ">
<choose>
<when test="sortPredicate.property == CONNECTION_NAME">guacamole_connection.connection_name</when>
<when test="sortPredicate.property == USER_IDENTIFIER">guacamole_user.username</when>
<when test="sortPredicate.property == START_DATE">guacamole_connection_history.start_date</when>
<when test="sortPredicate.property == END_DATE">guacamole_connection_history.end_date</when>
<otherwise>1</otherwise>
</choose>
<if test="sortPredicate.descending">DESC</if>
</foreach>
LIMIT #{limit,jdbcType=INTEGER}
</select>
</mapper>