GUACAMOLE-394: Add user history REST endpoint.

Project: http://git-wip-us.apache.org/repos/asf/guacamole-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/guacamole-client/commit/29284725
Tree: http://git-wip-us.apache.org/repos/asf/guacamole-client/tree/29284725
Diff: http://git-wip-us.apache.org/repos/asf/guacamole-client/diff/29284725

Branch: refs/heads/master
Commit: 2928472549e5664247ff892d9155ddca8c9365b5
Parents: 9df20f2
Author: Michael Jumper <mjum...@apache.org>
Authored: Mon Sep 11 18:27:21 2017 -0700
Committer: Michael Jumper <mjum...@apache.org>
Committed: Mon Dec 11 20:44:28 2017 -0800

----------------------------------------------------------------------
 .../rest/history/APIActivityRecord.java         | 131 +++++++++++++++++
 .../rest/history/APIConnectionRecord.java       |  89 +-----------
 .../APIConnectionRecordSortPredicate.java       | 144 -------------------
 .../rest/history/APISortPredicate.java          | 144 +++++++++++++++++++
 .../guacamole/rest/history/HistoryResource.java |  60 +++++++-
 5 files changed, 335 insertions(+), 233 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/29284725/guacamole/src/main/java/org/apache/guacamole/rest/history/APIActivityRecord.java
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/java/org/apache/guacamole/rest/history/APIActivityRecord.java
 
