mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 17:13:21 +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