diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordSearchTerm.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordSearchTerm.java
index e2e62b32e..a03d478f9 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordSearchTerm.java
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordSearchTerm.java
@@ -215,7 +215,7 @@ public class ConnectionRecordSearchTerm {
startCalendar.clear();
startCalendar.set(
Integer.parseInt(year),
- parseInt(month, 0),
+ parseInt(month, 1) - 1,
parseInt(day, 1)
);
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
index ad118923f..f6b6698a9 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
@@ -40,19 +40,20 @@
@@ -61,7 +62,6 @@
INSERT INTO guacamole_connection_history (
connection_id,
- connection_name,
user_id,
start_date,
end_date
@@ -108,8 +108,8 @@
OR (
- (start_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
- AND (end_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
+ (start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP})
+ AND (end_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP})
)
@@ -184,8 +184,8 @@
OR (
- (start_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
- AND (end_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
+ (start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP})
+ AND (end_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP})
)
diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
index 1fa7490a5..b3a23eadc 100644
--- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
+++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/src/main/resources/org/glyptodon/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml
@@ -40,19 +40,20 @@
@@ -61,7 +62,6 @@
INSERT INTO guacamole_connection_history (
connection_id,
- connection_name,
user_id,
start_date,
end_date
@@ -108,8 +108,8 @@
OR (
- (start_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
- AND (end_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
+ (start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP})
+ AND (end_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP})
)
@@ -184,8 +184,8 @@
OR (
- (start_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
- AND (end_date BETWEEN #{term.startDate,jdbcType=DATE} AND #{term.endDate,jdbcType=DATE})
+ (start_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP})
+ AND (end_date BETWEEN #{term.startDate,jdbcType=TIMESTAMP} AND #{term.endDate,jdbcType=TIMESTAMP})
)
diff --git a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/history/APIConnectionRecordSortPredicate.java b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/history/APIConnectionRecordSortPredicate.java
index 5c4ebbb94..17872d77d 100644
--- a/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/history/APIConnectionRecordSortPredicate.java
+++ b/guacamole/src/main/java/org/glyptodon/guacamole/net/basic/rest/history/APIConnectionRecordSortPredicate.java
@@ -50,7 +50,7 @@ public class APIConnectionRecordSortPredicate {
* The name (not identifier) of the connection associated with the
* connection record.
*/
- connection(ConnectionRecordSet.SortableProperty.CONNECTION_NAME),
+ connectionName(ConnectionRecordSet.SortableProperty.CONNECTION_NAME),
/**
* The username (identifier) of the user associated with the connection
diff --git a/guacamole/src/main/webapp/app/navigation/services/userPageService.js b/guacamole/src/main/webapp/app/navigation/services/userPageService.js
index 114ee2efb..9001aa1e0 100644
--- a/guacamole/src/main/webapp/app/navigation/services/userPageService.js
+++ b/guacamole/src/main/webapp/app/navigation/services/userPageService.js
@@ -173,6 +173,7 @@ angular.module('navigation').factory('userPageService', ['$injector',
var canManageUsers = [];
var canManageConnections = [];
+ var canViewConnectionRecords = [];
var canManageSessions = [];
// Inspect the contents of each provided permission set
@@ -234,12 +235,13 @@ angular.module('navigation').factory('userPageService', ['$injector',
)
canManageConnections.push(dataSource);
- // Determine whether the current user needs access to the session management UI
+ // Determine whether the current user needs access to the session management UI or view connection history
if (
// A user must be a system administrator to manage sessions
PermissionSet.hasSystemPermission(permissions, PermissionSet.SystemPermissionType.ADMINISTER)
)
canManageSessions.push(dataSource);
+ canViewConnectionRecords.push(dataSource);
});
@@ -250,7 +252,18 @@ angular.module('navigation').factory('userPageService', ['$injector',
url : '/settings/sessions'
}));
}
-
+
+ // If user can manage connections, add links for connection management pages
+ angular.forEach(canViewConnectionRecords, function addConnectionHistoryLink(dataSource) {
+ pages.push(new PageDefinition({
+ name : [
+ 'USER_MENU.ACTION_VIEW_HISTORY',
+ translationStringService.canonicalize('DATA_SOURCE_' + dataSource) + '.NAME'
+ ],
+ url : '/settings/' + encodeURIComponent(dataSource) + '/history'
+ }));
+ });
+
// If user can manage users, add link to user management page
if (canManageUsers.length) {
pages.push(new PageDefinition({
diff --git a/guacamole/src/main/webapp/app/rest/types/ConnectionHistoryEntry.js b/guacamole/src/main/webapp/app/rest/types/ConnectionHistoryEntry.js
index 1ffb78e37..7e892538c 100644
--- a/guacamole/src/main/webapp/app/rest/types/ConnectionHistoryEntry.js
+++ b/guacamole/src/main/webapp/app/rest/types/ConnectionHistoryEntry.js
@@ -48,6 +48,13 @@ angular.module('rest').factory('ConnectionHistoryEntry', [function defineConnect
*/
this.connectionIdentifier = template.connectionIdentifier;
+ /**
+ * The name of the connection associated with this history entry.
+ *
+ * @type String
+ */
+ this.connectionName = template.connectionName;
+
/**
* The time that usage began, in seconds since 1970-01-01 00:00:00 UTC.
*
@@ -107,7 +114,7 @@ angular.module('rest').factory('ConnectionHistoryEntry', [function defineConnect
* The name of the connection associated with the history entry (not
* the connection identifier).
*/
- CONNECTION_NAME : 'connection',
+ CONNECTION_NAME : 'connectionName',
/**
* The username of the user associated with the history entry (the user
diff --git a/guacamole/src/main/webapp/app/settings/directives/guacSettingsConnectionHistory.js b/guacamole/src/main/webapp/app/settings/directives/guacSettingsConnectionHistory.js
new file mode 100644
index 000000000..7de5587e1
--- /dev/null
+++ b/guacamole/src/main/webapp/app/settings/directives/guacSettingsConnectionHistory.js
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2015 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * A directive for viewing connection history records.
+ */
+angular.module('settings').directive('guacSettingsConnectionHistory', [function guacSettingsConnectionHistory() {
+
+ return {
+ // Element only
+ restrict: 'E',
+ replace: true,
+
+ scope: {
+ },
+
+ templateUrl: 'app/settings/templates/settingsConnectionHistory.html',
+ controller: ['$scope', '$injector', function settingsConnectionHistoryController($scope, $injector) {
+
+ // Get required types
+ var SortOrder = $injector.get('SortOrder');
+
+ // Get required services
+ var $routeParams = $injector.get('$routeParams');
+ var $translate = $injector.get('$translate');
+ var historyService = $injector.get('historyService');
+
+ /**
+ * The identifier of the currently-selected data source.
+ *
+ * @type String
+ */
+ $scope.dataSource = $routeParams.dataSource;
+
+ /**
+ * The identifier of the currently-selected data source.
+ *
+ * @type String
+ */
+ $scope.historyRecords = null;
+
+ /**
+ * The search terms to use when filtering the history records.
+ *
+ * @type String
+ */
+ $scope.searchString = '';
+
+ /**
+ * The date format for use for start/end dates.
+ *
+ * @type String
+ */
+ $scope.dateFormat = null;
+
+ /**
+ * SortOrder instance which stores the sort order of the history
+ * records.
+ *
+ * @type SortOrder
+ */
+ $scope.order = new SortOrder([
+ 'username',
+ 'startDate',
+ 'endDate',
+ 'connectionName'
+ ]);
+
+ // Get session date format
+ $translate('SETTINGS_CONNECTION_HISTORY.FORMAT_DATE')
+ .then(function dateFormatReceived(retrievedDateFormat) {
+
+ // Store received date format
+ $scope.dateFormat = retrievedDateFormat;
+
+ });
+
+ /**
+ * Returns true if the connection history records have been loaded,
+ * indicating that information needed to render the page is fully
+ * loaded.
+ *
+ * @returns {Boolean}
+ * true if the history records have been loaded, false
+ * otherwise.
+ *
+ */
+ $scope.isLoaded = function isLoaded() {
+ return $scope.historyRecords !== null
+ && $scope.dateFormat !== null;
+ };
+
+ /**
+ * Query the API for the connection record history, filtered by
+ * searchString, and ordered by order.
+ */
+ $scope.search = function search() {
+
+ // Clear current results
+ $scope.historyRecords = null;
+
+ // Fetch history records
+ historyService.getConnectionHistory(
+ $scope.dataSource,
+ $scope.searchString.split(/\s+/),
+ $scope.order.predicate
+ )
+ .success(function historyRetrieved(historyRecords) {
+
+ // Store retrieved permissions
+ $scope.historyRecords = historyRecords;
+
+ });
+
+ };
+
+ // Initialize search results
+ $scope.search();
+
+ }]
+ };
+
+}]);
diff --git a/guacamole/src/main/webapp/app/settings/styles/history.css b/guacamole/src/main/webapp/app/settings/styles/history.css
new file mode 100644
index 000000000..92e553baa
--- /dev/null
+++ b/guacamole/src/main/webapp/app/settings/styles/history.css
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+.settings.connectionHistory .filter {
+
+ /* IE10 */
+ display: -ms-flexbox;
+ -ms-flex-align: stretch;
+ -ms-flex-direction: row;
+
+ /* Ancient Mozilla */
+ display: -moz-box;
+ -moz-box-align: stretch;
+ -moz-box-orient: horizontal;
+
+ /* Ancient WebKit */
+ display: -webkit-box;
+ -webkit-box-align: stretch;
+ -webkit-box-orient: horizontal;
+
+ /* Old WebKit */
+ display: -webkit-flex;
+ -webkit-align-items: stretch;
+ -webkit-flex-direction: row;
+
+ /* W3C */
+ display: flex;
+ align-items: stretch;
+ flex-direction: row;
+
+}
+
+.settings.connectionHistory .filter .search-button {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+.settings.connectionHistory .history-list {
+ width: 100%;
+}
\ No newline at end of file
diff --git a/guacamole/src/main/webapp/app/settings/templates/settings.html b/guacamole/src/main/webapp/app/settings/templates/settings.html
index e138e6f68..9880ee29c 100644
--- a/guacamole/src/main/webapp/app/settings/templates/settings.html
+++ b/guacamole/src/main/webapp/app/settings/templates/settings.html
@@ -33,9 +33,10 @@ THE SOFTWARE.
-
-
-
-
+
+
+
+
+
diff --git a/guacamole/src/main/webapp/app/settings/templates/settingsConnectionHistory.html b/guacamole/src/main/webapp/app/settings/templates/settingsConnectionHistory.html
new file mode 100644
index 000000000..a27a2d06b
--- /dev/null
+++ b/guacamole/src/main/webapp/app/settings/templates/settingsConnectionHistory.html
@@ -0,0 +1,74 @@
+