mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-926: Migrate import code to a dedicated module.
This commit is contained in:
@@ -20,11 +20,11 @@
|
||||
/**
|
||||
* The controller for the connection import page.
|
||||
*/
|
||||
angular.module('settings').controller('importConnectionsController', ['$scope', '$injector',
|
||||
angular.module('import').controller('importConnectionsController', ['$scope', '$injector',
|
||||
function importConnectionsController($scope, $injector) {
|
||||
|
||||
// Required services
|
||||
const connectionImportParseService = $injector.get('connectionImportParseService');
|
||||
const connectionParseService = $injector.get('connectionParseService');
|
||||
const connectionService = $injector.get('connectionService');
|
||||
|
||||
function processData(type, data) {
|
||||
@@ -36,18 +36,18 @@ angular.module('settings').controller('importConnectionsController', ['$scope',
|
||||
|
||||
case "application/json":
|
||||
case "text/json":
|
||||
requestBody = connectionImportParseService.parseJSON(data);
|
||||
requestBody = connectionParseService.parseJSON(data);
|
||||
break;
|
||||
|
||||
case "text/csv":
|
||||
requestBody = connectionImportParseService.parseCSV(data);
|
||||
requestBody = connectionParseService.parseCSV(data);
|
||||
break;
|
||||
|
||||
case "application/yaml":
|
||||
case "application/x-yaml":
|
||||
case "text/yaml":
|
||||
case "text/x-yaml":
|
||||
requestBody = connectionImportParseService.parseYAML(data);
|
||||
requestBody = connectionParseService.parseYAML(data);
|
||||
break;
|
||||
|
||||
}
|
24
guacamole/src/main/frontend/src/app/import/importModule.js
Normal file
24
guacamole/src/main/frontend/src/app/import/importModule.js
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The module for code supporting importing user-supplied files. Currently, only
|
||||
* connection import is supported.
|
||||
*/
|
||||
angular.module('import', ['rest']);
|
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* global _ */
|
||||
|
||||
/**
|
||||
* A service for parsing user-provided CSV connection data for bulk import.
|
||||
*/
|
||||
angular.module('import').factory('connectionCSVService',
|
||||
['$injector', function connectionCSVService($injector) {
|
||||
|
||||
// Required services
|
||||
const $q = $injector.get('$q');
|
||||
const $routeParams = $injector.get('$routeParams');
|
||||
const schemaService = $injector.get('schemaService');
|
||||
|
||||
const service = {};
|
||||
|
||||
/**
|
||||
* Returns a promise that resolves to an object detailing the connection
|
||||
* attributes for the current data source, as well as the connection
|
||||
* paremeters for every protocol, for the current data source.
|
||||
*
|
||||
* The object that the promise will contain an "attributes" key that maps to
|
||||
* a set of attribute names, and a "protocolParameters" key that maps to an
|
||||
* object mapping protocol names to sets of parameter names for that protocol.
|
||||
*
|
||||
* The intended use case for this object is to determine if there is a
|
||||
* connection parameter or attribute with a given name, by e.g. checking the
|
||||
* path `.protocolParameters[protocolName]` to see if a protocol exists,
|
||||
* checking the path `.protocolParameters[protocolName][fieldName]` to see
|
||||
* if a parameter exists for a given protocol, or checking the path
|
||||
* `.attributes[fieldName]` to check if a connection attribute exists.
|
||||
*
|
||||
* @returns {Promise.<Object>}
|
||||
*/
|
||||
function getFieldLookups() {
|
||||
|
||||
// The current data source - the one that the connections will be
|
||||
// imported into
|
||||
const dataSource = $routeParams.dataSource;
|
||||
|
||||
// Fetch connection attributes and protocols for the current data source
|
||||
return $q.all({
|
||||
attributes : schemaService.getConnectionAttributes(dataSource),
|
||||
protocols : schemaService.getProtocols(dataSource)
|
||||
})
|
||||
.then(function connectionStructureRetrieved({attributes, protocols}) {
|
||||
|
||||
return {
|
||||
|
||||
// Translate the forms and fields into a flat map of attribute
|
||||
// name to `true` boolean value
|
||||
attributes: attributes.reduce(
|
||||
(attributeMap, form) => {
|
||||
form.fields.forEach(
|
||||
field => attributeMap[field.name] = true);
|
||||
return attributeMap
|
||||
}, {}),
|
||||
|
||||
// Translate the protocol definitions into a map of protocol
|
||||
// name to map of field name to `true` boolean value
|
||||
protocolParameters: _.mapValues(
|
||||
protocols, protocol => protocol.connectionForms.reduce(
|
||||
(protocolFieldMap, form) => {
|
||||
form.fields.forEach(
|
||||
field => protocolFieldMap[field.name] = true);
|
||||
return protocolFieldMap;
|
||||
}, {}))
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @returns {Promise.<Function.<String[], Object>>}
|
||||
* A promise that will resolve to a function that translates a CSV data
|
||||
* row (array of strings) to a connection object.
|
||||
*/
|
||||
service.getCSVTransformer = function getCSVTransformer(headerRow) {
|
||||
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}]);
|
@@ -26,8 +26,8 @@ import { parse as parseYAMLData } from 'yaml'
|
||||
* A service for parsing user-provided JSON, YAML, or JSON connection data into
|
||||
* an appropriate format for bulk uploading using the PATCH REST endpoint.
|
||||
*/
|
||||
angular.module('settings').factory('connectionImportParseService',
|
||||
['$injector', function connectionImportParseService($injector) {
|
||||
angular.module('import').factory('connectionParseService',
|
||||
['$injector', function connectionParseService($injector) {
|
||||
|
||||
// Required types
|
||||
const Connection = $injector.get('Connection');
|
||||
@@ -71,35 +71,6 @@ angular.module('settings').factory('connectionImportParseService',
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a provided YAML representation of a connection list into a JSON
|
||||
* string to be submitted to the PATCH REST endpoint. The returned JSON
|
||||
* string will contain a PATCH operation to create each connection in the
|
||||
* provided list.
|
||||
*
|
||||
* @param {String} yamlData
|
||||
* The YAML-encoded connection list to convert to a PATCH request body.
|
||||
*
|
||||
* @return {Promise.<Connection[]>}
|
||||
* A promise resolving to an array of Connection objects, one for each
|
||||
* connection in the provided CSV.
|
||||
*/
|
||||
service.parseYAML = function parseYAML(yamlData) {
|
||||
|
||||
// Parse from YAML into a javascript array
|
||||
const parsedData = parseYAMLData(yamlData);
|
||||
|
||||
// Check that the data is the correct format, and not empty
|
||||
performBasicChecks(parsedData);
|
||||
|
||||
// Convert to an array of Connection objects and return
|
||||
const deferredConnections = $q.defer();
|
||||
deferredConnections.resolve(
|
||||
parsedData.map(connection => new Connection(connection)));
|
||||
return deferredConnections.promise;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a promise that resolves to an object detailing the connection
|
||||
@@ -321,6 +292,35 @@ angular.module('settings').factory('connectionImportParseService',
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a provided YAML representation of a connection list into a JSON
|
||||
* string to be submitted to the PATCH REST endpoint. The returned JSON
|
||||
* string will contain a PATCH operation to create each connection in the
|
||||
* provided list.
|
||||
*
|
||||
* @param {String} yamlData
|
||||
* The YAML-encoded connection list to convert to a PATCH request body.
|
||||
*
|
||||
* @return {Promise.<Connection[]>}
|
||||
* A promise resolving to an array of Connection objects, one for each
|
||||
* connection in the provided CSV.
|
||||
*/
|
||||
service.parseYAML = function parseYAML(yamlData) {
|
||||
|
||||
// Parse from YAML into a javascript array
|
||||
const parsedData = parseYAMLData(yamlData);
|
||||
|
||||
// Check that the data is the correct format, and not empty
|
||||
performBasicChecks(parsedData);
|
||||
|
||||
// Convert to an array of Connection objects and return
|
||||
const deferredConnections = $q.defer();
|
||||
deferredConnections.resolve(
|
||||
parsedData.map(connection => new Connection(connection)));
|
||||
return deferredConnections.promise;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a provided JSON representation of a connection list into a JSON
|
||||
* string to be submitted to the PATCH REST endpoint. The returned JSON
|
@@ -20,7 +20,7 @@
|
||||
/**
|
||||
* Service which defines the ParseError class.
|
||||
*/
|
||||
angular.module('settings').factory('ParseError', [function defineParseError() {
|
||||
angular.module('import').factory('ParseError', [function defineParseError() {
|
||||
|
||||
/**
|
||||
* An error representing a parsing failure when attempting to convert
|
@@ -127,10 +127,10 @@ angular.module('index').config(['$routeProvider', '$locationProvider',
|
||||
})
|
||||
|
||||
// Connection import page
|
||||
.when('/settings/:dataSource/import', {
|
||||
.when('/import/:dataSource/connection', {
|
||||
title : 'APP.NAME',
|
||||
bodyClassName : 'settings',
|
||||
templateUrl : 'app/settings/templates/settingsImport.html',
|
||||
templateUrl : 'app/import/templates/connectionImport.html',
|
||||
controller : 'importConnectionsController',
|
||||
resolve : { updateCurrentToken: updateCurrentToken }
|
||||
})
|
||||
|
@@ -156,41 +156,38 @@ angular.module('rest').factory('connectionService', ['$injector',
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to create multiple connections, returning a
|
||||
* a promise that can be used for processing the results of the call. This
|
||||
* operation is atomic - if any errors are encountered during the connection
|
||||
* creation process, the entire request will fail, and no connections will be
|
||||
* created.
|
||||
* Makes a request to the REST API to apply a supplied list of connection
|
||||
* patches, returning a promise that can be used for processing the results
|
||||
* of the call.
|
||||
*
|
||||
* This operation is atomic - if any errors are encountered during the
|
||||
* connection patching process, the entire request will fail, and no
|
||||
* changes will be persisted.
|
||||
*
|
||||
* @param {Connection[]} connections The connections to create.
|
||||
* @param {DirectoryPatch.<Connection>[]} patches
|
||||
* An array of patches to apply.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* create operation is successful.
|
||||
* patch operation is successful.
|
||||
*/
|
||||
service.createConnections = function createConnections(dataSource, connections) {
|
||||
service.patchConnections = function patchConnections(dataSource, patches) {
|
||||
|
||||
// An object containing a PATCH operation to create each connection
|
||||
const patchBody = connections.map(connection => ({
|
||||
op: "add",
|
||||
path: "/",
|
||||
value: connection
|
||||
}));
|
||||
|
||||
// Make a PATCH request to create the connections
|
||||
// Make the PATCH request
|
||||
return authenticationService.request({
|
||||
method : 'PATCH',
|
||||
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connections',
|
||||
data : patchBody
|
||||
data : patches
|
||||
})
|
||||
|
||||
// Clear the cache
|
||||
.then(function connectionUpdated(){
|
||||
.then(function connectionsPatched(){
|
||||
cacheService.connections.removeAll();
|
||||
|
||||
// Clear users cache to force reload of permissions for this
|
||||
// newly updated connection
|
||||
// Clear users cache to force reload of permissions for any
|
||||
// newly created or replaced connections
|
||||
cacheService.users.removeAll();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service which defines the DirectoryPatch class.
|
||||
*/
|
||||
angular.module('rest').factory('DirectoryPatch', [function defineDirectoryPatch() {
|
||||
|
||||
/**
|
||||
* The object consumed by REST API calls when representing changes to an
|
||||
* arbitrary set of directory-based objects.
|
||||
* @constructor
|
||||
*
|
||||
* @template DirectoryObject
|
||||
* The directory-based object type that this DirectoryPatch will
|
||||
* operate on.
|
||||
*
|
||||
* @param {DirectoryObject|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* DirectoryPatch.
|
||||
*/
|
||||
var DirectoryPatch = function DirectoryPatch(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The operation to apply to the objects indicated by the path. Valid
|
||||
* operation values are defined within DirectoryPatch.Operation.
|
||||
*
|
||||
* @type {String}
|
||||
*/
|
||||
this.op = template.op;
|
||||
|
||||
/**
|
||||
* The path of the objects to modify. For creation of new objects, this
|
||||
* should be "/". Otherwise, it should be "/{identifier}", specifying
|
||||
* the identifier of the existing object being modified.
|
||||
*
|
||||
* @type {String}
|
||||
* @default '/'
|
||||
*/
|
||||
this.path = template.path || '/';
|
||||
|
||||
/**
|
||||
* The object being added or replaced, or the identifier of the object
|
||||
* being removed.
|
||||
*
|
||||
* @type {DirectoryObject|String}
|
||||
*/
|
||||
this.value = template.value;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* All valid patch operations for directory-based objects.
|
||||
*/
|
||||
DirectoryPatch.Operation = {
|
||||
|
||||
/**
|
||||
* Adds the specified object to the relation.
|
||||
*/
|
||||
ADD : "add",
|
||||
|
||||
/**
|
||||
* Removes the specified object from the relation.
|
||||
*/
|
||||
REPLACE : "replace",
|
||||
|
||||
/**
|
||||
* Removes the specified object from the relation.
|
||||
*/
|
||||
REMOVE : "remove"
|
||||
|
||||
};
|
||||
|
||||
return DirectoryPatch;
|
||||
|
||||
}]);
|
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service which defines the DirectoryPatchOutcome class.
|
||||
*/
|
||||
angular.module('rest').factory('DirectoryPatchOutcome', [
|
||||
function defineDirectoryPatchOutcome() {
|
||||
|
||||
/**
|
||||
* An object returned by a PATCH request to a directory REST API,
|
||||
* representing the outcome associated with a particular patch in the
|
||||
* request. This object can indicate either a successful or unsuccessful
|
||||
* response. The error field is only meaningful for unsuccessful patches.
|
||||
* @constructor
|
||||
*
|
||||
* @template DirectoryObject
|
||||
* The directory-based object type that this DirectoryPatchOutcome
|
||||
* represents a patch outcome for.
|
||||
*
|
||||
* @param {DirectoryObject|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* DirectoryPatchOutcome.
|
||||
*/
|
||||
var DirectoryPatchOutcome = function DirectoryPatchOutcome(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The operation to apply to the objects indicated by the path. Valid
|
||||
* operation values are defined within DirectoryPatch.Operation.
|
||||
*
|
||||
* @type {String}
|
||||
*/
|
||||
this.op = template.op;
|
||||
|
||||
/**
|
||||
* The path of the object operated on by the corresponding patch in the
|
||||
* request.
|
||||
*
|
||||
* @type {String}
|
||||
*/
|
||||
this.path = template.path;
|
||||
|
||||
/**
|
||||
* The identifier of the object operated on by the corresponding patch
|
||||
* in the request. If the object was newly created and the PATCH request
|
||||
* did not fail, this will be the identifier of the newly created object.
|
||||
*
|
||||
* @type {String}
|
||||
*/
|
||||
this.identifier = template.identifier;
|
||||
|
||||
/**
|
||||
* The error message associated with the failure, if the patch failed to
|
||||
* apply.
|
||||
*
|
||||
* @type {String}
|
||||
*/
|
||||
this.error = template.error;
|
||||
|
||||
};
|
||||
|
||||
return DirectoryPatch;
|
||||
|
||||
}]);
|
Reference in New Issue
Block a user