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:
@@ -76,6 +76,7 @@ import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileParameterMapp
|
||||
import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileService;
|
||||
import org.apache.guacamole.auth.jdbc.tunnel.RestrictedGuacamoleTunnelService;
|
||||
import org.apache.guacamole.auth.jdbc.user.PasswordRecordMapper;
|
||||
import org.apache.guacamole.auth.jdbc.user.UserRecordMapper;
|
||||
import org.mybatis.guice.MyBatisModule;
|
||||
import org.mybatis.guice.datasource.builtin.PooledDataSourceProvider;
|
||||
|
||||
@@ -126,6 +127,7 @@ public class JDBCAuthenticationProviderModule extends MyBatisModule {
|
||||
addMapperClass(SharingProfilePermissionMapper.class);
|
||||
addMapperClass(UserMapper.class);
|
||||
addMapperClass(UserPermissionMapper.class);
|
||||
addMapperClass(UserRecordMapper.class);
|
||||
|
||||
// Bind core implementations of guacamole-ext classes
|
||||
bind(ActiveConnectionDirectory.class);
|
||||
|
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.jdbc.base;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* A single activity record representing an arbitrary activity performed by a
|
||||
* user.
|
||||
*/
|
||||
public class ActivityRecordModel {
|
||||
|
||||
/**
|
||||
* The ID of this object in the database, if any.
|
||||
*/
|
||||
private Integer recordID;
|
||||
|
||||
/**
|
||||
* The database ID of the user associated with this activity record.
|
||||
*/
|
||||
private Integer userID;
|
||||
|
||||
/**
|
||||
* The username of the user that performed the activity.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* The remote host associated with the user that performed the activity.
|
||||
*/
|
||||
private String remoteHost;
|
||||
|
||||
/**
|
||||
* The time the activity was initiated by the associated user.
|
||||
*/
|
||||
private Date startDate;
|
||||
|
||||
/**
|
||||
* The time the activity ended, or null if the end time is not known or
|
||||
* the activity is still in progress.
|
||||
*/
|
||||
private Date endDate;
|
||||
|
||||
/**
|
||||
* Returns the ID of this record in the database, if it exists.
|
||||
*
|
||||
* @return
|
||||
* The ID of this record in the database, or null if this record was
|
||||
* not retrieved from the database.
|
||||
*/
|
||||
public Integer getRecordID() {
|
||||
return recordID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database ID of this record to the given value.
|
||||
*
|
||||
* @param recordID
|
||||
* The ID to assign to this object.
|
||||
*/
|
||||
public void setRecordID(Integer recordID) {
|
||||
this.recordID = recordID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database ID of the user associated with this activity
|
||||
* record.
|
||||
*
|
||||
* @return
|
||||
* The database ID of the user associated with this activity record.
|
||||
*/
|
||||
public Integer getUserID() {
|
||||
return userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database ID of the user associated with this activity record.
|
||||
*
|
||||
* @param userID
|
||||
* The database ID of the user to associate with this activity
|
||||
* record.
|
||||
*/
|
||||
public void setUserID(Integer userID) {
|
||||
this.userID = userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the username of the user that performed the activity associated
|
||||
* with this record.
|
||||
*
|
||||
* @return
|
||||
* The username of the user that performed the activity associated with
|
||||
* this record.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the username of the user that performed the activity associated
|
||||
* with this record.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user that performed the activity associated with
|
||||
* this record.
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remote host associated with the user that performed the
|
||||
* activity.
|
||||
*
|
||||
* @return
|
||||
* The remote host associated with the user that performed the activity.
|
||||
*/
|
||||
public String getRemoteHost() {
|
||||
return remoteHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the remote host associated with the user that performed the
|
||||
* activity.
|
||||
*
|
||||
* @param remoteHost
|
||||
* The remote host associated with the user that performed the activity.
|
||||
*/
|
||||
public void setRemoteHost(String remoteHost) {
|
||||
this.remoteHost = remoteHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time the activity was initiated by the associated user.
|
||||
*
|
||||
* @return
|
||||
* The time the activity was initiated by the associated user.
|
||||
*/
|
||||
public Date getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time the activity was initiated by the associated user.
|
||||
*
|
||||
* @param startDate
|
||||
* The time the activity was initiated by the associated user.
|
||||
*/
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the time the activity ended, or null if the end time is not
|
||||
* known or the activity is still in progress.
|
||||
*
|
||||
* @return
|
||||
* The time the activity ended, or null if the end time is not known or
|
||||
* the activity is still in progress.
|
||||
*/
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time the activity ended, if known.
|
||||
*
|
||||
* @param endDate
|
||||
* The time the activity ended, or null if the end time is not known or
|
||||
* the activity is still in progress.
|
||||
*/
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
}
|
@@ -17,7 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.jdbc.connection;
|
||||
package org.apache.guacamole.auth.jdbc.base;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
@@ -25,11 +25,11 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A search term for querying historical connection records. This will contain
|
||||
* a the search term in string form and, if that string appears to be a date. a
|
||||
* corresponding date range.
|
||||
* A search term for querying historical records of arbitrary activities. This
|
||||
* will contain a the search term in string form and, if that string appears to
|
||||
* be a date. a corresponding date range.
|
||||
*/
|
||||
public class ConnectionRecordSearchTerm {
|
||||
public class ActivityRecordSearchTerm {
|
||||
|
||||
/**
|
||||
* A pattern that can match a year, year and month, or year and month and
|
||||
@@ -180,7 +180,7 @@ public class ConnectionRecordSearchTerm {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ConnectionRecordSearchTerm representing the given string.
|
||||
* Creates a new ActivityRecordSearchTerm representing the given string.
|
||||
* If the given string appears to be a date, the start and end dates of the
|
||||
* implied date range will be automatically determined and made available
|
||||
* via getStartDate() and getEndDate() respectively.
|
||||
@@ -188,7 +188,7 @@ public class ConnectionRecordSearchTerm {
|
||||
* @param term
|
||||
* The string that should be searched for.
|
||||
*/
|
||||
public ConnectionRecordSearchTerm(String term) {
|
||||
public ActivityRecordSearchTerm(String term) {
|
||||
|
||||
// Search terms absolutely must not be null
|
||||
if (term == null)
|
||||
@@ -281,10 +281,10 @@ public class ConnectionRecordSearchTerm {
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (obj == null || !(obj instanceof ConnectionRecordSearchTerm))
|
||||
if (obj == null || !(obj instanceof ActivityRecordSearchTerm))
|
||||
return false;
|
||||
|
||||
return ((ConnectionRecordSearchTerm) obj).getTerm().equals(getTerm());
|
||||
return ((ActivityRecordSearchTerm) obj).getTerm().equals(getTerm());
|
||||
|
||||
}
|
||||
|
@@ -17,18 +17,18 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.jdbc.connection;
|
||||
package org.apache.guacamole.auth.jdbc.base;
|
||||
|
||||
import org.apache.guacamole.net.auth.ActivityRecordSet;
|
||||
|
||||
/**
|
||||
* A sort predicate which species the property to use when sorting connection
|
||||
* A sort predicate which species the property to use when sorting activity
|
||||
* records, along with the sort order.
|
||||
*/
|
||||
public class ConnectionRecordSortPredicate {
|
||||
public class ActivityRecordSortPredicate {
|
||||
|
||||
/**
|
||||
* The property to use when sorting ConnectionRecords.
|
||||
* The property to use when sorting ActivityRecords.
|
||||
*/
|
||||
private final ActivityRecordSet.SortableProperty property;
|
||||
|
||||
@@ -38,26 +38,26 @@ public class ConnectionRecordSortPredicate {
|
||||
private final boolean descending;
|
||||
|
||||
/**
|
||||
* Creates a new ConnectionRecordSortPredicate with the given sort property
|
||||
* Creates a new ActivityRecordSortPredicate with the given sort property
|
||||
* and sort order.
|
||||
*
|
||||
* @param property
|
||||
* The property to use when sorting ConnectionRecords.
|
||||
* The property to use when sorting ActivityRecords.
|
||||
*
|
||||
* @param descending
|
||||
* Whether the sort order is descending (true) or ascending (false).
|
||||
*/
|
||||
public ConnectionRecordSortPredicate(ActivityRecordSet.SortableProperty property,
|
||||
public ActivityRecordSortPredicate(ActivityRecordSet.SortableProperty property,
|
||||
boolean descending) {
|
||||
this.property = property;
|
||||
this.descending = descending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property that should be used when sorting ConnectionRecords.
|
||||
* Returns the property that should be used when sorting ActivityRecords.
|
||||
*
|
||||
* @return
|
||||
* The property that should be used when sorting ConnectionRecords.
|
||||
* The property that should be used when sorting ActivityRecords.
|
||||
*/
|
||||
public ActivityRecordSet.SortableProperty getProperty() {
|
||||
return property;
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.jdbc.base;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
import org.apache.guacamole.net.auth.ActivityRecord;
|
||||
|
||||
/**
|
||||
* An ActivityRecord which is backed by a database model.
|
||||
*/
|
||||
public class ModeledActivityRecord implements ActivityRecord {
|
||||
|
||||
/**
|
||||
* The model object backing this activity record.
|
||||
*/
|
||||
private final ActivityRecordModel model;
|
||||
|
||||
/**
|
||||
* 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 model
|
||||
* The model object to use to back this activity record.
|
||||
*/
|
||||
public ModeledActivityRecord(ActivityRecordModel model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getStartDate() {
|
||||
return model.getStartDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getEndDate() {
|
||||
return model.getEndDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteHost() {
|
||||
return model.getRemoteHost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return model.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.jdbc.base;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.net.auth.ActivityRecord;
|
||||
import org.apache.guacamole.net.auth.ActivityRecordSet;
|
||||
import org.apache.guacamole.net.auth.ActivityRecordSet.SortableProperty;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
|
||||
/**
|
||||
* A JDBC implementation of ActivityRecordSet. Calls to asCollection() will
|
||||
* query history records using an implementation-specific mechanism. Which
|
||||
* records are returned will be determined by the values passed in earlier.
|
||||
*
|
||||
* @param <RecordType>
|
||||
* The type of ActivityRecord contained within this set.
|
||||
*/
|
||||
public abstract class ModeledActivityRecordSet<RecordType extends ActivityRecord>
|
||||
extends RestrictedObject implements ActivityRecordSet<RecordType> {
|
||||
|
||||
/**
|
||||
* The set of strings that each must occur somewhere within the returned
|
||||
* records, whether within the associated username, an associated date, or
|
||||
* other related data. If non-empty, any record not matching each of the
|
||||
* strings within the collection will be excluded from the results.
|
||||
*/
|
||||
private final Set<ActivityRecordSearchTerm> requiredContents =
|
||||
new HashSet<ActivityRecordSearchTerm>();
|
||||
|
||||
/**
|
||||
* The maximum number of history records that should be returned by a call
|
||||
* to asCollection().
|
||||
*/
|
||||
private int limit = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* A list of predicates to apply while sorting the resulting records,
|
||||
* describing the properties involved and the sort order for those
|
||||
* properties.
|
||||
*/
|
||||
private final List<ActivityRecordSortPredicate> sortPredicates =
|
||||
new ArrayList<ActivityRecordSortPredicate>();
|
||||
|
||||
/**
|
||||
* Retrieves the history records matching the given criteria. Retrieves up
|
||||
* to <code>limit</code> 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 user
|
||||
* The user retrieving the 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
|
||||
* A collection of all history records matching the given criteria.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If permission to read the history records is denied.
|
||||
*/
|
||||
protected abstract Collection<RecordType> retrieveHistory(
|
||||
AuthenticatedUser user,
|
||||
Set<ActivityRecordSearchTerm> requiredContents,
|
||||
List<ActivityRecordSortPredicate> sortPredicates,
|
||||
int limit) throws GuacamoleException;
|
||||
|
||||
@Override
|
||||
public Collection<RecordType> asCollection()
|
||||
throws GuacamoleException {
|
||||
return retrieveHistory(getCurrentUser(), requiredContents,
|
||||
sortPredicates, limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModeledActivityRecordSet<RecordType> contains(String value)
|
||||
throws GuacamoleException {
|
||||
requiredContents.add(new ActivityRecordSearchTerm(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModeledActivityRecordSet<RecordType> limit(int limit) throws GuacamoleException {
|
||||
this.limit = Math.min(this.limit, limit);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModeledActivityRecordSet<RecordType> sort(SortableProperty property, boolean desc)
|
||||
throws GuacamoleException {
|
||||
|
||||
sortPredicates.add(new ActivityRecordSortPredicate(
|
||||
property,
|
||||
desc
|
||||
));
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -19,6 +19,7 @@
|
||||
|
||||
package org.apache.guacamole.auth.jdbc.connection;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.apache.guacamole.auth.jdbc.base.ChildObjectModel;
|
||||
@@ -92,6 +93,12 @@ public class ConnectionModel extends ChildObjectModel {
|
||||
*/
|
||||
private EncryptionMethod proxyEncryptionMethod;
|
||||
|
||||
/**
|
||||
* The date and time that this connection was last used, or null if this
|
||||
* connection has never been used.
|
||||
*/
|
||||
private Date lastActive;
|
||||
|
||||
/**
|
||||
* Creates a new, empty connection.
|
||||
*/
|
||||
@@ -341,6 +348,32 @@ public class ConnectionModel extends ChildObjectModel {
|
||||
this.sharingProfileIdentifiers = sharingProfileIdentifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date and time that this connection was last used, or null if
|
||||
* this connection has never been used.
|
||||
*
|
||||
* @return
|
||||
* The date and time that this connection was last used, or null if this
|
||||
* connection has never been used.
|
||||
*/
|
||||
public Date getLastActive() {
|
||||
return lastActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date and time that this connection was last used. This value is
|
||||
* expected to be set automatically via queries, derived from connection
|
||||
* history records. It does NOT correspond to an actual column, and values
|
||||
* set manually through invoking this function will not persist.
|
||||
*
|
||||
* @param lastActive
|
||||
* The date and time that this connection was last used, or null if this
|
||||
* connection has never been used.
|
||||
*/
|
||||
public void setLastActive(Date lastActive) {
|
||||
this.lastActive = lastActive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
|
||||
|
@@ -21,6 +21,8 @@ package org.apache.guacamole.auth.jdbc.connection;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.guacamole.auth.jdbc.user.UserModel;
|
||||
|
||||
@@ -75,8 +77,8 @@ public interface ConnectionRecordMapper {
|
||||
* @return
|
||||
* The results of the search performed with the given parameters.
|
||||
*/
|
||||
List<ConnectionRecordModel> search(@Param("terms") Collection<ConnectionRecordSearchTerm> terms,
|
||||
@Param("sortPredicates") List<ConnectionRecordSortPredicate> sortPredicates,
|
||||
List<ConnectionRecordModel> search(@Param("terms") Collection<ActivityRecordSearchTerm> terms,
|
||||
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
|
||||
@Param("limit") int limit);
|
||||
|
||||
/**
|
||||
@@ -104,8 +106,8 @@ public interface ConnectionRecordMapper {
|
||||
* 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("terms") Collection<ActivityRecordSearchTerm> terms,
|
||||
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
|
||||
@Param("limit") int limit);
|
||||
|
||||
}
|
||||
|
@@ -19,14 +19,14 @@
|
||||
|
||||
package org.apache.guacamole.auth.jdbc.connection;
|
||||
|
||||
import java.util.Date;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordModel;
|
||||
|
||||
/**
|
||||
* A single connection record representing a past usage of a particular
|
||||
* connection. If the connection was being shared, the sharing profile used to
|
||||
* join the connection is included in the record.
|
||||
*/
|
||||
public class ConnectionRecordModel {
|
||||
public class ConnectionRecordModel extends ActivityRecordModel {
|
||||
|
||||
/**
|
||||
* The identifier of the connection associated with this connection record.
|
||||
@@ -53,32 +53,6 @@ public class ConnectionRecordModel {
|
||||
*/
|
||||
private String sharingProfileName;
|
||||
|
||||
/**
|
||||
* The database ID of the user associated with this connection record.
|
||||
*/
|
||||
private Integer userID;
|
||||
|
||||
/**
|
||||
* The username of the user associated with this connection record.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* The remote host associated with this connection record.
|
||||
*/
|
||||
private String remoteHost;
|
||||
|
||||
/**
|
||||
* The time the connection was initiated by the associated user.
|
||||
*/
|
||||
private Date startDate;
|
||||
|
||||
/**
|
||||
* The time the connection ended, or null if the end time is not known or
|
||||
* the connection is still running.
|
||||
*/
|
||||
private Date endDate;
|
||||
|
||||
/**
|
||||
* Returns the identifier of the connection associated with this connection
|
||||
* record.
|
||||
@@ -179,109 +153,4 @@ public class ConnectionRecordModel {
|
||||
this.sharingProfileName = sharingProfileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database ID of the user associated with this connection
|
||||
* record.
|
||||
*
|
||||
* @return
|
||||
* The database ID of the user associated with this connection record.
|
||||
*/
|
||||
public Integer getUserID() {
|
||||
return userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database ID of the user associated with this connection record.
|
||||
*
|
||||
* @param userID
|
||||
* The database ID of the user to associate with this connection
|
||||
* record.
|
||||
*/
|
||||
public void setUserID(Integer userID) {
|
||||
this.userID = userID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the username of the user associated with this connection record.
|
||||
*
|
||||
* @return
|
||||
* The username of the user associated with this connection record.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the username of the user associated with this connection record.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user to associate with this connection record.
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remote host associated with this connection record.
|
||||
*
|
||||
* @return
|
||||
* The remote host associated with this connection record.
|
||||
*/
|
||||
public String getRemoteHost() {
|
||||
return remoteHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the remote host associated with this connection record.
|
||||
*
|
||||
* @param remoteHost
|
||||
* The remote host to associate with this connection record.
|
||||
*/
|
||||
public void setRemoteHost(String remoteHost) {
|
||||
this.remoteHost = remoteHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date that the associated connection was established.
|
||||
*
|
||||
* @return
|
||||
* The date the associated connection was established.
|
||||
*/
|
||||
public Date getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date that the associated connection was established.
|
||||
*
|
||||
* @param startDate
|
||||
* The date that the associated connection was established.
|
||||
*/
|
||||
public void setStartDate(Date startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date that the associated connection ended, or null if no
|
||||
* end date was recorded. The lack of an end date does not necessarily
|
||||
* mean that the connection is still active.
|
||||
*
|
||||
* @return
|
||||
* The date the associated connection ended, or null if no end date was
|
||||
* recorded.
|
||||
*/
|
||||
public Date getEndDate() {
|
||||
return endDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date that the associated connection ended.
|
||||
*
|
||||
* @param endDate
|
||||
* The date that the associated connection ended.
|
||||
*/
|
||||
public void setEndDate(Date endDate) {
|
||||
this.endDate = endDate;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -20,15 +20,14 @@
|
||||
package org.apache.guacamole.auth.jdbc.connection;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
|
||||
import org.apache.guacamole.net.auth.ActivityRecordSet;
|
||||
import org.apache.guacamole.net.auth.ActivityRecordSet.SortableProperty;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
||||
import org.apache.guacamole.auth.jdbc.base.ModeledActivityRecordSet;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
import org.apache.guacamole.net.auth.ConnectionRecord;
|
||||
|
||||
/**
|
||||
@@ -36,8 +35,7 @@ import org.apache.guacamole.net.auth.ConnectionRecord;
|
||||
* asCollection() will query connection history records from the database. Which
|
||||
* records are returned will be determined by the values passed in earlier.
|
||||
*/
|
||||
public class ConnectionRecordSet extends RestrictedObject
|
||||
implements ActivityRecordSet<ConnectionRecord> {
|
||||
public class ConnectionRecordSet extends ModeledActivityRecordSet<ConnectionRecord> {
|
||||
|
||||
/**
|
||||
* Service for managing connection objects.
|
||||
@@ -45,60 +43,15 @@ public class ConnectionRecordSet extends RestrictedObject
|
||||
@Inject
|
||||
private ConnectionService connectionService;
|
||||
|
||||
/**
|
||||
* The set of strings that each must occur somewhere within the returned
|
||||
* connection records, whether within the associated username, the name of
|
||||
* the associated connection, or any associated date. If non-empty, any
|
||||
* connection record not matching each of the strings within the collection
|
||||
* will be excluded from the results.
|
||||
*/
|
||||
private final Set<ConnectionRecordSearchTerm> requiredContents =
|
||||
new HashSet<ConnectionRecordSearchTerm>();
|
||||
|
||||
/**
|
||||
* The maximum number of connection history records that should be returned
|
||||
* by a call to asCollection().
|
||||
*/
|
||||
private int limit = Integer.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* A list of predicates to apply while sorting the resulting connection
|
||||
* records, describing the properties involved and the sort order for those
|
||||
* properties.
|
||||
*/
|
||||
private final List<ConnectionRecordSortPredicate> connectionRecordSortPredicates =
|
||||
new ArrayList<ConnectionRecordSortPredicate>();
|
||||
|
||||
@Override
|
||||
public Collection<ConnectionRecord> asCollection()
|
||||
protected Collection<ConnectionRecord> retrieveHistory(
|
||||
AuthenticatedUser user, Set<ActivityRecordSearchTerm> requiredContents,
|
||||
List<ActivityRecordSortPredicate> sortPredicates, int limit)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Retrieve history from database
|
||||
return connectionService.retrieveHistory(getCurrentUser(),
|
||||
requiredContents, connectionRecordSortPredicates, limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionRecordSet contains(String value)
|
||||
throws GuacamoleException {
|
||||
requiredContents.add(new ConnectionRecordSearchTerm(value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionRecordSet limit(int limit) throws GuacamoleException {
|
||||
this.limit = Math.min(this.limit, limit);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConnectionRecordSet sort(SortableProperty property, boolean desc)
|
||||
throws GuacamoleException {
|
||||
|
||||
connectionRecordSortPredicates.add(new ConnectionRecordSortPredicate(
|
||||
property,
|
||||
desc
|
||||
));
|
||||
|
||||
return this;
|
||||
requiredContents, sortPredicates, limit);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -34,6 +34,8 @@ import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
|
||||
import org.apache.guacamole.GuacamoleClientException;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleSecurityException;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
||||
import org.apache.guacamole.auth.jdbc.base.ModeledChildDirectoryObjectService;
|
||||
import org.apache.guacamole.auth.jdbc.permission.ConnectionPermissionMapper;
|
||||
import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
|
||||
@@ -460,8 +462,8 @@ public class ConnectionService extends ModeledChildDirectoryObjectService<Modele
|
||||
* If permission to read the connection history is denied.
|
||||
*/
|
||||
public List<ConnectionRecord> retrieveHistory(ModeledAuthenticatedUser user,
|
||||
Collection<ConnectionRecordSearchTerm> requiredContents,
|
||||
List<ConnectionRecordSortPredicate> sortPredicates, int limit)
|
||||
Collection<ActivityRecordSearchTerm> requiredContents,
|
||||
List<ActivityRecordSortPredicate> sortPredicates, int limit)
|
||||
throws GuacamoleException {
|
||||
|
||||
List<ConnectionRecordModel> searchResults;
|
||||
|
@@ -235,7 +235,7 @@ public class ModeledConnection extends ModeledChildDirectoryObject<ConnectionMod
|
||||
|
||||
@Override
|
||||
public Date getLastActive() {
|
||||
return null;
|
||||
return getModel().getLastActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -20,13 +20,14 @@
|
||||
package org.apache.guacamole.auth.jdbc.connection;
|
||||
|
||||
|
||||
import java.util.Date;
|
||||
import org.apache.guacamole.auth.jdbc.base.ModeledActivityRecord;
|
||||
import org.apache.guacamole.net.auth.ConnectionRecord;
|
||||
|
||||
/**
|
||||
* A ConnectionRecord which is backed by a database model.
|
||||
*/
|
||||
public class ModeledConnectionRecord implements ConnectionRecord {
|
||||
public class ModeledConnectionRecord extends ModeledActivityRecord
|
||||
implements ConnectionRecord {
|
||||
|
||||
/**
|
||||
* The model object backing this connection record.
|
||||
@@ -42,6 +43,7 @@ public class ModeledConnectionRecord implements ConnectionRecord {
|
||||
* The model object to use to back this connection record.
|
||||
*/
|
||||
public ModeledConnectionRecord(ConnectionRecordModel model) {
|
||||
super(model);
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
@@ -65,29 +67,4 @@ public class ModeledConnectionRecord implements ConnectionRecord {
|
||||
return model.getSharingProfileName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getStartDate() {
|
||||
return model.getStartDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getEndDate() {
|
||||
return model.getEndDate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteHost() {
|
||||
return model.getRemoteHost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return model.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -144,6 +144,12 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
|
||||
ACCOUNT_RESTRICTIONS
|
||||
));
|
||||
|
||||
/**
|
||||
* Service for managing users.
|
||||
*/
|
||||
@Inject
|
||||
private UserService userService;
|
||||
|
||||
/**
|
||||
* Service for hashing passwords.
|
||||
*/
|
||||
@@ -795,13 +801,13 @@ public class ModeledUser extends ModeledDirectoryObject<UserModel> implements Us
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getLastActive() {
|
||||
return null;
|
||||
public Timestamp getLastActive() {
|
||||
return getModel().getLastActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActivityRecord> getHistory() throws GuacamoleException {
|
||||
return Collections.<ActivityRecord>emptyList();
|
||||
return userService.retrieveHistory(getCurrentUser(), this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -26,9 +26,11 @@ import org.apache.guacamole.auth.jdbc.connection.ConnectionDirectory;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
|
||||
import org.apache.guacamole.auth.jdbc.activeconnection.ActiveConnectionDirectory;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordModel;
|
||||
import org.apache.guacamole.auth.jdbc.connection.ConnectionRecordSet;
|
||||
import org.apache.guacamole.auth.jdbc.connection.ModeledConnection;
|
||||
import org.apache.guacamole.auth.jdbc.connectiongroup.ModeledConnectionGroup;
|
||||
@@ -44,7 +46,6 @@ import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||
import org.apache.guacamole.net.auth.Directory;
|
||||
import org.apache.guacamole.net.auth.SharingProfile;
|
||||
import org.apache.guacamole.net.auth.User;
|
||||
import org.apache.guacamole.net.auth.simple.SimpleActivityRecordSet;
|
||||
|
||||
/**
|
||||
* UserContext implementation which is driven by an arbitrary, underlying
|
||||
@@ -99,7 +100,24 @@ public class ModeledUserContext extends RestrictedObject
|
||||
*/
|
||||
@Inject
|
||||
private Provider<ConnectionRecordSet> connectionRecordSetProvider;
|
||||
|
||||
|
||||
/**
|
||||
* Provider for creating user record sets.
|
||||
*/
|
||||
@Inject
|
||||
private Provider<UserRecordSet> userRecordSetProvider;
|
||||
|
||||
/**
|
||||
* Mapper for user login records.
|
||||
*/
|
||||
@Inject
|
||||
private UserRecordMapper userRecordMapper;
|
||||
|
||||
/**
|
||||
* The activity record associated with this user's Guacamole session.
|
||||
*/
|
||||
private ActivityRecordModel userRecord;
|
||||
|
||||
@Override
|
||||
public void init(ModeledAuthenticatedUser currentUser) {
|
||||
|
||||
@@ -112,6 +130,15 @@ public class ModeledUserContext extends RestrictedObject
|
||||
sharingProfileDirectory.init(currentUser);
|
||||
activeConnectionDirectory.init(currentUser);
|
||||
|
||||
// Create login record for user
|
||||
userRecord = new ActivityRecordModel();
|
||||
userRecord.setUsername(currentUser.getIdentifier());
|
||||
userRecord.setStartDate(new Date());
|
||||
userRecord.setRemoteHost(currentUser.getCredentials().getRemoteHostname());
|
||||
|
||||
// Insert record representing login
|
||||
userRecordMapper.insert(userRecord);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,7 +194,9 @@ public class ModeledUserContext extends RestrictedObject
|
||||
@Override
|
||||
public ActivityRecordSet<ActivityRecord> getUserHistory()
|
||||
throws GuacamoleException {
|
||||
return new SimpleActivityRecordSet<ActivityRecord>();
|
||||
UserRecordSet userRecordSet = userRecordSetProvider.get();
|
||||
userRecordSet.init(getCurrentUser());
|
||||
return userRecordSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -202,7 +231,11 @@ public class ModeledUserContext extends RestrictedObject
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
// Nothing to invalidate
|
||||
|
||||
// Record logout time
|
||||
userRecord.setEndDate(new Date());
|
||||
userRecordMapper.update(userRecord);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -114,6 +114,12 @@ public class UserModel extends ObjectModel {
|
||||
*/
|
||||
private String organizationalRole;
|
||||
|
||||
/**
|
||||
* The date and time that this user was last active, or null if this user
|
||||
* has never logged in.
|
||||
*/
|
||||
private Timestamp lastActive;
|
||||
|
||||
/**
|
||||
* Creates a new, empty user.
|
||||
*/
|
||||
@@ -465,4 +471,30 @@ public class UserModel extends ObjectModel {
|
||||
this.organizationalRole = organizationalRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date and time that this user was last active, or null if
|
||||
* this user has never logged in.
|
||||
*
|
||||
* @return
|
||||
* The date and time that this user was last active, or null if this
|
||||
* user has never logged in.
|
||||
*/
|
||||
public Timestamp getLastActive() {
|
||||
return lastActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the date and time that this user was last active. This value is
|
||||
* expected to be set automatically via queries, derived from user history
|
||||
* records. It does NOT correspond to an actual column, and values set
|
||||
* manually through invoking this function will not persist.
|
||||
*
|
||||
* @param lastActive
|
||||
* The date and time that this user was last active, or null if this
|
||||
* user has never logged in.
|
||||
*/
|
||||
public void setLastActive(Timestamp lastActive) {
|
||||
this.lastActive = lastActive;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.jdbc.user;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordModel;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* Mapper for user login activity records.
|
||||
*/
|
||||
public interface UserRecordMapper {
|
||||
|
||||
/**
|
||||
* Returns a collection of all user login records associated with the user
|
||||
* having the given username.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user whose login records are to be retrieved.
|
||||
*
|
||||
* @return
|
||||
* A collection of all user login records associated with the user
|
||||
* having the given username. This collection will be empty if no such
|
||||
* user exists.
|
||||
*/
|
||||
List<ActivityRecordModel> select(@Param("username") String username);
|
||||
|
||||
/**
|
||||
* Inserts the given user login record.
|
||||
*
|
||||
* @param record
|
||||
* The user login record to insert.
|
||||
*
|
||||
* @return
|
||||
* The number of rows inserted.
|
||||
*/
|
||||
int insert(@Param("record") ActivityRecordModel record);
|
||||
|
||||
/**
|
||||
* Updates the given user login record.
|
||||
*
|
||||
* @param record
|
||||
* The user login record to update.
|
||||
*
|
||||
* @return
|
||||
* The number of rows updated.
|
||||
*/
|
||||
int update(@Param("record") ActivityRecordModel record);
|
||||
|
||||
/**
|
||||
* Searches for up to <code>limit</code> user login records that contain
|
||||
* 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.
|
||||
*
|
||||
* @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<ActivityRecordModel> search(@Param("terms") Collection<ActivityRecordSearchTerm> terms,
|
||||
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
|
||||
@Param("limit") int limit);
|
||||
|
||||
/**
|
||||
* Searches for up to <code>limit</code> user login 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<ActivityRecordModel> searchReadable(@Param("user") UserModel user,
|
||||
@Param("terms") Collection<ActivityRecordSearchTerm> terms,
|
||||
@Param("sortPredicates") List<ActivityRecordSortPredicate> sortPredicates,
|
||||
@Param("limit") int limit);
|
||||
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.apache.guacamole.auth.jdbc.user;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
||||
import org.apache.guacamole.auth.jdbc.base.ModeledActivityRecordSet;
|
||||
import org.apache.guacamole.net.auth.ActivityRecord;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
|
||||
/**
|
||||
* A JDBC implementation of ActivityRecordSet for retrieving user login history.
|
||||
* Calls to asCollection() will query user login records from the database.
|
||||
* Which records are returned will be determined by the values passed in
|
||||
* earlier.
|
||||
*/
|
||||
public class UserRecordSet extends ModeledActivityRecordSet<ActivityRecord> {
|
||||
|
||||
/**
|
||||
* Service for managing user objects.
|
||||
*/
|
||||
@Inject
|
||||
private UserService userService;
|
||||
|
||||
@Override
|
||||
protected Collection<ActivityRecord> retrieveHistory(
|
||||
AuthenticatedUser user, Set<ActivityRecordSearchTerm> requiredContents,
|
||||
List<ActivityRecordSortPredicate> sortPredicates, int limit)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Retrieve history from database
|
||||
return userService.retrieveHistory(getCurrentUser(),
|
||||
requiredContents, sortPredicates, limit);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -21,16 +21,24 @@ package org.apache.guacamole.auth.jdbc.user;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.guacamole.net.auth.Credentials;
|
||||
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectMapper;
|
||||
import org.apache.guacamole.auth.jdbc.base.ModeledDirectoryObjectService;
|
||||
import org.apache.guacamole.GuacamoleClientException;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleSecurityException;
|
||||
import org.apache.guacamole.GuacamoleUnsupportedException;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordModel;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSearchTerm;
|
||||
import org.apache.guacamole.auth.jdbc.base.ActivityRecordSortPredicate;
|
||||
import org.apache.guacamole.auth.jdbc.base.ModeledActivityRecord;
|
||||
import org.apache.guacamole.auth.jdbc.connection.ConnectionRecordModel;
|
||||
import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionMapper;
|
||||
import org.apache.guacamole.auth.jdbc.permission.ObjectPermissionModel;
|
||||
import org.apache.guacamole.auth.jdbc.permission.UserPermissionMapper;
|
||||
@@ -38,8 +46,10 @@ import org.apache.guacamole.auth.jdbc.security.PasswordEncryptionService;
|
||||
import org.apache.guacamole.auth.jdbc.security.PasswordPolicyService;
|
||||
import org.apache.guacamole.form.Field;
|
||||
import org.apache.guacamole.form.PasswordField;
|
||||
import org.apache.guacamole.net.auth.ActivityRecord;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||
import org.apache.guacamole.net.auth.ConnectionRecord;
|
||||
import org.apache.guacamole.net.auth.User;
|
||||
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
||||
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
|
||||
@@ -116,7 +126,13 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
||||
*/
|
||||
@Inject
|
||||
private UserPermissionMapper userPermissionMapper;
|
||||
|
||||
|
||||
/**
|
||||
* Mapper for accessing user login history.
|
||||
*/
|
||||
@Inject
|
||||
private UserRecordMapper userRecordMapper;
|
||||
|
||||
/**
|
||||
* Provider for creating users.
|
||||
*/
|
||||
@@ -460,4 +476,119 @@ public class UserService extends ModeledDirectoryObjectService<ModeledUser, User
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a ActivityRecord object which is backed by the given model.
|
||||
*
|
||||
* @param model
|
||||
* The model object to use to back the returned connection record
|
||||
* object.
|
||||
*
|
||||
* @return
|
||||
* A connection record object which is backed by the given model.
|
||||
*/
|
||||
protected ActivityRecord getObjectInstance(ActivityRecordModel model) {
|
||||
return new ModeledActivityRecord(model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ActivityRecord objects which are backed by the
|
||||
* models in the given list.
|
||||
*
|
||||
* @param models
|
||||
* The model objects to use to back the activity record objects
|
||||
* within the returned list.
|
||||
*
|
||||
* @return
|
||||
* A list of activity record objects which are backed by the models
|
||||
* in the given list.
|
||||
*/
|
||||
protected List<ActivityRecord> getObjectInstances(List<ActivityRecordModel> models) {
|
||||
|
||||
// Create new list of records by manually converting each model
|
||||
List<ActivityRecord> objects = new ArrayList<ActivityRecord>(models.size());
|
||||
for (ActivityRecordModel model : models)
|
||||
objects.add(getObjectInstance(model));
|
||||
|
||||
return objects;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the login history of the given user, including any active
|
||||
* sessions.
|
||||
*
|
||||
* @param authenticatedUser
|
||||
* The user retrieving the login history.
|
||||
*
|
||||
* @param user
|
||||
* The user whose history is being retrieved.
|
||||
*
|
||||
* @return
|
||||
* The login history of the given user, including any active sessions.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If permission to read the login history is denied.
|
||||
*/
|
||||
public List<ActivityRecord> retrieveHistory(ModeledAuthenticatedUser authenticatedUser,
|
||||
ModeledUser user) throws GuacamoleException {
|
||||
|
||||
String username = user.getIdentifier();
|
||||
|
||||
// Retrieve history only if READ permission is granted
|
||||
if (hasObjectPermission(authenticatedUser, username, ObjectPermission.Type.READ))
|
||||
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 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(ModeledAuthenticatedUser user,
|
||||
Collection<ActivityRecordSearchTerm> requiredContents,
|
||||
List<ActivityRecordSortPredicate> sortPredicates, int limit)
|
||||
throws GuacamoleException {
|
||||
|
||||
List<ActivityRecordModel> searchResults;
|
||||
|
||||
// Bypass permission checks if the user is a system admin
|
||||
if (user.getUser().isAdministrator())
|
||||
searchResults = userRecordMapper.search(requiredContents,
|
||||
sortPredicates, limit);
|
||||
|
||||
// Otherwise only return explicitly readable history records
|
||||
else
|
||||
searchResults = userRecordMapper.searchReadable(user.getUser().getModel(),
|
||||
requiredContents, sortPredicates, limit);
|
||||
|
||||
return getObjectInstances(searchResults);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user