From 4059054d31fddc8b7c7f7632eb5b991966ff74aa Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 6 Apr 2016 22:37:15 -0700 Subject: [PATCH 1/5] GUACAMOLE-44: Replace use of ManagedFileDownload with calls to the tunnel REST service. --- .../client/controllers/clientController.js | 2 +- .../directives/guacFileTransferManager.js | 5 - .../webapp/app/client/types/ManagedClient.js | 15 +- .../app/client/types/ManagedFileDownload.js | 153 ------------------ .../app/client/types/ManagedFilesystem.js | 11 +- 5 files changed, 8 insertions(+), 178 deletions(-) delete mode 100644 guacamole/src/main/webapp/app/client/types/ManagedFileDownload.js diff --git a/guacamole/src/main/webapp/app/client/controllers/clientController.js b/guacamole/src/main/webapp/app/client/controllers/clientController.js index 0c7145a88..daa782229 100644 --- a/guacamole/src/main/webapp/app/client/controllers/clientController.js +++ b/guacamole/src/main/webapp/app/client/controllers/clientController.js @@ -755,7 +755,7 @@ angular.module('client').controller('clientController', ['$scope', '$routeParams if (!$scope.client) return false; - return !!($scope.client.uploads.length || $scope.client.downloads.length); + return !!$scope.client.uploads.length; }; diff --git a/guacamole/src/main/webapp/app/client/directives/guacFileTransferManager.js b/guacamole/src/main/webapp/app/client/directives/guacFileTransferManager.js index ac810d04c..002494865 100644 --- a/guacamole/src/main/webapp/app/client/directives/guacFileTransferManager.js +++ b/guacamole/src/main/webapp/app/client/directives/guacFileTransferManager.js @@ -83,11 +83,6 @@ angular.module('client').directive('guacFileTransferManager', [function guacFile return isInProgress(upload.transferState); }); - // Remove completed downloads - $scope.client.downloads = $scope.client.downloads.filter(function isDownloadInProgress(download) { - return isInProgress(download.transferState); - }); - }; }] diff --git a/guacamole/src/main/webapp/app/client/types/ManagedClient.js b/guacamole/src/main/webapp/app/client/types/ManagedClient.js index 9a3ffb1c4..128cf904d 100644 --- a/guacamole/src/main/webapp/app/client/types/ManagedClient.js +++ b/guacamole/src/main/webapp/app/client/types/ManagedClient.js @@ -28,7 +28,6 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', var ClientIdentifier = $injector.get('ClientIdentifier'); var ManagedClientState = $injector.get('ManagedClientState'); var ManagedDisplay = $injector.get('ManagedDisplay'); - var ManagedFileDownload = $injector.get('ManagedFileDownload'); var ManagedFilesystem = $injector.get('ManagedFilesystem'); var ManagedFileUpload = $injector.get('ManagedFileUpload'); @@ -41,6 +40,7 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', var clipboardService = $injector.get('clipboardService'); var connectionGroupService = $injector.get('connectionGroupService'); var connectionService = $injector.get('connectionService'); + var tunnelService = $injector.get('tunnelService'); var guacAudio = $injector.get('guacAudio'); var guacHistory = $injector.get('guacHistory'); var guacImage = $injector.get('guacImage'); @@ -104,15 +104,6 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', */ this.clipboardData = template.clipboardData || ''; - /** - * All downloaded files. As files are downloaded, their progress can be - * observed through the elements of this array. It is intended that - * this array be manipulated externally as needed. - * - * @type ManagedFileDownload[] - */ - this.downloads = template.downloads || []; - /** * All uploaded files. As files are uploaded, their progress can be * observed through the elements of this array. It is intended that @@ -453,9 +444,7 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', // Handle any received files client.onfile = function clientFileReceived(stream, mimetype, filename) { - $rootScope.$apply(function startDownload() { - managedClient.downloads.push(ManagedFileDownload.getInstance(stream, mimetype, filename)); - }); + tunnelService.downloadStream(tunnel.uuid, stream, mimetype, filename); }; // Handle any received filesystem objects diff --git a/guacamole/src/main/webapp/app/client/types/ManagedFileDownload.js b/guacamole/src/main/webapp/app/client/types/ManagedFileDownload.js deleted file mode 100644 index 35f683b1f..000000000 --- a/guacamole/src/main/webapp/app/client/types/ManagedFileDownload.js +++ /dev/null @@ -1,153 +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. - */ - -/** - * Provides the ManagedFileDownload class used by the guacClientManager service. - */ -angular.module('client').factory('ManagedFileDownload', ['$rootScope', '$injector', - function defineManagedFileDownload($rootScope, $injector) { - - // Required types - var ManagedFileTransferState = $injector.get('ManagedFileTransferState'); - - /** - * Object which serves as a surrogate interface, encapsulating a Guacamole - * file download while it is active, allowing it to be detached and - * reattached from different client views. - * - * @constructor - * @param {ManagedFileDownload|Object} [template={}] - * The object whose properties should be copied within the new - * ManagedFileDownload. - */ - var ManagedFileDownload = function ManagedFileDownload(template) { - - // Use empty object by default - template = template || {}; - - /** - * The current state of the file transfer stream. - * - * @type ManagedFileTransferState - */ - this.transferState = template.transferState || new ManagedFileTransferState(); - - /** - * The mimetype of the file being transferred. - * - * @type String - */ - this.mimetype = template.mimetype; - - /** - * The filename of the file being transferred. - * - * @type String - */ - this.filename = template.filename; - - /** - * The number of bytes transferred so far. - * - * @type Number - */ - this.progress = template.progress; - - /** - * A blob containing the complete downloaded file. This is available - * only after the download has finished. - * - * @type Blob - */ - this.blob = template.blob; - - }; - - /** - * Creates a new ManagedFileDownload which downloads the contents of the - * given stream as a file having the given mimetype and filename. - * - * @param {Guacamole.InputStream} stream - * The stream whose contents should be downloaded as a file. - * - * @param {String} mimetype - * The mimetype of the stream contents. - * - * @param {String} filename - * The filename of the file being received over the steram. - * - * @return {ManagedFileDownload} - * A new ManagedFileDownload object which can be used to track the - * progress of the download. - */ - ManagedFileDownload.getInstance = function getInstance(stream, mimetype, filename) { - - // Init new file download object - var managedFileDownload = new ManagedFileDownload({ - mimetype : mimetype, - filename : filename, - progress : 0, - transferState : new ManagedFileTransferState({ - streamState : ManagedFileTransferState.StreamState.OPEN - }) - }); - - // Begin file download - var blob_reader = new Guacamole.BlobReader(stream, mimetype); - - // Update progress as data is received - blob_reader.onprogress = function onprogress() { - - // Update progress - $rootScope.$apply(function downloadStreamProgress() { - managedFileDownload.progress = blob_reader.getLength(); - }); - - // Signal server that data was received - stream.sendAck("Received", Guacamole.Status.Code.SUCCESS); - - }; - - // Save blob and close stream when complete - blob_reader.onend = function onend() { - $rootScope.$apply(function downloadStreamEnd() { - - // Save blob - managedFileDownload.blob = blob_reader.getBlob(); - - // Mark stream as closed - ManagedFileTransferState.setStreamState(managedFileDownload.transferState, - ManagedFileTransferState.StreamState.CLOSED); - - // Notify of upload completion - $rootScope.$broadcast('guacDownloadComplete', filename); - - }); - }; - - // Signal server that data is ready to be received - stream.sendAck("Ready", Guacamole.Status.Code.SUCCESS); - - return managedFileDownload; - - }; - - return ManagedFileDownload; - -}]); \ No newline at end of file diff --git a/guacamole/src/main/webapp/app/client/types/ManagedFilesystem.js b/guacamole/src/main/webapp/app/client/types/ManagedFilesystem.js index 4b49aeb9e..7bd45096d 100644 --- a/guacamole/src/main/webapp/app/client/types/ManagedFilesystem.js +++ b/guacamole/src/main/webapp/app/client/types/ManagedFilesystem.js @@ -25,8 +25,7 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector' function defineManagedFilesystem($rootScope, $injector) { // Required types - var ManagedFileDownload = $injector.get('ManagedFileDownload'); - var ManagedFileUpload = $injector.get('ManagedFileUpload'); + var tunnelService = $injector.get('tunnelService'); /** * Object which serves as a surrogate interface, encapsulating a Guacamole @@ -194,8 +193,8 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector' /** * Downloads the given file from the server using the given Guacamole - * client and filesystem. The file transfer can be monitored through the - * corresponding entry in the downloads array of the given ManagedClient. + * client and filesystem. The browser will automatically start the + * download upon completion of this function. * * @param {ManagedClient} managedClient * The ManagedClient from which the file is to be downloaded. @@ -215,8 +214,8 @@ angular.module('client').factory('ManagedFilesystem', ['$rootScope', '$injector' // Parse filename from string var filename = path.match(/(.*[\\/])?(.*)/)[2]; - // Start and track download - managedClient.downloads.push(ManagedFileDownload.getInstance(stream, mimetype, filename)); + // Start download + tunnelService.downloadStream(managedClient.tunnel.uuid, stream, mimetype, filename); }); From f207b29cc6480c8d2aeaa3be39f5c1594858dbbb Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 5 Jun 2016 16:16:53 -0700 Subject: [PATCH 2/5] GUACAMOLE-44: Use tunnel REST service for file uploads. --- .../webapp/app/client/types/ManagedClient.js | 2 +- .../app/client/types/ManagedFileUpload.js | 85 ++++++++++--------- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/guacamole/src/main/webapp/app/client/types/ManagedClient.js b/guacamole/src/main/webapp/app/client/types/ManagedClient.js index 128cf904d..9a2870687 100644 --- a/guacamole/src/main/webapp/app/client/types/ManagedClient.js +++ b/guacamole/src/main/webapp/app/client/types/ManagedClient.js @@ -519,7 +519,7 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector', } // Start and manage file upload - managedClient.uploads.push(ManagedFileUpload.getInstance(managedClient.client, file, object, streamName)); + managedClient.uploads.push(ManagedFileUpload.getInstance(managedClient, file, object, streamName)); }; diff --git a/guacamole/src/main/webapp/app/client/types/ManagedFileUpload.js b/guacamole/src/main/webapp/app/client/types/ManagedFileUpload.js index 7fe4f3579..06fabbb14 100644 --- a/guacamole/src/main/webapp/app/client/types/ManagedFileUpload.js +++ b/guacamole/src/main/webapp/app/client/types/ManagedFileUpload.js @@ -24,10 +24,12 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector' function defineManagedFileUpload($rootScope, $injector) { // Required types + var Error = $injector.get('Error'); var ManagedFileTransferState = $injector.get('ManagedFileTransferState'); // Required services - var $window = $injector.get('$window'); + var $window = $injector.get('$window'); + var tunnelService = $injector.get('tunnelService'); /** * Object which serves as a surrogate interface, encapsulating a Guacamole @@ -105,8 +107,8 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector' * Creates a new ManagedFileUpload which uploads the given file to the * server through the given Guacamole client. * - * @param {Guacamole.Client} client - * The Guacamole client through which the file is to be uploaded. + * @param {ManagedClient} managedClient + * The ManagedClient through which the file is to be uploaded. * * @param {File} file * The file to upload. @@ -123,10 +125,13 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector' * A new ManagedFileUpload object which can be used to track the * progress of the upload. */ - ManagedFileUpload.getInstance = function getInstance(client, file, object, streamName) { + ManagedFileUpload.getInstance = function getInstance(managedClient, file, object, streamName) { var managedFileUpload = new ManagedFileUpload(); - var streamAcknowledged = false; + + // Pull Guacamole.Tunnel and Guacamole.Client from given ManagedClient + var client = managedClient.client; + var tunnel = managedClient.tunnel; // Open file for writing var stream; @@ -153,10 +158,8 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector' }); - var writer = new Guacamole.FileWriter(stream); - - // Begin upload when stream is acknowledged, notify of any errors - writer.onack = function ackReceived(status) { + // Upload file once stream is acknowledged + stream.onack = function beginUpload(status) { // Notify of any errors from the Guacamole server if (status.isError()) { @@ -165,50 +168,48 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector' ManagedFileTransferState.StreamState.ERROR, status.code); }); + return; } - // Begin sending the requested file once stream is acknowledged - else if (!streamAcknowledged) { - writer.sendFile(file); - streamAcknowledged = true; - } + // Begin upload + tunnelService.uploadToStream(tunnel.uuid, stream, file, function uploadContinuing(length) { + $rootScope.$apply(function uploadStreamProgress() { + managedFileUpload.progress = length; + }); + }) - }; + // Notify if upload succeeds + .then(function uploadSuccessful() { - // Abort and notify if the file cannot be read - writer.onerror = function fileReadError(file, offset, error) { + // Upload complete + managedFileUpload.progress = file.size; + ManagedFileTransferState.setStreamState(managedFileUpload.transferState, + ManagedFileTransferState.StreamState.CLOSED); - // Abort transfer - writer.sendEnd(); + // Notify of upload completion + $rootScope.$broadcast('guacUploadComplete', file.name); - // Upload failed - ManagedFileTransferState.setStreamState(managedFileUpload.transferState, - ManagedFileTransferState.StreamState.ERROR); + }, - }; + // Notify if upload fails + function uploadFailed(error) { - // Notify of upload progress - writer.onprogress = function uploadProgressing(file, length) { + // Use provide status code if the error is coming from the stream + if (error.type === Error.Type.STREAM_ERROR) + ManagedFileTransferState.setStreamState(managedFileUpload.transferState, + ManagedFileTransferState.StreamState.ERROR, + error.statusCode); + + // Fail with internal error for all other causes + else + ManagedFileTransferState.setStreamState(managedFileUpload.transferState, + ManagedFileTransferState.StreamState.ERROR, + Guacamole.Status.Code.INTERNAL_ERROR); - $rootScope.$apply(function uploadStreamProgress() { - managedFileUpload.progress = length; }); - }; - - // Clean up and notify when upload completes - writer.oncomplete = function uploadComplete(file) { - - // If at end, stop upload - writer.sendEnd(); - managedFileUpload.progress = file.size; - - // Upload complete - ManagedFileTransferState.setStreamState(managedFileUpload.transferState, - ManagedFileTransferState.StreamState.CLOSED); - - // Notify of upload completion - $rootScope.$broadcast('guacUploadComplete', file.name); + // Ignore all further acks + stream.onack = null; }; From 0b6faba25882b50ba5d0ed1a67a34f2f54e09fba Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Sun, 5 Jun 2016 17:00:46 -0700 Subject: [PATCH 3/5] GUACAMOLE-44: Remove now-unnecessary getBase64() implementation within ManagedFileUpload (base64 conversion is handled by REST service). --- .../app/client/types/ManagedFileUpload.js | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/guacamole/src/main/webapp/app/client/types/ManagedFileUpload.js b/guacamole/src/main/webapp/app/client/types/ManagedFileUpload.js index 06fabbb14..82bface4d 100644 --- a/guacamole/src/main/webapp/app/client/types/ManagedFileUpload.js +++ b/guacamole/src/main/webapp/app/client/types/ManagedFileUpload.js @@ -28,7 +28,6 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector' var ManagedFileTransferState = $injector.get('ManagedFileTransferState'); // Required services - var $window = $injector.get('$window'); var tunnelService = $injector.get('tunnelService'); /** @@ -83,26 +82,6 @@ angular.module('client').factory('ManagedFileUpload', ['$rootScope', '$injector' }; - /** - * Converts the given bytes to a base64-encoded string. - * - * @param {Uint8Array} bytes A Uint8Array which contains the data to be - * encoded as base64. - * @return {String} The base64-encoded string. - */ - var getBase64 = function getBase64(bytes) { - - var data = ""; - - // Produce binary string from bytes in buffer - for (var i=0; i Date: Tue, 14 Jun 2016 13:16:18 -0600 Subject: [PATCH 4/5] GUACAMOLE-50: Update Docker container to use Java 8 --- guacamole-docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guacamole-docker/Dockerfile b/guacamole-docker/Dockerfile index 36d39b245..a3b2941c7 100644 --- a/guacamole-docker/Dockerfile +++ b/guacamole-docker/Dockerfile @@ -22,7 +22,7 @@ # # Start from Tomcat image -FROM tomcat:8.0.20-jre7 +FROM tomcat:8.0.20-jre8 MAINTAINER Michael Jumper # Version info From f4a3c5b31e410fa03463064df7a8eb144d2fd9cf Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Wed, 27 Apr 2016 13:12:31 -0700 Subject: [PATCH 5/5] GUACAMOLE-52: Foreign keys in history table should be ON DELETE SET NULL. For sake of context, always store username and connection name in history table. --- .../AbstractGuacamoleTunnelService.java | 5 +- .../schema/001-create-schema.sql | 12 +-- .../schema/upgrade/upgrade-pre-0.9.10.sql | 89 ++++++++++++++++++ .../connection/ConnectionRecordMapper.xml | 27 +++--- .../schema/001-create-schema.sql | 12 +-- .../schema/upgrade/upgrade-pre-0.9.10.sql | 90 +++++++++++++++++++ .../connection/ConnectionRecordMapper.xml | 29 +++--- 7 files changed, 225 insertions(+), 39 deletions(-) create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.10.sql create mode 100644 extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-postgresql/schema/upgrade/upgrade-pre-0.9.10.sql diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java index 482a2fab1..95d5ab640 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/tunnel/AbstractGuacamoleTunnelService.java @@ -246,13 +246,12 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS // Get associated models AuthenticatedUser user = record.getUser(); - UserModel userModel = user.getUser().getModel(); ConnectionRecordModel recordModel = new ConnectionRecordModel(); // Copy user information and timestamps into new record - recordModel.setUserID(userModel.getObjectID()); - recordModel.setUsername(userModel.getIdentifier()); + recordModel.setUsername(user.getIdentifier()); recordModel.setConnectionIdentifier(connection.getIdentifier()); + recordModel.setConnectionName(connection.getName()); recordModel.setStartDate(record.getStartDate()); recordModel.setEndDate(new Date()); diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql index 339236a0b..6982896ff 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/001-create-schema.sql @@ -230,11 +230,13 @@ CREATE TABLE `guacamole_user_permission` ( CREATE TABLE `guacamole_connection_history` ( - `history_id` int(11) NOT NULL AUTO_INCREMENT, - `user_id` int(11) NOT NULL, - `connection_id` int(11) NOT NULL, - `start_date` datetime NOT NULL, - `end_date` datetime DEFAULT NULL, + `history_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) DEFAULT NULL, + `username` varchar(128) NOT NULL, + `connection_id` int(11) DEFAULT NULL, + `connection_name` varchar(128) NOT NULL, + `start_date` datetime NOT NULL, + `end_date` datetime DEFAULT NULL, PRIMARY KEY (`history_id`), KEY `user_id` (`user_id`), diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.10.sql b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.10.sql new file mode 100644 index 000000000..f69ba41b5 --- /dev/null +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/upgrade/upgrade-pre-0.9.10.sql @@ -0,0 +1,89 @@ +-- +-- 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. +-- + +-- +-- User and connection IDs within history table can now be null +-- + +ALTER TABLE guacamole_connection_history + MODIFY COLUMN user_id INT(11) DEFAULT NULL; + +ALTER TABLE guacamole_connection_history + MODIFY COLUMN connection_id INT(11) DEFAULT NULL; + +-- +-- Add new username and connection_name columns to history table +-- + +ALTER TABLE guacamole_connection_history + ADD COLUMN username VARCHAR(128); + +ALTER TABLE guacamole_connection_history + ADD COLUMN connection_name VARCHAR(128); + +-- +-- Populate new name columns by joining corresponding tables +-- + +UPDATE guacamole_connection_history +JOIN guacamole_user + ON guacamole_user.user_id = guacamole_connection_history.user_id +SET guacamole_connection_history.username = guacamole_user.username; + +UPDATE guacamole_connection_history +JOIN guacamole_connection + ON guacamole_connection.connection_id = + guacamole_connection_history.connection_id +SET guacamole_connection_history.connection_name = + guacamole_connection.connection_name; + +-- +-- Set NOT NULL now that the column is fully populated +-- + +ALTER TABLE guacamole_connection_history + MODIFY username VARCHAR(128) NOT NULL; + +ALTER TABLE guacamole_connection_history + MODIFY connection_name VARCHAR(128) NOT NULL; + +-- +-- Remove old foreign key constraints with ON DELETE CASCADE +-- + +ALTER TABLE guacamole_connection_history + DROP FOREIGN KEY guacamole_connection_history_ibfk_1; + +ALTER TABLE guacamole_connection_history + DROP FOREIGN KEY guacamole_connection_history_ibfk_2; + +-- +-- Recreate foreign key constraints with ON DELETE SET NULL +-- + +ALTER TABLE guacamole_connection_history + ADD CONSTRAINT guacamole_connection_history_ibfk_1 + FOREIGN KEY (user_id) + REFERENCES guacamole_user (user_id) ON DELETE SET NULL; + +ALTER TABLE guacamole_connection_history + ADD CONSTRAINT guacamole_connection_history_ibfk_2 + FOREIGN KEY (connection_id) + REFERENCES guacamole_connection (connection_id) ON DELETE SET NULL; + diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml index d1825fab6..3adcde2c2 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/src/main/resources/org/apache/guacamole/auth/jdbc/connection/ConnectionRecordMapper.xml @@ -37,17 +37,15 @@ SELECT - guacamole_connection.connection_id, - guacamole_connection.connection_name, - guacamole_user.user_id, - guacamole_user.username, + guacamole_connection_history.connection_id, + guacamole_connection_history.connection_name, + guacamole_connection_history.user_id, + guacamole_connection_history.username, guacamole_connection_history.start_date, guacamole_connection_history.end_date FROM guacamole_connection_history - JOIN guacamole_connection ON guacamole_connection_history.connection_id = guacamole_connection.connection_id - JOIN guacamole_user ON guacamole_connection_history.user_id = guacamole_user.user_id WHERE - guacamole_connection.connection_id = #{identifier,jdbcType=INTEGER}::integer + guacamole_connection_history.connection_id = #{identifier,jdbcType=INTEGER}::integer ORDER BY guacamole_connection_history.start_date DESC, guacamole_connection_history.end_date DESC @@ -59,13 +57,18 @@ INSERT INTO guacamole_connection_history ( connection_id, + connection_name, user_id, + username, start_date, end_date ) VALUES ( #{record.connectionIdentifier,jdbcType=INTEGER}::integer, - #{record.userID,jdbcType=INTEGER}, + #{record.connectionName,jdbcType=VARCHAR}, + (SELECT user_id FROM guacamole_user + WHERE username = #{record.username,jdbcType=VARCHAR}), + #{record.username,jdbcType=VARCHAR}, #{record.startDate,jdbcType=TIMESTAMP}, #{record.endDate,jdbcType=TIMESTAMP} ) @@ -77,14 +80,12 @@ SELECT guacamole_connection_history.connection_id, - guacamole_connection.connection_name, + guacamole_connection_history.connection_name, guacamole_connection_history.user_id, - guacamole_user.username, + guacamole_connection_history.username, guacamole_connection_history.start_date, guacamole_connection_history.end_date FROM guacamole_connection_history - LEFT JOIN guacamole_connection ON guacamole_connection_history.connection_id = guacamole_connection.connection_id - LEFT JOIN guacamole_user ON guacamole_connection_history.user_id = guacamole_user.user_id