mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 21:27:40 +00:00
GUACAMOLE-394: Merge add support for recording user login/logout history to database auth.
This commit is contained in:
@@ -502,6 +502,43 @@ CREATE NONCLUSTERED INDEX [IX_guacamole_connection_history_start_date]
|
||||
|
||||
CREATE NONCLUSTERED INDEX [IX_guacamole_connection_history_end_date]
|
||||
ON [guacamole_connection_history] ([end_date]);
|
||||
|
||||
CREATE NONCLUSTERED INDEX [IX_guacamole_connection_history_connection_id_start_date]
|
||||
ON [guacamole_connection_history] ([connection_id], [start_date]);
|
||||
GO
|
||||
|
||||
--
|
||||
-- User login/logout history
|
||||
--
|
||||
|
||||
CREATE TABLE [guacamole_user_history] (
|
||||
|
||||
[history_id] [int] IDENTITY(1,1) NOT NULL,
|
||||
[user_id] [int] DEFAULT NULL,
|
||||
[username] [nvarchar](128) NOT NULL,
|
||||
[remote_host] [nvarchar](256) DEFAULT NULL,
|
||||
[start_date] [datetime] NOT NULL,
|
||||
[end_date] [datetime] DEFAULT NULL,
|
||||
|
||||
PRIMARY KEY (history_id),
|
||||
|
||||
CONSTRAINT FK_guacamole_user_history_user_id
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES guacamole_user (user_id) ON DELETE SET NULL
|
||||
|
||||
);
|
||||
|
||||
CREATE NONCLUSTERED INDEX [IX_guacamole_user_history_user_id]
|
||||
ON [guacamole_user_history] ([user_id]);
|
||||
|
||||
CREATE NONCLUSTERED INDEX [IX_guacamole_user_history_start_date]
|
||||
ON [guacamole_user_history] ([start_date]);
|
||||
|
||||
CREATE NONCLUSTERED INDEX [IX_guacamole_user_history_end_date]
|
||||
ON [guacamole_user_history] ([end_date]);
|
||||
|
||||
CREATE NONCLUSTERED INDEX [IX_guacamole_user_history_user_id_start_date]
|
||||
ON [guacamole_user_history] ([user_id], [start_date]);
|
||||
GO
|
||||
|
||||
--
|
||||
|
@@ -39,6 +39,7 @@
|
||||
javaType="org.apache.guacamole.net.auth.GuacamoleProxyConfiguration$EncryptionMethod"/>
|
||||
<result column="connection_weight" property="connectionWeight" jdbcType="INTEGER"/>
|
||||
<result column="failover_only" property="failoverOnly" jdbcType="BOOLEAN"/>
|
||||
<result column="last_active" property="lastActive" jdbcType="TIMESTAMP"/>
|
||||
|
||||
<!-- Associated sharing profiles -->
|
||||
<collection property="sharingProfileIdentifiers" resultSet="sharingProfiles" ofType="java.lang.String"
|
||||
@@ -89,8 +90,8 @@
|
||||
resultSets="connections,sharingProfiles">
|
||||
|
||||
SELECT
|
||||
connection_id,
|
||||
connection_name,
|
||||
[guacamole_connection].connection_id,
|
||||
[guacamole_connection].connection_name,
|
||||
parent_id,
|
||||
protocol,
|
||||
max_connections,
|
||||
@@ -99,9 +100,14 @@
|
||||
proxy_port,
|
||||
proxy_encryption_method,
|
||||
connection_weight,
|
||||
failover_only
|
||||
failover_only,
|
||||
(
|
||||
SELECT MAX(start_date)
|
||||
FROM [guacamole_connection_history]
|
||||
WHERE [guacamole_connection_history].connection_id = [guacamole_connection].connection_id
|
||||
) AS last_active
|
||||
FROM [guacamole_connection]
|
||||
WHERE connection_id IN
|
||||
WHERE [guacamole_connection].connection_id IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=INTEGER}
|
||||
@@ -123,7 +129,7 @@
|
||||
|
||||
SELECT
|
||||
[guacamole_connection].connection_id,
|
||||
connection_name,
|
||||
[guacamole_connection].connection_name,
|
||||
parent_id,
|
||||
protocol,
|
||||
max_connections,
|
||||
@@ -132,7 +138,12 @@
|
||||
proxy_port,
|
||||
proxy_encryption_method,
|
||||
connection_weight,
|
||||
failover_only
|
||||
failover_only,
|
||||
(
|
||||
SELECT MAX(start_date)
|
||||
FROM [guacamole_connection_history]
|
||||
WHERE [guacamole_connection_history].connection_id = [guacamole_connection].connection_id
|
||||
) AS last_active
|
||||
FROM [guacamole_connection]
|
||||
JOIN [guacamole_connection_permission] ON [guacamole_connection_permission].connection_id = [guacamole_connection].connection_id
|
||||
WHERE [guacamole_connection].connection_id IN
|
||||
@@ -140,7 +151,7 @@
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=INTEGER}
|
||||
</foreach>
|
||||
AND user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND [guacamole_connection_permission].user_id = #{user.objectID,jdbcType=INTEGER}
|
||||
AND permission = 'READ';
|
||||
|
||||
SELECT primary_connection_id, [guacamole_sharing_profile].sharing_profile_id
|
||||
@@ -160,8 +171,8 @@
|
||||
<select id="selectOneByName" resultMap="ConnectionResultMap">
|
||||
|
||||
SELECT
|
||||
connection_id,
|
||||
connection_name,
|
||||
[guacamole_connection].connection_id,
|
||||
[guacamole_connection].connection_name,
|
||||
parent_id,
|
||||
protocol,
|
||||
max_connections,
|
||||
@@ -170,12 +181,17 @@
|
||||
proxy_port,
|
||||
proxy_encryption_method,
|
||||
connection_weight,
|
||||
failover_only
|
||||
failover_only,
|
||||
(
|
||||
SELECT MAX(start_date)
|
||||
FROM [guacamole_connection_history]
|
||||
WHERE [guacamole_connection_history].connection_id = [guacamole_connection].connection_id
|
||||
) AS last_active
|
||||
FROM [guacamole_connection]
|
||||
WHERE
|
||||
<if test="parentIdentifier != null">parent_id = #{parentIdentifier,jdbcType=INTEGER}</if>
|
||||
<if test="parentIdentifier == null">parent_id IS NULL</if>
|
||||
AND connection_name = #{name,jdbcType=VARCHAR}
|
||||
AND [guacamole_connection].connection_name = #{name,jdbcType=VARCHAR}
|
||||
|
||||
</select>
|
||||
|
||||
|
@@ -41,6 +41,7 @@
|
||||
<result column="email_address" property="emailAddress" jdbcType="VARCHAR"/>
|
||||
<result column="organization" property="organization" jdbcType="VARCHAR"/>
|
||||
<result column="organizational_role" property="organizationalRole" jdbcType="VARCHAR"/>
|
||||
<result column="last_active" property="lastActive" jdbcType="TIMESTAMP"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- Select all usernames -->
|
||||
@@ -63,8 +64,8 @@
|
||||
<select id="select" resultMap="UserResultMap">
|
||||
|
||||
SELECT
|
||||
user_id,
|
||||
username,
|
||||
[guacamole_user].user_id,
|
||||
[guacamole_user].username,
|
||||
password_hash,
|
||||
password_salt,
|
||||
password_date,
|
||||
@@ -78,13 +79,18 @@
|
||||
full_name,
|
||||
email_address,
|
||||
organization,
|
||||
organizational_role
|
||||
organizational_role,
|
||||
(
|
||||
SELECT MAX(start_date)
|
||||
FROM [guacamole_user_history]
|
||||
WHERE [guacamole_user_history].user_id = [guacamole_user].user_id
|
||||
) AS last_active
|
||||
FROM [guacamole_user]
|
||||
WHERE username IN
|
||||
WHERE [guacamole_user].username IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
</foreach>
|
||||
</foreach>;
|
||||
|
||||
</select>
|
||||
|
||||
@@ -93,7 +99,7 @@
|
||||
|
||||
SELECT
|
||||
[guacamole_user].user_id,
|
||||
username,
|
||||
[guacamole_user].username,
|
||||
password_hash,
|
||||
password_salt,
|
||||
password_date,
|
||||
@@ -107,10 +113,15 @@
|
||||
full_name,
|
||||
email_address,
|
||||
organization,
|
||||
organizational_role
|
||||
organizational_role,
|
||||
(
|
||||
SELECT MAX(start_date)
|
||||
FROM [guacamole_user_history]
|
||||
WHERE [guacamole_user_history].user_id = [guacamole_user].user_id
|
||||
) AS last_active
|
||||
FROM [guacamole_user]
|
||||
JOIN [guacamole_user_permission] ON affected_user_id = [guacamole_user].user_id
|
||||
WHERE username IN
|
||||
WHERE [guacamole_user].username IN
|
||||
<foreach collection="identifiers" item="identifier"
|
||||
open="(" separator="," close=")">
|
||||
#{identifier,jdbcType=VARCHAR}
|
||||
@@ -124,8 +135,8 @@
|
||||
<select id="selectOne" resultMap="UserResultMap">
|
||||
|
||||
SELECT
|
||||
user_id,
|
||||
username,
|
||||
[guacamole_user].user_id,
|
||||
[guacamole_user].username,
|
||||
password_hash,
|
||||
password_salt,
|
||||
password_date,
|
||||
@@ -139,10 +150,16 @@
|
||||
full_name,
|
||||
email_address,
|
||||
organization,
|
||||
organizational_role
|
||||
organizational_role,
|
||||
(
|
||||
SELECT MAX(start_date)
|
||||
FROM [guacamole_user_history]
|
||||
WHERE [guacamole_user_history].user_id = [guacamole_user].user_id
|
||||
) AS last_active
|
||||
FROM [guacamole_user]
|
||||
LEFT JOIN [guacamole_user_history] ON [guacamole_user_history].user_id = [guacamole_user].user_id
|
||||
WHERE
|
||||
username = #{username,jdbcType=VARCHAR}
|
||||
[guacamole_user].username = #{username,jdbcType=VARCHAR}
|
||||
|
||||
</select>
|
||||
|
||||
|
@@ -0,0 +1,187 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<mapper namespace="org.apache.guacamole.auth.jdbc.user.UserRecordMapper" >
|
||||
|
||||
<!-- Result mapper for system permissions -->
|
||||
<resultMap id="UserRecordResultMap" type="org.apache.guacamole.auth.jdbc.base.ActivityRecordModel">
|
||||
<id column="history_id" property="recordID" jdbcType="INTEGER"/>
|
||||
<result column="remote_host" property="remoteHost" jdbcType="VARCHAR"/>
|
||||
<result column="user_id" property="userID" jdbcType="INTEGER"/>
|
||||
<result column="username" property="username" jdbcType="VARCHAR"/>
|
||||
<result column="start_date" property="startDate" jdbcType="TIMESTAMP"/>
|
||||
<result column="end_date" property="endDate" jdbcType="TIMESTAMP"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- Select all user records from a given user -->
|
||||
<select id="select" resultMap="UserRecordResultMap">
|
||||
|
||||
SELECT
|
||||
[guacamole_user_history].remote_host,
|
||||
[guacamole_user_history].user_id,
|
||||
[guacamole_user_history].username,
|
||||
[guacamole_user_history].start_date,
|
||||
[guacamole_user_history].end_date
|
||||
FROM [guacamole_user_history]
|
||||
JOIN [guacamole_user] ON [guacamole_user_history].user_id = [guacamole_user].user_id
|
||||
WHERE
|
||||
[guacamole_user].username = #{username,jdbcType=VARCHAR}
|
||||
ORDER BY
|
||||
[guacamole_user_history].start_date DESC,
|
||||
[guacamole_user_history].end_date DESC
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Insert the given user record -->
|
||||
<insert id="insert" useGeneratedKeys="true" keyProperty="record.recordID"
|
||||
parameterType="org.apache.guacamole.auth.jdbc.base.ActivityRecordModel">
|
||||
|
||||
INSERT INTO [guacamole_user_history] (
|
||||
remote_host,
|
||||
user_id,
|
||||
username,
|
||||
start_date,
|
||||
end_date
|
||||
)
|
||||
VALUES (
|
||||
#{record.remoteHost,jdbcType=VARCHAR},
|
||||
(SELECT user_id FROM [guacamole_user]
|
||||
WHERE username = #{record.username,jdbcType=VARCHAR}),
|
||||
#{record.username,jdbcType=VARCHAR},
|
||||
#{record.startDate,jdbcType=TIMESTAMP},
|
||||
#{record.endDate,jdbcType=TIMESTAMP}
|
||||
)
|
||||
|
||||
</insert>
|
||||
|
||||
<!-- Update the given user record -->
|
||||
<update id="update" parameterType="org.apache.guacamole.auth.jdbc.base.ActivityRecordModel">
|
||||
UPDATE [guacamole_user_history]
|
||||
SET remote_host = #{record.remoteHost,jdbcType=VARCHAR},
|
||||
user_id = (SELECT user_id FROM [guacamole_user]
|
||||
WHERE username = #{record.username,jdbcType=VARCHAR}),
|
||||
username = #{record.username,jdbcType=VARCHAR},
|
||||
start_date = #{record.startDate,jdbcType=TIMESTAMP},
|
||||
end_date = #{record.endDate,jdbcType=TIMESTAMP}
|
||||
WHERE history_id = #{record.recordID,jdbcType=INTEGER}
|
||||
</update>
|
||||
|
||||
<!-- Search for specific user records -->
|
||||
<select id="search" resultMap="UserRecordResultMap">
|
||||
|
||||
SELECT
|
||||
[guacamole_user_history].remote_host,
|
||||
[guacamole_user_history].user_id,
|
||||
[guacamole_user_history].username,
|
||||
[guacamole_user_history].start_date,
|
||||
[guacamole_user_history].end_date
|
||||
FROM [guacamole_user_history]
|
||||
|
||||
<!-- Search terms -->
|
||||
<foreach collection="terms" item="term"
|
||||
open="WHERE " separator=" AND ">
|
||||
(
|
||||
|
||||
[guacamole_user_history].user_id IN (
|
||||
SELECT user_id
|
||||
FROM [guacamole_user]
|
||||
WHERE POSITION(#{term.term,jdbcType=VARCHAR} IN username) > 0
|
||||
)
|
||||
|
||||
<if test="term.startDate != null and term.endDate != null">
|
||||
OR start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP}
|
||||
</if>
|
||||
|
||||
)
|
||||
</foreach>
|
||||
|
||||
<!-- Bind sort property enum values for sake of readability -->
|
||||
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
|
||||
|
||||
<!-- Sort predicates -->
|
||||
<foreach collection="sortPredicates" item="sortPredicate"
|
||||
open="ORDER BY " separator=", ">
|
||||
<choose>
|
||||
<when test="sortPredicate.property == START_DATE">[guacamole_user_history].start_date</when>
|
||||
<otherwise>1</otherwise>
|
||||
</choose>
|
||||
<if test="sortPredicate.descending">DESC</if>
|
||||
</foreach>
|
||||
|
||||
LIMIT #{limit,jdbcType=INTEGER}
|
||||
|
||||
</select>
|
||||
|
||||
<!-- Search for specific user records -->
|
||||
<select id="searchReadable" resultMap="UserRecordResultMap">
|
||||
|
||||
SELECT
|
||||
[guacamole_user_history].remote_host,
|
||||
[guacamole_user_history].user_id,
|
||||
[guacamole_user_history].username,
|
||||
[guacamole_user_history].start_date,
|
||||
[guacamole_user_history].end_date
|
||||
FROM [guacamole_user_history]
|
||||
|
||||
<!-- Restrict to readable users -->
|
||||
JOIN [guacamole_user_permission] ON
|
||||
[guacamole_user_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 ">
|
||||
(
|
||||
|
||||
[guacamole_user_history].user_id IN (
|
||||
SELECT user_id
|
||||
FROM [guacamole_user]
|
||||
WHERE POSITION(#{term.term,jdbcType=VARCHAR} IN username) > 0
|
||||
)
|
||||
|
||||
<if test="term.startDate != null and term.endDate != null">
|
||||
OR start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP}
|
||||
</if>
|
||||
|
||||
)
|
||||
</foreach>
|
||||
|
||||
<!-- Bind sort property enum values for sake of readability -->
|
||||
<bind name="START_DATE" value="@org.apache.guacamole.net.auth.ActivityRecordSet$SortableProperty@START_DATE"/>
|
||||
|
||||
<!-- Sort predicates -->
|
||||
<foreach collection="sortPredicates" item="sortPredicate"
|
||||
open="ORDER BY " separator=", ">
|
||||
<choose>
|
||||
<when test="sortPredicate.property == START_DATE">[guacamole_user_history].start_date</when>
|
||||
<otherwise>1</otherwise>
|
||||
</choose>
|
||||
<if test="sortPredicate.descending">DESC</if>
|
||||
</foreach>
|
||||
|
||||
LIMIT #{limit,jdbcType=INTEGER}
|
||||
|
||||
</select>
|
||||
|
||||
</mapper>
|
Reference in New Issue
Block a user