mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 21:27:40 +00:00
Merge 1.1.0 changes to master.
This commit is contained in:
@@ -54,6 +54,11 @@ public class APIActiveConnection {
|
||||
*/
|
||||
private final String username;
|
||||
|
||||
/**
|
||||
* Whether this active connection may be connected to.
|
||||
*/
|
||||
private final boolean connectable;
|
||||
|
||||
/**
|
||||
* Creates a new APIActiveConnection, copying the information from the given
|
||||
* active connection.
|
||||
@@ -67,6 +72,7 @@ public class APIActiveConnection {
|
||||
this.startDate = connection.getStartDate();
|
||||
this.remoteHost = connection.getRemoteHost();
|
||||
this.username = connection.getUsername();
|
||||
this.connectable = connection.isConnectable();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,5 +127,16 @@ public class APIActiveConnection {
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* Returns whether this active connection may be connected to, just as a
|
||||
* normal connection.
|
||||
*
|
||||
* @return
|
||||
* true if this active connection may be connected to, false otherwise.
|
||||
*/
|
||||
public boolean isConnectable() {
|
||||
return connectable;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,8 +21,6 @@ package org.apache.guacamole.tunnel;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.guacamole.GuacamoleClientException;
|
||||
import org.apache.guacamole.GuacamoleClientException;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
|
||||
/**
|
||||
@@ -101,40 +99,6 @@ public abstract class TunnelRequest {
|
||||
*/
|
||||
public static final String TIMEZONE_PARAMETER = "GUAC_TIMEZONE";
|
||||
|
||||
/**
|
||||
* All supported object types that can be used as the destination of a
|
||||
* tunnel.
|
||||
*/
|
||||
public static enum Type {
|
||||
|
||||
/**
|
||||
* A Guacamole connection.
|
||||
*/
|
||||
CONNECTION("c"),
|
||||
|
||||
/**
|
||||
* A Guacamole connection group.
|
||||
*/
|
||||
CONNECTION_GROUP("g");
|
||||
|
||||
/**
|
||||
* The parameter value which denotes a destination object of this type.
|
||||
*/
|
||||
final String PARAMETER_VALUE;
|
||||
|
||||
/**
|
||||
* Defines a Type having the given corresponding parameter value.
|
||||
*
|
||||
* @param value
|
||||
* The parameter value which denotes a destination object of this
|
||||
* type.
|
||||
*/
|
||||
Type(String value) {
|
||||
PARAMETER_VALUE = value;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the value of the parameter having the given name.
|
||||
*
|
||||
@@ -257,18 +221,11 @@ public abstract class TunnelRequest {
|
||||
* If the type was not present in the request, or if the type requested
|
||||
* is in the wrong format.
|
||||
*/
|
||||
public Type getType() throws GuacamoleException {
|
||||
public TunnelRequestType getType() throws GuacamoleException {
|
||||
|
||||
String type = getRequiredParameter(TYPE_PARAMETER);
|
||||
|
||||
// For each possible object type
|
||||
for (Type possibleType : Type.values()) {
|
||||
|
||||
// Match against defined parameter value
|
||||
if (type.equals(possibleType.PARAMETER_VALUE))
|
||||
return possibleType;
|
||||
|
||||
}
|
||||
TunnelRequestType type = TunnelRequestType.parseType(getRequiredParameter(TYPE_PARAMETER));
|
||||
if (type != null)
|
||||
return type;
|
||||
|
||||
throw new GuacamoleClientException("Illegal identifier - unknown type.");
|
||||
|
||||
|
@@ -24,15 +24,13 @@ import com.google.inject.Singleton;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.GuacamoleSecurityException;
|
||||
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
||||
import org.apache.guacamole.GuacamoleSession;
|
||||
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||
import org.apache.guacamole.net.auth.Connection;
|
||||
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||
import org.apache.guacamole.net.auth.Connectable;
|
||||
import org.apache.guacamole.net.auth.Credentials;
|
||||
import org.apache.guacamole.net.auth.Directory;
|
||||
import org.apache.guacamole.net.auth.UserContext;
|
||||
import org.apache.guacamole.net.event.TunnelCloseEvent;
|
||||
import org.apache.guacamole.net.event.TunnelConnectEvent;
|
||||
@@ -204,58 +202,20 @@ public class TunnelRequestService {
|
||||
* If an error occurs while creating the tunnel.
|
||||
*/
|
||||
protected GuacamoleTunnel createConnectedTunnel(UserContext context,
|
||||
final TunnelRequest.Type type, String id,
|
||||
final TunnelRequestType type, String id,
|
||||
GuacamoleClientInformation info, Map<String, String> tokens)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Create connected tunnel from identifier
|
||||
GuacamoleTunnel tunnel = null;
|
||||
switch (type) {
|
||||
|
||||
// Connection identifiers
|
||||
case CONNECTION: {
|
||||
|
||||
// Get connection directory
|
||||
Directory<Connection> directory = context.getConnectionDirectory();
|
||||
|
||||
// Get authorized connection
|
||||
Connection connection = directory.get(id);
|
||||
if (connection == null) {
|
||||
logger.info("Connection \"{}\" does not exist for user \"{}\".", id, context.self().getIdentifier());
|
||||
throw new GuacamoleSecurityException("Requested connection is not authorized.");
|
||||
}
|
||||
|
||||
// Connect tunnel
|
||||
tunnel = connection.connect(info, tokens);
|
||||
logger.info("User \"{}\" connected to connection \"{}\".", context.self().getIdentifier(), id);
|
||||
break;
|
||||
}
|
||||
|
||||
// Connection group identifiers
|
||||
case CONNECTION_GROUP: {
|
||||
|
||||
// Get connection group directory
|
||||
Directory<ConnectionGroup> directory = context.getConnectionGroupDirectory();
|
||||
|
||||
// Get authorized connection group
|
||||
ConnectionGroup group = directory.get(id);
|
||||
if (group == null) {
|
||||
logger.info("Connection group \"{}\" does not exist for user \"{}\".", id, context.self().getIdentifier());
|
||||
throw new GuacamoleSecurityException("Requested connection group is not authorized.");
|
||||
}
|
||||
|
||||
// Connect tunnel
|
||||
tunnel = group.connect(info, tokens);
|
||||
logger.info("User \"{}\" connected to group \"{}\".", context.self().getIdentifier(), id);
|
||||
break;
|
||||
}
|
||||
|
||||
// Type is guaranteed to be one of the above
|
||||
default:
|
||||
assert(false);
|
||||
|
||||
}
|
||||
// Retrieve requested destination object
|
||||
Connectable connectable = type.getConnectable(context, id);
|
||||
if (connectable == null)
|
||||
throw new GuacamoleResourceNotFoundException("Requested tunnel "
|
||||
+ "destination does not exist.");
|
||||
|
||||
// Connect tunnel to destination
|
||||
GuacamoleTunnel tunnel = connectable.connect(info, tokens);
|
||||
logger.info("User \"{}\" connected to {} \"{}\".",
|
||||
context.self().getIdentifier(), type.NAME, id);
|
||||
return tunnel;
|
||||
|
||||
}
|
||||
@@ -297,7 +257,7 @@ public class TunnelRequestService {
|
||||
*/
|
||||
protected GuacamoleTunnel createAssociatedTunnel(final GuacamoleTunnel tunnel,
|
||||
final String authToken, final GuacamoleSession session,
|
||||
final UserContext context, final TunnelRequest.Type type,
|
||||
final UserContext context, final TunnelRequestType type,
|
||||
final String id) throws GuacamoleException {
|
||||
|
||||
// Monitor tunnel closure and data
|
||||
@@ -320,26 +280,9 @@ public class TunnelRequestService {
|
||||
long connectionEndTime = System.currentTimeMillis();
|
||||
long duration = connectionEndTime - connectionStartTime;
|
||||
|
||||
// Log closure
|
||||
switch (type) {
|
||||
|
||||
// Connection identifiers
|
||||
case CONNECTION:
|
||||
logger.info("User \"{}\" disconnected from connection \"{}\". Duration: {} milliseconds",
|
||||
session.getAuthenticatedUser().getIdentifier(), id, duration);
|
||||
break;
|
||||
|
||||
// Connection group identifiers
|
||||
case CONNECTION_GROUP:
|
||||
logger.info("User \"{}\" disconnected from connection group \"{}\". Duration: {} milliseconds",
|
||||
session.getAuthenticatedUser().getIdentifier(), id, duration);
|
||||
break;
|
||||
|
||||
// Type is guaranteed to be one of the above
|
||||
default:
|
||||
assert(false);
|
||||
|
||||
}
|
||||
logger.info("User \"{}\" disconnected from {} \"{}\". Duration: {} milliseconds",
|
||||
session.getAuthenticatedUser().getIdentifier(),
|
||||
type.NAME, id, duration);
|
||||
|
||||
try {
|
||||
|
||||
@@ -390,7 +333,7 @@ public class TunnelRequestService {
|
||||
// Parse request parameters
|
||||
String authToken = request.getAuthenticationToken();
|
||||
String id = request.getIdentifier();
|
||||
TunnelRequest.Type type = request.getType();
|
||||
TunnelRequestType type = request.getType();
|
||||
String authProviderIdentifier = request.getAuthenticationProviderIdentifier();
|
||||
GuacamoleClientInformation info = getClientInformation(request);
|
||||
|
||||
|
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* 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.tunnel;
|
||||
|
||||
import org.apache.guacamole.GuacamoleException;
|
||||
import org.apache.guacamole.net.auth.ActiveConnection;
|
||||
import org.apache.guacamole.net.auth.Connectable;
|
||||
import org.apache.guacamole.net.auth.Connection;
|
||||
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||
import org.apache.guacamole.net.auth.UserContext;
|
||||
|
||||
/**
|
||||
* All supported object types that can be used as the destination of a tunnel.
|
||||
*
|
||||
* @see TunnelRequest#TYPE_PARAMETER
|
||||
* @see TunnelRequest#getType()
|
||||
*/
|
||||
public enum TunnelRequestType {
|
||||
|
||||
/**
|
||||
* A Guacamole connection.
|
||||
*/
|
||||
CONNECTION("c", "connection") {
|
||||
|
||||
@Override
|
||||
public Connection getConnectable(UserContext userContext,
|
||||
String identifier) throws GuacamoleException {
|
||||
return userContext.getConnectionDirectory().get(identifier);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* A Guacamole connection group.
|
||||
*/
|
||||
CONNECTION_GROUP("g", "connection group") {
|
||||
|
||||
@Override
|
||||
public ConnectionGroup getConnectable(UserContext userContext,
|
||||
String identifier) throws GuacamoleException {
|
||||
return userContext.getConnectionGroupDirectory().get(identifier);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* An active Guacamole connection.
|
||||
*/
|
||||
ACTIVE_CONNECTION("a", "active connection") {
|
||||
|
||||
@Override
|
||||
public ActiveConnection getConnectable(UserContext userContext,
|
||||
String identifier) throws GuacamoleException {
|
||||
return userContext.getActiveConnectionDirectory().get(identifier);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The parameter value which denotes a destination object of this type
|
||||
* within a tunnel request.
|
||||
*
|
||||
* @see TunnelRequest#TYPE_PARAMETER
|
||||
* @see TunnelRequest#getType()
|
||||
*/
|
||||
public final String PARAMETER_VALUE;
|
||||
|
||||
/**
|
||||
* A human-readable, descriptive name of the type of destination object.
|
||||
*/
|
||||
public final String NAME;
|
||||
|
||||
/**
|
||||
* Defines a tunnel request type having the given corresponding parameter
|
||||
* value and human-readable name.
|
||||
*
|
||||
* @param value
|
||||
* The parameter value which denotes a destination object of this
|
||||
* type.
|
||||
*
|
||||
* @param name
|
||||
* A human-readable, descriptive name of the type of destination
|
||||
* object.
|
||||
*/
|
||||
private TunnelRequestType(String value, String name) {
|
||||
PARAMETER_VALUE = value;
|
||||
NAME = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the object having the given identifier from the given
|
||||
* UserContext, where the type of object retrieved is the type of object
|
||||
* represented by this tunnel request type.
|
||||
*
|
||||
* @param userContext
|
||||
* The UserContext to retrieve the object from.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the object to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The object having the given identifier, or null if no such object
|
||||
* exists.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs retrieving the requested object, or if permission
|
||||
* to retrieve the object is denied.
|
||||
*/
|
||||
public abstract Connectable getConnectable(UserContext userContext,
|
||||
String identifier) throws GuacamoleException;
|
||||
|
||||
/**
|
||||
* Parses the given tunnel request type string, returning the
|
||||
* TunnelRequestType which matches that string, as declared by
|
||||
* {@link #PARAMETER_VALUE}. If no such type exists, null is returned.
|
||||
*
|
||||
* @param type
|
||||
* The type string to parse.
|
||||
*
|
||||
* @return
|
||||
* The TunnelRequestType which specifies the given string as its
|
||||
* {@link #PARAMETER_VALUE}, or null if no such type exists.
|
||||
*/
|
||||
public static TunnelRequestType parseType(String type) {
|
||||
|
||||
// Locate type with given parameter value
|
||||
for (TunnelRequestType possibleType : values()) {
|
||||
if (type.equals(possibleType.PARAMETER_VALUE))
|
||||
return possibleType;
|
||||
}
|
||||
|
||||
// No such type
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -36,21 +36,22 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
|
||||
var ManagedShareLink = $injector.get('ManagedShareLink');
|
||||
|
||||
// Required services
|
||||
var $document = $injector.get('$document');
|
||||
var $q = $injector.get('$q');
|
||||
var $rootScope = $injector.get('$rootScope');
|
||||
var $window = $injector.get('$window');
|
||||
var authenticationService = $injector.get('authenticationService');
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
var connectionService = $injector.get('connectionService');
|
||||
var preferenceService = $injector.get('preferenceService');
|
||||
var requestService = $injector.get('requestService');
|
||||
var schemaService = $injector.get('schemaService');
|
||||
var tunnelService = $injector.get('tunnelService');
|
||||
var guacAudio = $injector.get('guacAudio');
|
||||
var guacHistory = $injector.get('guacHistory');
|
||||
var guacImage = $injector.get('guacImage');
|
||||
var guacVideo = $injector.get('guacVideo');
|
||||
var $document = $injector.get('$document');
|
||||
var $q = $injector.get('$q');
|
||||
var $rootScope = $injector.get('$rootScope');
|
||||
var $window = $injector.get('$window');
|
||||
var activeConnectionService = $injector.get('activeConnectionService');
|
||||
var authenticationService = $injector.get('authenticationService');
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
var connectionService = $injector.get('connectionService');
|
||||
var preferenceService = $injector.get('preferenceService');
|
||||
var requestService = $injector.get('requestService');
|
||||
var schemaService = $injector.get('schemaService');
|
||||
var tunnelService = $injector.get('tunnelService');
|
||||
var guacAudio = $injector.get('guacAudio');
|
||||
var guacHistory = $injector.get('guacHistory');
|
||||
var guacImage = $injector.get('guacImage');
|
||||
var guacVideo = $injector.get('guacVideo');
|
||||
|
||||
/**
|
||||
* The minimum amount of time to wait between updates to the client
|
||||
@@ -610,6 +611,29 @@ angular.module('client').factory('ManagedClient', ['$rootScope', '$injector',
|
||||
}, requestService.WARN);
|
||||
}
|
||||
|
||||
// If using an active connection, pull corresponding connection, then
|
||||
// pull connection name and protocol information from that
|
||||
else if (clientIdentifier.type === ClientIdentifier.Types.ACTIVE_CONNECTION) {
|
||||
activeConnectionService.getActiveConnection(clientIdentifier.dataSource, clientIdentifier.id)
|
||||
.then(function activeConnectionRetrieved(activeConnection) {
|
||||
|
||||
// Attempt to retrieve connection details only if the
|
||||
// underlying connection is known
|
||||
if (activeConnection.connectionIdentifier) {
|
||||
$q.all({
|
||||
connection : connectionService.getConnection(clientIdentifier.dataSource, activeConnection.connectionIdentifier),
|
||||
protocols : schemaService.getProtocols(clientIdentifier.dataSource)
|
||||
})
|
||||
.then(function dataRetrieved(values) {
|
||||
managedClient.name = managedClient.title = values.connection.name;
|
||||
managedClient.protocol = values.connection.protocol;
|
||||
managedClient.forms = values.protocols[values.connection.protocol].connectionForms;
|
||||
}, requestService.WARN);
|
||||
}
|
||||
|
||||
}, requestService.WARN);
|
||||
}
|
||||
|
||||
return managedClient;
|
||||
|
||||
};
|
||||
|
@@ -89,7 +89,14 @@ angular.module('client').factory('ClientIdentifier', ['$injector',
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
CONNECTION_GROUP : 'g'
|
||||
CONNECTION_GROUP : 'g',
|
||||
|
||||
/**
|
||||
* The type string for an active Guacamole connection.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
ACTIVE_CONNECTION : 'a'
|
||||
|
||||
};
|
||||
|
||||
|
@@ -29,6 +29,38 @@ angular.module('rest').factory('activeConnectionService', ['$injector',
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get a single active connection,
|
||||
* returning a promise that provides the corresponding
|
||||
* @link{ActiveConnection} if successful.
|
||||
*
|
||||
* @param {String} dataSource
|
||||
* The identifier of the data source to retrieve the active connection
|
||||
* from.
|
||||
*
|
||||
* @param {String} id
|
||||
* The identifier of the active connection.
|
||||
*
|
||||
* @returns {Promise.<ActiveConnection>}
|
||||
* A promise which will resolve with a @link{ActiveConnection} upon
|
||||
* success.
|
||||
*/
|
||||
service.getActiveConnection = function getActiveConnection(dataSource, id) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve active connection
|
||||
return requestService({
|
||||
method : 'GET',
|
||||
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/activeConnections/' + encodeURIComponent(id),
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the list of active tunnels,
|
||||
* returning a promise that provides a map of @link{ActiveConnection}
|
||||
|
@@ -76,6 +76,14 @@ angular.module('rest').factory('ActiveConnection', [function defineActiveConnect
|
||||
*/
|
||||
this.username = template.username;
|
||||
|
||||
/**
|
||||
* Whether this active connection may be connected to, just as a
|
||||
* normal connection.
|
||||
*
|
||||
* @type Boolean
|
||||
*/
|
||||
this.connectable = template.connectable;
|
||||
|
||||
};
|
||||
|
||||
return ActiveConnection;
|
||||
|
@@ -35,6 +35,7 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
||||
|
||||
// Required types
|
||||
var ActiveConnectionWrapper = $injector.get('ActiveConnectionWrapper');
|
||||
var ClientIdentifier = $injector.get('ClientIdentifier');
|
||||
var ConnectionGroup = $injector.get('ConnectionGroup');
|
||||
var SortOrder = $injector.get('SortOrder');
|
||||
|
||||
@@ -336,7 +337,37 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
||||
'actions' : [ DELETE_ACTION, CANCEL_ACTION]
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the relative URL of the client page which accesses the
|
||||
* given active connection. If the active connection is not
|
||||
* connectable, null is returned.
|
||||
*
|
||||
* @param {String} dataSource
|
||||
* The unique identifier of the data source containing the
|
||||
* active connection.
|
||||
*
|
||||
* @param {String} activeConnection
|
||||
* The active connection to determine the relative URL of.
|
||||
*
|
||||
* @returns {String}
|
||||
* The relative URL of the client page which accesses the given
|
||||
* active connection, or null if the active connection is not
|
||||
* connectable.
|
||||
*/
|
||||
$scope.getClientURL = function getClientURL(dataSource, activeConnection) {
|
||||
|
||||
if (!activeConnection.connectable)
|
||||
return null;
|
||||
|
||||
return '#/client/' + encodeURIComponent(ClientIdentifier.toString({
|
||||
dataSource : dataSource,
|
||||
type : ClientIdentifier.Types.ACTIVE_CONNECTION,
|
||||
id : activeConnection.identifier
|
||||
}));
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the selected sessions can be deleted.
|
||||
*
|
||||
|
@@ -40,7 +40,9 @@
|
||||
<td><guac-user-item username="wrapper.activeConnection.username"></guac-user-item></td>
|
||||
<td>{{wrapper.startDate}}</td>
|
||||
<td>{{wrapper.activeConnection.remoteHost}}</td>
|
||||
<td>{{wrapper.name}}</td>
|
||||
<td><a ng-href="{{
|
||||
getClientURL(wrapper.dataSource, wrapper.activeConnection)
|
||||
}}">{{wrapper.name}}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
Reference in New Issue
Block a user