b/guacamole/src/main/java/org/apache/guacamole/rest/history/APIActivityRecord.java
new file mode 100644
index 0000000..c1a0149
--- /dev/null
+++ 
b/guacamole/src/main/java/org/apache/guacamole/rest/history/APIActivityRecord.java
@@ -0,0 +1,131 @@
+/*
+ * 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.rest.history;
+
+import java.util.Date;
+import org.apache.guacamole.net.auth.ActivityRecord;
+
+/**
+ * A activity record which may be exposed through the REST endpoints.
+ */
+public class APIActivityRecord {
+
+    /**
+     * The date and time the activity began.
+     */
+    private final Date startDate;
+
+    /**
+     * The date and time the activity ended, or null if the activity is
+     * still in progress or if the end time is unknown.
+     */
+    private final Date endDate;
+
+    /**
+     * The hostname or IP address of the remote host that performed the
+     * activity associated with this record, if known.
+     */
+    private final String remoteHost;
+
+    /**
+     * The name of the user who performed or is performing the activity
+     * associated with this record.
+     */
+    private final String username;
+
+    /**
+     * Whether the activity is still in progress.
+     */
+    private final boolean active;
+
+    /**
+     * Creates a new APIActivityRecord, copying the data from the given 
activity
+     * record.
+     *
+     * @param record
+     *     The record to copy data from.
+     */
+    public APIActivityRecord(ActivityRecord record) {
+        this.startDate  = record.getStartDate();
+        this.endDate    = record.getEndDate();
+        this.remoteHost = record.getRemoteHost();
+        this.username   = record.getUsername();
+        this.active     = record.isActive();
+    }
+
+    /**
+     * Returns the date and time the activity began.
+     *
+     * @return
+     *     The date and time the activity began.
+     */
+    public Date getStartDate() {
+        return startDate;
+    }
+
+    /**
+     * Returns the date and time the activity ended, if applicable.
+     *
+     * @return
+     *     The date and time the activity ended, or null if the activity is
+     *     still in progress or if the end time is unknown.
+     */
+    public Date getEndDate() {
+        return endDate;
+    }
+
+    /**
+     * Returns the hostname or IP address of the remote host that performed the
+     * activity associated with this record, if known.
+     *
+     * @return
+     *     The hostname or IP address of the remote host that performed the
+     *     activity associated with this record, or null if the remote host is
+     *     unknown.
+     */
+    public String getRemoteHost() {
+        return remoteHost;
+    }
+
+    /**
+     * Returns the name of the user who performed or is performing the activity
+     * associated with this record.
+     *
+     * @return
+     *     The name of the user who performed or is performing the activity
+     *     associated with this record.
+     */
+    public String getUsername() {
+        return username;
+    }
+
+    /**
+     * Returns whether the activity associated with this record is still in
+     * progress.
+     *
+     * @return
+     *     true if the activity associated with this record is still in
+     *     progress, false otherwise.
+     */
+    public boolean isActive() {
+        return active;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/29284725/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecord.java
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecord.java
 
b/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecord.java
index 97c99a0..9d17fbf 100644
--- 
a/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecord.java
+++ 
b/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecord.java
@@ -19,13 +19,12 @@
 
 package org.apache.guacamole.rest.history;
 
-import java.util.Date;
 import org.apache.guacamole.net.auth.ConnectionRecord;
 
 /**
  * A connection record which may be exposed through the REST endpoints.
  */
-public class APIConnectionRecord {
+public class APIConnectionRecord extends APIActivityRecord {
 
     /**
      * The identifier of the connection associated with this record.
@@ -48,32 +47,6 @@ public class APIConnectionRecord {
     private final String sharingProfileName;
 
     /**
-     * The date and time the connection began.
-     */
-    private final Date startDate;
-
-    /**
-     * The date and time the connection ended, or null if the connection is
-     * still running or if the end time is unknown.
-     */
-    private final Date endDate;
-
-    /**
-     * The host from which the connection originated, if known.
-     */
-    private final String remoteHost;
-
-    /**
-     * The name of the user who used or is using the connection.
-     */
-    private final String username;
-
-    /**
-     * Whether the connection is currently active.
-     */
-    private final boolean active;
-
-    /**
      * Creates a new APIConnectionRecord, copying the data from the given
      * record.
      *
@@ -81,15 +54,11 @@ public class APIConnectionRecord {
      *     The record to copy data from.
      */
     public APIConnectionRecord(ConnectionRecord record) {
+        super(record);
         this.connectionIdentifier     = record.getConnectionIdentifier();
         this.connectionName           = record.getConnectionName();
         this.sharingProfileIdentifier = record.getSharingProfileIdentifier();
         this.sharingProfileName       = record.getSharingProfileName();
-        this.startDate                = record.getStartDate();
-        this.endDate                  = record.getEndDate();
-        this.remoteHost               = record.getRemoteHost();
-        this.username                 = record.getUsername();
-        this.active                   = record.isActive();
     }
 
     /**
@@ -139,58 +108,4 @@ public class APIConnectionRecord {
         return sharingProfileName;
     }
 
-    /**
-     * Returns the date and time the connection began.
-     *
-     * @return
-     *     The date and time the connection began.
-     */
-    public Date getStartDate() {
-        return startDate;
-    }
-
-    /**
-     * Returns the date and time the connection ended, if applicable.
-     *
-     * @return
-     *     The date and time the connection ended, or null if the connection is
-     *     still running or if the end time is unknown.
-     */
-    public Date getEndDate() {
-        return endDate;
-    }
-
-    /**
-     * Returns the remote host from which this connection originated.
-     *
-     * @return
-     *     The remote host from which this connection originated.
-     */
-    public String getRemoteHost() {
-        return remoteHost;
-    }
-
-    /**
-     * Returns the name of the user who used or is using the connection at the
-     * times given by this connection record.
-     *
-     * @return
-     *     The name of the user who used or is using the associated connection.
-     */
-    public String getUsername() {
-        return username;
-    }
-
-    /**
-     * Returns whether the connection associated with this record is still
-     * active.
-     *
-     * @return
-     *     true if the connection associated with this record is still active,
-     *     false otherwise.
-     */
-    public boolean isActive() {
-        return active;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/29284725/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecordSortPredicate.java
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecordSortPredicate.java
 
b/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecordSortPredicate.java
deleted file mode 100644
index d2281d0..0000000
--- 
a/guacamole/src/main/java/org/apache/guacamole/rest/history/APIConnectionRecordSortPredicate.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * 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.rest.history;
-
-import javax.ws.rs.core.Response;
-import org.apache.guacamole.GuacamoleClientException;
-import org.apache.guacamole.net.auth.ActivityRecordSet;
-import org.apache.guacamole.rest.APIException;
-
-/**
- * A sort predicate which species the property to use when sorting connection
- * records, along with the sort order.
- */
-public class APIConnectionRecordSortPredicate {
-
-    /**
-     * The prefix which will be included before the name of a sortable property
-     * to indicate that the sort order is descending, not ascending.
-     */
-    public static final String DESCENDING_PREFIX = "-";
-
-    /**
-     * All possible property name strings and their corresponding
-     * ActivityRecordSet.SortableProperty values.
-     */
-    public enum SortableProperty {
-
-        /**
-         * The date that the connection associated with the connection record
-         * began (connected).
-         */
-        startDate(ActivityRecordSet.SortableProperty.START_DATE);
-
-        /**
-         * The ActivityRecordSet.SortableProperty that this property name
-         * string represents.
-         */
-        public final ActivityRecordSet.SortableProperty recordProperty;
-
-        /**
-         * Creates a new SortableProperty which associates the property name
-         * string (identical to its own name) with the given
-         * ActivityRecordSet.SortableProperty value.
-         *
-         * @param recordProperty
-         *     The ActivityRecordSet.SortableProperty value to associate with
-         *     the new SortableProperty.
-         */
-        SortableProperty(ActivityRecordSet.SortableProperty recordProperty) {
-            this.recordProperty = recordProperty;
-        }
-
-    }
-
-    /**
-     * The property to use when sorting ConnectionRecords.
-     */
-    private ActivityRecordSet.SortableProperty property;
-
-    /**
-     * Whether the requested sort order is descending (true) or ascending
-     * (false).
-     */
-    private boolean descending;
-
-    /**
-     * Parses the given string value, determining the requested sort property
-     * and ordering. Possible values consist of any valid property name, and
-     * may include an optional prefix to denote descending sort order. Each
-     * possible property name is enumerated by the SortableValue enum.
-     *
-     * @param value
-     *     The sort predicate string to parse, which must consist ONLY of a
-     *     valid property name, possibly preceded by the DESCENDING_PREFIX.
-     *
-     * @throws APIException
-     *     If the provided sort predicate string is invalid.
-     */
-    public APIConnectionRecordSortPredicate(String value)
-        throws APIException {
-
-        // Parse whether sort order is descending
-        if (value.startsWith(DESCENDING_PREFIX)) {
-            descending = true;
-            value = value.substring(DESCENDING_PREFIX.length());
-        }
-
-        // Parse sorting property into ActivityRecordSet.SortableProperty
-        try {
-            this.property = SortableProperty.valueOf(value).recordProperty;
-        }
-
-        // Bail out if sort property is not valid
-        catch (IllegalArgumentException e) {
-            throw new APIException(
-                Response.Status.BAD_REQUEST,
-                new GuacamoleClientException(String.format("Invalid sort 
property: \"%s\"", value))
-            );
-        }
-
-    }
-
-    /**
-     * Returns the SortableProperty defined by ActivityRecordSet which
-     * represents the property requested.
-     *
-     * @return
-     *     The ActivityRecordSet.SortableProperty which refers to the same
-     *     property as the string originally provided when this
-     *     APIConnectionRecordSortPredicate was created.
-     */
-    public ActivityRecordSet.SortableProperty getProperty() {
-        return property;
-    }
-
-    /**
-     * Returns whether the requested sort order is descending.
-     *
-     * @return
-     *     true if the sort order is descending, false if the sort order is
-     *     ascending.
-     */
-    public boolean isDescending() {
-        return descending;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/29284725/guacamole/src/main/java/org/apache/guacamole/rest/history/APISortPredicate.java
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/java/org/apache/guacamole/rest/history/APISortPredicate.java
 
b/guacamole/src/main/java/org/apache/guacamole/rest/history/APISortPredicate.java
new file mode 100644
index 0000000..c45ae9a
--- /dev/null
+++ 
b/guacamole/src/main/java/org/apache/guacamole/rest/history/APISortPredicate.java
@@ -0,0 +1,144 @@
+/*
+ * 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.rest.history;
+
+import javax.ws.rs.core.Response;
+import org.apache.guacamole.GuacamoleClientException;
+import org.apache.guacamole.net.auth.ActivityRecordSet;
+import org.apache.guacamole.rest.APIException;
+
+/**
+ * A sort predicate which species the property to use when sorting activity
+ * records, along with the sort order.
+ */
+public class APISortPredicate {
+
+    /**
+     * The prefix which will be included before the name of a sortable property
+     * to indicate that the sort order is descending, not ascending.
+     */
+    public static final String DESCENDING_PREFIX = "-";
+
+    /**
+     * All possible property name strings and their corresponding
+     * ActivityRecordSet.SortableProperty values.
+     */
+    public enum SortableProperty {
+
+        /**
+         * The date that the activity associated with the activity record
+         * began.
+         */
+        startDate(ActivityRecordSet.SortableProperty.START_DATE);
+
+        /**
+         * The ActivityRecordSet.SortableProperty that this property name
+         * string represents.
+         */
+        public final ActivityRecordSet.SortableProperty recordProperty;
+
+        /**
+         * Creates a new SortableProperty which associates the property name
+         * string (identical to its own name) with the given
+         * ActivityRecordSet.SortableProperty value.
+         *
+         * @param recordProperty
+         *     The ActivityRecordSet.SortableProperty value to associate with
+         *     the new SortableProperty.
+         */
+        SortableProperty(ActivityRecordSet.SortableProperty recordProperty) {
+            this.recordProperty = recordProperty;
+        }
+
+    }
+
+    /**
+     * The property to use when sorting ActivityRecords.
+     */
+    private ActivityRecordSet.SortableProperty property;
+
+    /**
+     * Whether the requested sort order is descending (true) or ascending
+     * (false).
+     */
+    private boolean descending;
+
+    /**
+     * Parses the given string value, determining the requested sort property
+     * and ordering. Possible values consist of any valid property name, and
+     * may include an optional prefix to denote descending sort order. Each
+     * possible property name is enumerated by the SortableValue enum.
+     *
+     * @param value
+     *     The sort predicate string to parse, which must consist ONLY of a
+     *     valid property name, possibly preceded by the DESCENDING_PREFIX.
+     *
+     * @throws APIException
+     *     If the provided sort predicate string is invalid.
+     */
+    public APISortPredicate(String value)
+        throws APIException {
+
+        // Parse whether sort order is descending
+        if (value.startsWith(DESCENDING_PREFIX)) {
+            descending = true;
+            value = value.substring(DESCENDING_PREFIX.length());
+        }
+
+        // Parse sorting property into ActivityRecordSet.SortableProperty
+        try {
+            this.property = SortableProperty.valueOf(value).recordProperty;
+        }
+
+        // Bail out if sort property is not valid
+        catch (IllegalArgumentException e) {
+            throw new APIException(
+                Response.Status.BAD_REQUEST,
+                new GuacamoleClientException(String.format("Invalid sort 
property: \"%s\"", value))
+            );
+        }
+
+    }
+
+    /**
+     * Returns the SortableProperty defined by ActivityRecordSet which
+     * represents the property requested.
+     *
+     * @return
+     *     The ActivityRecordSet.SortableProperty which refers to the same
+     *     property as the string originally provided when this
+     *     APISortPredicate was created.
+     */
+    public ActivityRecordSet.SortableProperty getProperty() {
+        return property;
+    }
+
+    /**
+     * Returns whether the requested sort order is descending.
+     *
+     * @return
+     *     true if the sort order is descending, false if the sort order is
+     *     ascending.
+     */
+    public boolean isDescending() {
+        return descending;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/guacamole-client/blob/29284725/guacamole/src/main/java/org/apache/guacamole/rest/history/HistoryResource.java
----------------------------------------------------------------------
diff --git 
a/guacamole/src/main/java/org/apache/guacamole/rest/history/HistoryResource.java
 
b/guacamole/src/main/java/org/apache/guacamole/rest/history/HistoryResource.java
index 53a8cdb..559ebd5 100644
--- 
a/guacamole/src/main/java/org/apache/guacamole/rest/history/HistoryResource.java
+++ 
b/guacamole/src/main/java/org/apache/guacamole/rest/history/HistoryResource.java
@@ -28,6 +28,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 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.ConnectionRecord;
 import org.apache.guacamole.net.auth.UserContext;
@@ -88,7 +89,7 @@ public class HistoryResource {
     @Path("connections")
     public List<APIConnectionRecord> getConnectionHistory(
             @QueryParam("contains") List<String> requiredContents,
-            @QueryParam("order") List<APIConnectionRecordSortPredicate> 
sortPredicates)
+            @QueryParam("order") List<APISortPredicate> sortPredicates)
             throws GuacamoleException {
 
         // Retrieve overall connection history
@@ -101,7 +102,7 @@ public class HistoryResource {
         }
 
         // Sort according to specified ordering
-        for (APIConnectionRecordSortPredicate predicate : sortPredicates)
+        for (APISortPredicate predicate : sortPredicates)
             history = history.sort(predicate.getProperty(), 
predicate.isDescending());
 
         // Limit to maximum result size
@@ -117,4 +118,59 @@ public class HistoryResource {
 
     }
 
+    /**
+     * Retrieves the login history for all users, restricted by optional filter
+     * parameters.
+     *
+     * @param requiredContents
+     *     The set of strings that each must occur somewhere within the
+     *     returned user records, whether within the associated username or any
+     *     associated date. If non-empty, any user record not matching each of
+     *     the strings within the collection will be excluded from the results.
+     *
+     * @param sortPredicates
+     *     A list of predicates to apply while sorting the resulting user
+     *     records, describing the properties involved and the sort order for
+     *     those properties.
+     *
+     * @return
+     *     A list of user records, describing the start and end times of user
+     *     sessions.
+     *
+     * @throws GuacamoleException
+     *     If an error occurs while retrieving the user history.
+     */
+    @GET
+    @Path("users")
+    public List<APIActivityRecord> getUserHistory(
+            @QueryParam("contains") List<String> requiredContents,
+            @QueryParam("order") List<APISortPredicate> sortPredicates)
+            throws GuacamoleException {
+
+        // Retrieve overall user history
+        ActivityRecordSet<ActivityRecord> history = 
userContext.getUserHistory();
+
+        // Restrict to records which contain the specified strings
+        for (String required : requiredContents) {
+            if (!required.isEmpty())
+                history = history.contains(required);
+        }
+
+        // Sort according to specified ordering
+        for (APISortPredicate predicate : sortPredicates)
+            history = history.sort(predicate.getProperty(), 
predicate.isDescending());
+
+        // Limit to maximum result size
+        history = history.limit(MAXIMUM_HISTORY_SIZE);
+
+        // Convert record set to collection of API user records
+        List<APIActivityRecord> apiRecords = new 
ArrayList<APIActivityRecord>();
+        for (ActivityRecord record : history.asCollection())
+            apiRecords.add(new APIActivityRecord(record));
+
+        // Return the converted history
+        return apiRecords;
+
+    }
+
 }

Reply via email to