diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecordSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecordSet.java index d2590184b..60446aab5 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecordSet.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/base/ModeledActivityRecordSet.java @@ -48,7 +48,7 @@ public abstract class ModeledActivityRecordSet requiredContents = - new HashSet(); + new HashSet<>(); /** * The maximum number of history records that should be returned by a call @@ -62,7 +62,7 @@ public abstract class ModeledActivityRecordSet sortPredicates = - new ArrayList(); + new ArrayList<>(); /** * Retrieves the history records matching the given criteria. Retrieves up diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java index f4574f4e0..0446abece 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordSet.java @@ -27,6 +27,7 @@ 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.auth.jdbc.user.ModeledAuthenticatedUser; import org.apache.guacamole.net.auth.AuthenticatedUser; import org.apache.guacamole.net.auth.ConnectionRecord; @@ -43,6 +44,27 @@ public class ConnectionRecordSet extends ModeledActivityRecordSet retrieveHistory( AuthenticatedUser user, Set requiredContents, @@ -50,7 +72,7 @@ public class ConnectionRecordSet extends ModeledActivityRecordSet configProvider; + /** + * Provider for creating connection record sets. + */ + @Inject + private Provider connectionRecordSetProvider; + /** * The manually-set GuacamoleConfiguration, if any. */ @@ -257,6 +264,14 @@ public class ModeledConnection extends ModeledChildDirectoryObject getHistory() throws GuacamoleException { return connectionService.retrieveHistory(getCurrentUser(), this); } + + @Override + public ActivityRecordSet getConnectionHistory() + throws GuacamoleException { + ConnectionRecordSet connectionRecordSet = connectionRecordSetProvider.get(); + connectionRecordSet.init(getCurrentUser(), this.getIdentifier()); + return connectionRecordSet; + } @Override public GuacamoleTunnel connect(GuacamoleClientInformation info, diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/connection/SharedConnection.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/connection/SharedConnection.java index cf0083167..b1cf4a52a 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/connection/SharedConnection.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/connection/SharedConnection.java @@ -26,10 +26,12 @@ import java.util.List; import java.util.Map; import java.util.Set; import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.GuacamoleUnsupportedException; import org.apache.guacamole.auth.jdbc.sharing.connectiongroup.SharedRootConnectionGroup; import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService; import org.apache.guacamole.auth.jdbc.user.RemoteAuthenticatedUser; import org.apache.guacamole.net.GuacamoleTunnel; +import org.apache.guacamole.net.auth.ActivityRecordSet; import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.ConnectionRecord; import org.apache.guacamole.protocol.GuacamoleClientInformation; @@ -157,6 +159,12 @@ public class SharedConnection implements Connection { throws GuacamoleException { return Collections.emptyList(); } + + @Override + public ActivityRecordSet getConnectionHistory() + throws GuacamoleException { + throw new GuacamoleUnsupportedException("SharedConnection objects do not provide history."); + } @Override public Set getSharingProfileIdentifiers() diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUser.java index f0a48b87d..dbf520567 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUser.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/sharing/user/SharedUser.java @@ -24,8 +24,10 @@ import java.util.Date; import java.util.List; import java.util.Map; import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.GuacamoleUnsupportedException; import org.apache.guacamole.auth.jdbc.sharing.permission.SharedObjectPermissionSet; import org.apache.guacamole.net.auth.ActivityRecord; +import org.apache.guacamole.net.auth.ActivityRecordSet; import org.apache.guacamole.net.auth.AuthenticatedUser; import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.ConnectionGroup; @@ -106,6 +108,12 @@ public class SharedUser implements User { return Collections.emptyList(); } + + @Override + public ActivityRecordSet getUserHistory() + throws GuacamoleException { + throw new GuacamoleUnsupportedException("SharedUser objects do not provide login history."); + } @Override public String getPassword() { diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java index 54f052b75..bc0395c23 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/ModeledUser.java @@ -47,6 +47,7 @@ import org.apache.guacamole.form.TextField; import org.apache.guacamole.form.TimeField; import org.apache.guacamole.form.TimeZoneField; import org.apache.guacamole.net.auth.ActivityRecord; +import org.apache.guacamole.net.auth.ActivityRecordSet; import org.apache.guacamole.net.auth.Permissions; import org.apache.guacamole.net.auth.RelatedObjectSet; import org.apache.guacamole.net.auth.User; @@ -182,6 +183,12 @@ public class ModeledUser extends ModeledPermissions implements User { */ @Inject private Provider parentUserGroupSetProvider; + + /** + * Provider for creating user record sets. + */ + @Inject + private Provider userRecordSetProvider; /** * Whether attributes which control access restrictions should be exposed @@ -751,6 +758,14 @@ public class ModeledUser extends ModeledPermissions implements User { public List getHistory() throws GuacamoleException { return userService.retrieveHistory(getCurrentUser(), this); } + + @Override + public ActivityRecordSet getUserHistory() + throws GuacamoleException { + UserRecordSet userRecordSet = userRecordSetProvider.get(); + userRecordSet.init(getCurrentUser(), this.getIdentifier()); + return userRecordSet; + } @Override public RelatedObjectSet getUserGroups() throws GuacamoleException { diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java index c1b4897e7..555f1cbb4 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/user/UserRecordSet.java @@ -44,6 +44,13 @@ public class UserRecordSet extends ModeledActivityRecordSet { @Inject private UserService userService; + private String identifier = null; + + protected void init(ModeledAuthenticatedUser currentUser, String identifier) { + super.init(currentUser); + this.identifier = identifier; + } + @Override protected Collection retrieveHistory( AuthenticatedUser user, Set requiredContents, @@ -51,7 +58,7 @@ public class UserRecordSet extends ModeledActivityRecordSet { throws GuacamoleException { // Retrieve history from database - return userService.retrieveHistory(getCurrentUser(), + return userService.retrieveHistory(identifier, getCurrentUser(), requiredContents, sortPredicates, limit); } diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractUser.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractUser.java index b502f7a1b..cf333725d 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractUser.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/AbstractUser.java @@ -26,6 +26,7 @@ import java.util.Map; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; import org.apache.guacamole.net.auth.permission.SystemPermissionSet; +import org.apache.guacamole.net.auth.simple.SimpleActivityRecordSet; /** * Base implementation of User which provides default implementations of @@ -96,6 +97,12 @@ public abstract class AbstractUser extends AbstractIdentifiable public List getHistory() throws GuacamoleException { return Collections.emptyList(); } + + @Override + public ActivityRecordSet getUserHistory() + throws GuacamoleException { + return new SimpleActivityRecordSet<>(); + } /** * {@inheritDoc} diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java index 5b1d13d54..8643ccc5a 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/Connection.java @@ -109,6 +109,24 @@ public interface Connection extends Identifiable, Connectable, Attributes { */ public List getHistory() throws GuacamoleException; + /** + * Returns an ActivityRecordSet containing ConnectionRecords that + * represent the usage history of this Connection, including any active + * users. ConnectionRecords in this list will be sorted in descending order + * of end time (active connections are first), and then in descending order + * of start time (newer connections are first). + * + * @return + * An ActivityRecordSet containing ConnectionRecords representing the + * usage history of this Connection. + * + * @throws GuacamoleException + * If an error occurs retrieving history for this Connection, or if + * permission to retrieve the history is denied. + */ + public ActivityRecordSet getConnectionHistory() + throws GuacamoleException; + /** * Returns identifiers of all readable sharing profiles that can be used to * join this connection when it is active. The level of access granted to a diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingConnection.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingConnection.java index 95b6e9326..6b9e96451 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingConnection.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingConnection.java @@ -139,6 +139,12 @@ public class DelegatingConnection implements Connection { throws GuacamoleException { return connection.getHistory(); } + + @Override + public ActivityRecordSet getConnectionHistory() + throws GuacamoleException { + return connection.getConnectionHistory(); + } @Override public Set getSharingProfileIdentifiers() diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUser.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUser.java index add7be669..0fbdf0e6b 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUser.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/DelegatingUser.java @@ -98,6 +98,12 @@ public class DelegatingUser implements User { throws GuacamoleException { return user.getHistory(); } + + @Override + public ActivityRecordSet getUserHistory() + throws GuacamoleException { + return user.getUserHistory(); + } @Override public SystemPermissionSet getSystemPermissions() diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java index 4a8b43a8d..6ceceabb6 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/User.java @@ -104,6 +104,24 @@ public interface User extends Identifiable, Attributes, Permissions { * permission is denied. */ List getHistory() throws GuacamoleException; + + /** + * Returns an ActivityRecordSet containing ActivityRecords representing + * the login history for this user, including any active sessions. + * ActivityRecords in this list will be sorted in descending order of end + * time (active sessions are first), and then in descending order of start + * time (newer sessions are first). + * + * @return + * An ActivityRecordSet containing ActivityRecords representing the + * login history for this user. + * + * @throws GuacamoleException + * If an error occurs retrieving this user's login history, or if + * permission to retrieve login history is denied. + */ + public ActivityRecordSet getUserHistory() + throws GuacamoleException; /** * Returns a set of all readable user groups of which this user is a member. diff --git a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleConnection.java b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleConnection.java index 2934cbe9f..d1c01291c 100644 --- a/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleConnection.java +++ b/guacamole-ext/src/main/java/org/apache/guacamole/net/auth/simple/SimpleConnection.java @@ -33,6 +33,7 @@ import org.apache.guacamole.net.InetGuacamoleSocket; import org.apache.guacamole.net.SSLGuacamoleSocket; import org.apache.guacamole.net.SimpleGuacamoleTunnel; import org.apache.guacamole.net.auth.AbstractConnection; +import org.apache.guacamole.net.auth.ActivityRecordSet; import org.apache.guacamole.net.auth.ConnectionRecord; import org.apache.guacamole.net.auth.GuacamoleProxyConfiguration; import org.apache.guacamole.protocol.ConfiguredGuacamoleSocket; @@ -288,5 +289,11 @@ public class SimpleConnection extends AbstractConnection { public List getHistory() throws GuacamoleException { return Collections.emptyList(); } + + @Override + public ActivityRecordSet getConnectionHistory() + throws GuacamoleException { + return new SimpleActivityRecordSet<>(); + } } diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/connection/APIConnectionWrapper.java b/guacamole/src/main/java/org/apache/guacamole/rest/connection/APIConnectionWrapper.java index 704db2397..52a7d0808 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/connection/APIConnectionWrapper.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/connection/APIConnectionWrapper.java @@ -25,7 +25,9 @@ import java.util.List; import java.util.Map; import java.util.Set; import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.GuacamoleUnsupportedException; import org.apache.guacamole.net.GuacamoleTunnel; +import org.apache.guacamole.net.auth.ActivityRecordSet; import org.apache.guacamole.net.auth.Connection; import org.apache.guacamole.net.auth.ConnectionRecord; import org.apache.guacamole.protocol.GuacamoleClientInformation; @@ -123,14 +125,14 @@ public class APIConnectionWrapper implements Connection { } @Override - public Set getSharingProfileIdentifiers() { - throw new UnsupportedOperationException("Operation not supported."); + public Set getSharingProfileIdentifiers() throws GuacamoleException { + throw new GuacamoleUnsupportedException("Operation not supported."); } @Override public GuacamoleTunnel connect(GuacamoleClientInformation info, Map tokens) throws GuacamoleException { - throw new UnsupportedOperationException("Operation not supported."); + throw new GuacamoleUnsupportedException("Operation not supported."); } @Override @@ -143,4 +145,11 @@ public class APIConnectionWrapper implements Connection { return Collections.emptyList(); } + @Override + public ActivityRecordSet getConnectionHistory() + throws GuacamoleException { + throw new GuacamoleUnsupportedException("APIConnectionWrapper does not " + + "support retrieving connection history."); + } + } diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java index 02c2c0f6e..a5a21727a 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/connection/ConnectionResource.java @@ -22,8 +22,6 @@ package org.apache.guacamole.rest.connection; import com.google.inject.Inject; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -33,7 +31,6 @@ import javax.ws.rs.core.MediaType; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleSecurityException; import org.apache.guacamole.net.auth.Connection; -import org.apache.guacamole.net.auth.ConnectionRecord; import org.apache.guacamole.net.auth.Directory; import org.apache.guacamole.net.auth.Permissions; import org.apache.guacamole.rest.directory.DirectoryView; @@ -43,12 +40,12 @@ import org.apache.guacamole.net.auth.permission.ObjectPermission; import org.apache.guacamole.net.auth.permission.ObjectPermissionSet; import org.apache.guacamole.net.auth.permission.SystemPermission; import org.apache.guacamole.net.auth.permission.SystemPermissionSet; -import org.apache.guacamole.rest.history.APIConnectionRecord; import org.apache.guacamole.protocol.GuacamoleConfiguration; import org.apache.guacamole.rest.directory.DirectoryObjectResource; import org.apache.guacamole.rest.directory.DirectoryObjectTranslator; import org.apache.guacamole.rest.directory.DirectoryResource; import org.apache.guacamole.rest.directory.DirectoryResourceFactory; +import org.apache.guacamole.rest.history.ConnectionHistoryResource; import org.apache.guacamole.rest.sharingprofile.APISharingProfile; /** @@ -150,18 +147,11 @@ public class ConnectionResource extends DirectoryObjectResource getConnectionHistory() + public ConnectionHistoryResource getConnectionHistory() throws GuacamoleException { - // Retrieve the requested connection's history - List apiRecords = new ArrayList<>(); - for (ConnectionRecord record : connection.getHistory()) - apiRecords.add(new APIConnectionRecord(record)); - - // Return the converted history - return apiRecords; + return new ConnectionHistoryResource(connection.getConnectionHistory()); } diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/history/ActivityRecordSetResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/history/ActivityRecordSetResource.java index 8599a9557..3f72d4b3a 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/history/ActivityRecordSetResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/history/ActivityRecordSetResource.java @@ -84,7 +84,7 @@ public abstract class ActivityRecordSetResource getHistory() throws GuacamoleException { return Collections.emptyList(); } + + @Override + public ActivityRecordSet getUserHistory() + throws GuacamoleException { + throw new GuacamoleUnsupportedException("APIUserWrapper does not provide login history."); + } } diff --git a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java index d7d4bdc3f..1ed17fc38 100644 --- a/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java +++ b/guacamole/src/main/java/org/apache/guacamole/rest/user/UserResource.java @@ -33,7 +33,6 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.GuacamoleSecurityException; -import org.apache.guacamole.net.auth.ActivityRecord; import org.apache.guacamole.net.auth.AuthenticationProvider; import org.apache.guacamole.net.auth.Credentials; import org.apache.guacamole.net.auth.User; @@ -42,7 +41,7 @@ import org.apache.guacamole.net.auth.UserContext; import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException; import org.apache.guacamole.rest.directory.DirectoryObjectResource; import org.apache.guacamole.rest.directory.DirectoryObjectTranslator; -import org.apache.guacamole.rest.history.APIActivityRecord; +import org.apache.guacamole.rest.history.UserHistoryResource; import org.apache.guacamole.rest.identifier.RelatedObjectSetResource; import org.apache.guacamole.rest.permission.APIPermissionSet; import org.apache.guacamole.rest.permission.PermissionSetResource; @@ -110,18 +109,11 @@ public class UserResource * @throws GuacamoleException * If an error occurs while retrieving the user history. */ - @GET @Path("history") - public List getUserHistory() + public UserHistoryResource getUserHistory() throws GuacamoleException { - // Retrieve the requested user's history - List apiRecords = new ArrayList(); - for (ActivityRecord record : user.getHistory()) - apiRecords.add(new APIActivityRecord(record)); - - // Return the converted history - return apiRecords; + return new UserHistoryResource(user.getUserHistory()); }