diff --git a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java index 20861bae98..a9000939f2 100644 --- a/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java +++ b/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-base/src/main/java/org/apache/guacamole/auth/jdbc/connection/ModeledConnection.java @@ -26,7 +26,6 @@ import java.util.Collections; import java.util.Date; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService; diff --git a/extensions/guacamole-template-ext/.gitignore b/extensions/guacamole-template-ext/.gitignore new file mode 100644 index 0000000000..1de9633aed --- /dev/null +++ b/extensions/guacamole-template-ext/.gitignore @@ -0,0 +1,3 @@ +src/main/resources/generated/ +target/ +*~ diff --git a/extensions/guacamole-template-ext/.ratignore b/extensions/guacamole-template-ext/.ratignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/extensions/guacamole-template-ext/pom.xml b/extensions/guacamole-template-ext/pom.xml new file mode 100644 index 0000000000..5c56228435 --- /dev/null +++ b/extensions/guacamole-template-ext/pom.xml @@ -0,0 +1,148 @@ + + + + + 4.0.0 + org.apache.guacamole + guacamole-template-ext + jar + 1.5.2 + guacamole-template-ext + http://guacamole.apache.org/ + + + org.apache.guacamole + extensions + 1.5.2 + ../ + + + + + + + + com.keithbranton.mojo + angular-maven-plugin + 0.3.4 + + + generate-resources + + html2js + + + + + ${basedir}/src/main/resources + **/*.html + ${basedir}/src/main/resources/generated/templates-main/templates.js + app/ext/template-ext + + + + + + com.github.buckelieg + minify-maven-plugin + + + default-cli + + UTF-8 + + ${basedir}/src/main/resources + ${project.build.directory}/classes + + / + / + templateExt.css + + + license.txt + + + + **/*.css + + + / + / + templateExt.js + + + license.txt + + + + **/*.js + + + + + **/*.test.js + + CLOSURE + + + + OFF + OFF + + + + + minify + + + + + + + + + + + + + org.apache.guacamole + guacamole-ext + 1.5.2 + provided + + + + + com.google.inject + guice + + + + + com.google.guava + guava + + + + + diff --git a/extensions/guacamole-template-ext/src/main/assembly/dist.xml b/extensions/guacamole-template-ext/src/main/assembly/dist.xml new file mode 100644 index 0000000000..6ee3cd8c87 --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/assembly/dist.xml @@ -0,0 +1,53 @@ + + + + + dist + ${project.artifactId}-${project.version} + + + + tar.gz + + + + + + + + + target/licenses + + + + + target + + + *.jar + + + + + + diff --git a/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/TemplateAuthenticationProvider.java b/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/TemplateAuthenticationProvider.java new file mode 100644 index 0000000000..8a036c2300 --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/TemplateAuthenticationProvider.java @@ -0,0 +1,50 @@ +/* + * 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.templates; + +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.net.auth.AbstractAuthenticationProvider; +import org.apache.guacamole.net.auth.AuthenticatedUser; +import org.apache.guacamole.net.auth.Credentials; +import org.apache.guacamole.net.auth.UserContext; +import org.apache.guacamole.templates.user.TemplateUserContext; + +/** + * An implementation of an Authentication Provider which allows users to + * associate a connection with another connection as a template, pulling + * the values of parameters specified in the selected "template connection" + * into the connection. + */ +public class TemplateAuthenticationProvider extends AbstractAuthenticationProvider { + + @Override + public String getIdentifier() { + return "template-ext"; + } + + @Override + public UserContext decorate(UserContext context, AuthenticatedUser authenticatedUser, Credentials credentials) throws GuacamoleException { + if (context instanceof TemplateUserContext) + return context; + + return new TemplateUserContext(context); + } + +} diff --git a/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/connection/TemplatedConnection.java b/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/connection/TemplatedConnection.java new file mode 100644 index 0000000000..362ace641a --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/connection/TemplatedConnection.java @@ -0,0 +1,198 @@ +/* + * 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.templates.connection; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.form.Form; +import org.apache.guacamole.net.auth.Connection; +import org.apache.guacamole.net.auth.DelegatingConnection; +import org.apache.guacamole.net.auth.Directory; +import org.apache.guacamole.protocol.GuacamoleConfiguration; +import org.apache.guacamole.templates.form.ConnectionChooserField; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A Connection implementation which wraps another Connection object, but also + * adds the functionality to link the Connection to another object as a + * "template" connection, inheriting parameters and attributes from the + * template. + */ +public class TemplatedConnection extends DelegatingConnection { + + /** + * The Logger for this class. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(TemplatedConnection.class); + + /** + * The attribute name that provides the connection identifier which should + * e the template for this connection, and the parameters and attributes + * of which this connection will inherit. + */ + public static final String TEMPLATE_ID_ATTRIBUTE_NAME = "template-connection-id"; + + /** + * An array of all of the attributes implemented specifically by this + * connection type. + */ + public static final List TEMPLATED_CONNECTION_ATTRIBUTES = Arrays.asList(TEMPLATE_ID_ATTRIBUTE_NAME); + + /** + * The form that provides all of the fields that need to be visible for this + * connection implementation in order to provide the template functionality. + */ + public static final Form TEMPLATED_CONNECTION_FORM = new Form( + "templated-connection-form", + Arrays.asList(new ConnectionChooserField(TEMPLATE_ID_ATTRIBUTE_NAME)) + ); + + /** + * The directory in which this connection exists. + */ + private final Directory connectionDirectory; + + + /** + * Create a new TemplatedConnection, wrapping the given Connection object + * and delegating functionality to that underlying object, after providing + * the template capability. + * + * @param connection + * The original connection to wrap. + * + * @param directory + * The Connection Directory in which this connection exists, provided + * for the purpose of retrieving the template connection. + */ + public TemplatedConnection(Connection connection, Directory directory) { + super(connection); + this.connectionDirectory = directory; + } + + /** + * Retrieve the original connection that this object wraps. + * + * @return + * The original connection that this object wraps. + */ + public Connection getWrappedConnection() { + return getDelegateConnection(); + } + + @Override + public Map getAttributes() { + + // Make a mutable copy of the connection attributes + Map attributes = new HashMap<>(super.getAttributes()); + + // Loop through and add the ones that aren't present so that they are + // available on the web page. + for (String attribute : TEMPLATED_CONNECTION_ATTRIBUTES) { + String value = attributes.get(attribute); + if (value == null || value.isEmpty()) + attributes.put(attribute, null); + } + + // Return the new Map of attributes. + return attributes; + } + + @Override + public void setAttributes(Map attributes) { + + // Make a mutable copy of connection attributes + attributes = new HashMap<>(attributes); + + // Loop through extension-specific attributes, only sending ones + // that are non-null and non-empty to the underlying storage mechanism. + for (String attribute : TEMPLATED_CONNECTION_ATTRIBUTES) { + String value = attributes.get(attribute); + if (value != null && value.isEmpty()) + attributes.put(attribute, null); + } + + // Set the complete attributes + super.setAttributes(attributes); + + } + + @Override + public GuacamoleConfiguration getConfiguration() { + + // Retrieve the decorated connection's configuration. + GuacamoleConfiguration config = super.getConfiguration(); + + // Get the template connection identifier - if its empty, just return this config. + String templateId = getTemplateConnectionId(); + if (templateId == null || templateId.isEmpty()) + return config; + + try { + // Get the template connection from its identifier. + Connection templateConnection = connectionDirectory.get(templateId); + + // Get the template connection configuration. + GuacamoleConfiguration mergedConfig = new GuacamoleConfiguration(templateConnection.getConfiguration()); + + // Loop through values, overriding the template values as required. + for (String parameter: config.getParameterNames()) { + String value = config.getParameter(parameter); + if (value != null && !value.isEmpty()) { + mergedConfig.setParameter(parameter, value); + } + } + + // Return the merged configuration + return mergedConfig; + + } catch (GuacamoleException e) { + LOGGER.warn("Could not retrieve template connection: {}", templateId); + LOGGER.debug("Exception retrieving template connection.", e); + return null; + } + + } + + /** + * Return the identifier of the connection that has been set as this + * connections template. + * + * @return + * The identifier of the template connection as set in the + * connection attributes. + */ + private String getTemplateConnectionId() { + + Map attributes = getAttributes(); + String templateId = attributes.get(TEMPLATE_ID_ATTRIBUTE_NAME); + if (templateId != null && !templateId.isEmpty()) + return templateId; + return null; + + } + + + +} diff --git a/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/form/ConnectionChooserField.java b/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/form/ConnectionChooserField.java new file mode 100644 index 0000000000..eda0329844 --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/form/ConnectionChooserField.java @@ -0,0 +1,46 @@ +/* + * 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.templates.form; + +import org.apache.guacamole.form.Field; + +/** + * A field that allows users to choose from possible existing connections to + * which they have access. + */ +public class ConnectionChooserField extends Field { + + /** + * The field type, used to load the correct field within the AngularJS + * application. + */ + public static String FIELD_TYPE = "GUAC_CONNECTION_CHOOSER"; + + /** + * Create a new ConnectionChooserField with the specified name. + * + * @param name + * The name of the field. + */ + public ConnectionChooserField(String name) { + super(name, FIELD_TYPE); + } + +} diff --git a/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/user/TemplateUserContext.java b/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/user/TemplateUserContext.java new file mode 100644 index 0000000000..9d80b6e3bc --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/java/org/apache/guacamole/templates/user/TemplateUserContext.java @@ -0,0 +1,80 @@ +/* + * 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.templates.user; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import org.apache.guacamole.GuacamoleException; +import org.apache.guacamole.form.Form; +import org.apache.guacamole.net.auth.Connection; +import org.apache.guacamole.net.auth.DecoratingDirectory; +import org.apache.guacamole.net.auth.DelegatingUserContext; +import org.apache.guacamole.net.auth.Directory; +import org.apache.guacamole.net.auth.UserContext; +import org.apache.guacamole.templates.connection.TemplatedConnection; + +/** + * A UserContext which decorates another context, adding the capability for + * connections within this context to be linked to other connections in order + * to inherit settings from those connections. + */ +public class TemplateUserContext extends DelegatingUserContext { + + /** + * Create a new instances of the TemplateUserContext, wrapping the given + * UserContext and delegating functionality to that context. + * + * @param context + * The UserContext to wrap. + */ + public TemplateUserContext(UserContext context) { + super(context); + } + + @Override + public Directory getConnectionDirectory() throws GuacamoleException { + return new DecoratingDirectory(super.getConnectionDirectory()) { + + @Override + protected Connection decorate(Connection object) { + if (object instanceof TemplatedConnection) + return object; + return new TemplatedConnection(object, this); + } + + @Override + protected Connection undecorate(Connection object) { + if (object instanceof TemplatedConnection) + return ((TemplatedConnection) object).getWrappedConnection(); + return object; + } + + }; + } + + @Override + public Collection
getConnectionAttributes() { + Collection connectionAttrs = new HashSet<>(super.getConnectionAttributes()); + connectionAttrs.add(TemplatedConnection.TEMPLATED_CONNECTION_FORM); + return Collections.unmodifiableCollection(connectionAttrs); + } + +} diff --git a/extensions/guacamole-template-ext/src/main/resources/config/templateConfig.js b/extensions/guacamole-template-ext/src/main/resources/config/templateConfig.js new file mode 100644 index 0000000000..b917c481df --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/resources/config/templateConfig.js @@ -0,0 +1,33 @@ +/* + * 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. + */ + +/** + * Config block which registers restrict-specific field types. + */ +angular.module('templateExt').config(['formServiceProvider', + function templateExtConfig(formServiceProvider) { + + // Define the time restriction field + formServiceProvider.registerFieldType('GUAC_CONNECTION_CHOOSER', { + module : 'templateExt', + controller : 'connectionChooserController', + templateUrl : 'app/ext/template-ext/templates/templateChooser.html' + }); + +}]); \ No newline at end of file diff --git a/extensions/guacamole-template-ext/src/main/resources/controllers/connectionChooserController.js b/extensions/guacamole-template-ext/src/main/resources/controllers/connectionChooserController.js new file mode 100644 index 0000000000..3d8f8162dd --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/resources/controllers/connectionChooserController.js @@ -0,0 +1,175 @@ +/* + * 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. + */ + + +/** + * A controller for choosing a connection from a list of available connections. + */ +angular.module('templateExt').controller('connectionChooserController', + ['$scope', '$injector', function connectionChooserController($scope, $injector) { + + // Required types + var ConnectionGroup = $injector.get('ConnectionGroup'); + + // Required services + var $log = $injector.get('$log'); + var $routeParams = $injector.get('$routeParams'); + var connectionGroupService = $injector.get('connectionGroupService'); + + /** + * Map of unique identifiers to their corresponding connection + * groups. + * + * @type Object. + */ + var connectionGroups = {}; + + /** + * Map of unique identifiers to their correspnoding connections. + * + * @type Object. + */ + var connections = {}; + + /** + * The identifier of the connection being edited. If a new + * connection is being created, this will not be defined. + * + * @type String + */ + var identifier = $routeParams.id; + + /** + * The current data source that is being used to edit the connection, + * from which other available connections will be retrieved to use + * as possible template values. + * + * @type String + */ + var dataSource = $routeParams.dataSource; + + /** + * Recursively traverses the given connection group and all + * children, storing each encountered connection group within the + * connectionGroups map by its identifier. + * + * @param {GroupListItem} group + * The connection group to traverse. + */ + var mapConnectionsAndGroups = function mapConnectionsAndGroups(group) { + + // Map given group + connectionGroups[group.identifier] = group; + + if (group.childConnections) + group.childConnections.forEach(connection => { + // Skip this connection + if (connection.identifier === identifier) + return; + connections[connection.identifier] = connection; + }); + + // Map all child groups + if (group.childConnectionGroups) + group.childConnectionGroups.forEach(mapConnectionsAndGroups); + + + }; + + /** + * Whether the connection list menu is currently open. + * + * @type Boolean + */ + $scope.menuOpen = false; + + /** + * The human-readable name of the currently-chosen connection. + * + * @type String + */ + $scope.chosenConnectionName = null; + + /** + * The rootGroup for the currently-selected data source. + * + * @type ConnectionGroup + */ + $scope.rootGroups = {}; + + /** + * Retrive the root connection group for this data source and save it. + */ + connectionGroupService.getConnectionGroupTree($routeParams.dataSource, ConnectionGroup.ROOT_IDENTIFIER) + .then(function connectionGroupDataRetrieved(rootGroup) { + + connections = {} + connectionGroups = {}; + + // Map all known groups + mapConnectionsAndGroups(rootGroup); + + // Wrap root group in map + $scope.rootGroups = {}; + $scope.rootGroups[dataSource] = rootGroup; + + // Find the currently-selected connection. + if ($scope.model && $scope.model in connections) + $scope.chosenConnectionName = connections[$scope.model].name; + else + $scope.chosenConnectionName = '--No Template Chosen--'; + + }); + + /** + * Toggle the current state of the menu listing connections. + * If the menu is currently open, it will be closed. If currently + * closed, it will be opened. + */ + $scope.toggleMenu = function toggleMenu() { + $scope.menuOpen = !$scope.menuOpen; + }; + + // Expose selection function to connection list template + $scope.connectionListContext = { + + /** + * Selects the given connection item. + * + * @param {ConnectionListItem} item + * The chosen item. + */ + chooseConnection : function chooseConnection(item) { + + // Connection cannot set itself as the template + if (identifier && identifier === item.identifier) + return false; + + // Record new parent + $scope.model = item.identifier; + $scope.chosenConnectionName = item.name; + + // Close menu + $scope.menuOpen = false; + + } + + }; + +}]); \ No newline at end of file diff --git a/extensions/guacamole-template-ext/src/main/resources/guac-manifest.json b/extensions/guacamole-template-ext/src/main/resources/guac-manifest.json new file mode 100644 index 0000000000..7745af9877 --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/resources/guac-manifest.json @@ -0,0 +1,30 @@ +{ + + "guacamoleVersion" : "1.5.2", + + "name" : "Connection Template Extension", + "namespace" : "template-ext", + + "authProviders" : [ + "org.apache.guacamole.templates.TemplateAuthenticationProvider" + ], + + "translations" : [ + "translations/en.json" + ], + + "js" : [ + "templateExt.min.js" + ], + + "css" : [ + "templateExt.min.css" + ], + + "resources" : { + "templates/templateChooser.html" : "text/html", + "templates/templateChooserConnection.html" : "text/html", + "templates/tempalteChooserConnectionGroup.html" : "text/html" + } + +} diff --git a/extensions/guacamole-template-ext/src/main/resources/license.txt b/extensions/guacamole-template-ext/src/main/resources/license.txt new file mode 100644 index 0000000000..042f3ce1f3 --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/resources/license.txt @@ -0,0 +1,18 @@ +/* + * 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. + */ diff --git a/extensions/guacamole-template-ext/src/main/resources/styles/templateChooser.css b/extensions/guacamole-template-ext/src/main/resources/styles/templateChooser.css new file mode 100644 index 0000000000..261f498401 --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/resources/styles/templateChooser.css @@ -0,0 +1,35 @@ +/* + * 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. + */ + +.template-chooser .dropdown { + + position: absolute; + z-index: 2; + margin-top: -1px; + + width: 3in; + max-height: 2in; + overflow: auto; + + border: 1px solid rgba(0, 0, 0, 0.5); + background: white; + + font-size: 10pt; + +} \ No newline at end of file diff --git a/extensions/guacamole-template-ext/src/main/resources/templateExt.js b/extensions/guacamole-template-ext/src/main/resources/templateExt.js new file mode 100644 index 0000000000..0c694567d3 --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/resources/templateExt.js @@ -0,0 +1,29 @@ +/* + * 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. + */ + +/** + * Module which provides handling for setting one connection as a template + * for another. + */ +angular.module('templateExt', [ + 'form' +]); + +// Ensure the templateExt module is loaded along with the rest of the app +angular.module('index').requires.push('templateExt'); \ No newline at end of file diff --git a/extensions/guacamole-template-ext/src/main/resources/templates/templateChooser.html b/extensions/guacamole-template-ext/src/main/resources/templates/templateChooser.html new file mode 100644 index 0000000000..9bd95ba5c6 --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/resources/templates/templateChooser.html @@ -0,0 +1,17 @@ +
+ + +
{{chosenConnectionName}}
+ + + + +
diff --git a/extensions/guacamole-template-ext/src/main/resources/templates/templateChooserConnection.html b/extensions/guacamole-template-ext/src/main/resources/templates/templateChooserConnection.html new file mode 100644 index 0000000000..26c7950094 --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/resources/templates/templateChooserConnection.html @@ -0,0 +1,4 @@ + + {{item.name}} + diff --git a/extensions/guacamole-template-ext/src/main/resources/templates/templateChooserConnectionGroup.html b/extensions/guacamole-template-ext/src/main/resources/templates/templateChooserConnectionGroup.html new file mode 100644 index 0000000000..3bfec5933b --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/resources/templates/templateChooserConnectionGroup.html @@ -0,0 +1,3 @@ + + {{item.name}} + diff --git a/extensions/guacamole-template-ext/src/main/resources/translations/en.json b/extensions/guacamole-template-ext/src/main/resources/translations/en.json new file mode 100644 index 0000000000..97add23923 --- /dev/null +++ b/extensions/guacamole-template-ext/src/main/resources/translations/en.json @@ -0,0 +1,15 @@ +{ + + "DATA_SOURCE_TEMPLATE_EXT" : { + "NAME" : "Connection Template Extension" + }, + + "CONNECTION_ATTRIBUTES" : { + + "FIELD_HEADER_TEMPLATE_CONNECTION_ID" : "Template Connection: ", + + "SECTION_HEADER_TEMPLATED_CONNECTION_FORM" : "Connection Template" + + } + +} diff --git a/extensions/pom.xml b/extensions/pom.xml index e9b8a3e53a..07e93b6c1a 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -52,6 +52,7 @@ guacamole-history-recording-storage + guacamole-template-ext guacamole-vault