mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
Merge 1.1.0 changes to master.
This commit is contained in:
@@ -91,15 +91,16 @@ public class ActiveConnectionService
|
|||||||
Collection<TrackedActiveConnection> activeConnections = new ArrayList<TrackedActiveConnection>(identifiers.size());
|
Collection<TrackedActiveConnection> activeConnections = new ArrayList<TrackedActiveConnection>(identifiers.size());
|
||||||
for (ActiveConnectionRecord record : records) {
|
for (ActiveConnectionRecord record : records) {
|
||||||
|
|
||||||
// Sensitive information should be included if the connection was
|
// The current user should have access to sensitive information and
|
||||||
// started by the current user OR the user is an admin
|
// be able to connect to (join) the active connection if they are
|
||||||
boolean includeSensitiveInformation =
|
// the user that started the connection OR the user is an admin
|
||||||
|
boolean hasPrivilegedAccess =
|
||||||
isAdmin || username.equals(record.getUsername());
|
isAdmin || username.equals(record.getUsername());
|
||||||
|
|
||||||
// Add connection if within requested identifiers
|
// Add connection if within requested identifiers
|
||||||
if (identifierSet.contains(record.getUUID().toString())) {
|
if (identifierSet.contains(record.getUUID().toString())) {
|
||||||
TrackedActiveConnection activeConnection = trackedActiveConnectionProvider.get();
|
TrackedActiveConnection activeConnection = trackedActiveConnectionProvider.get();
|
||||||
activeConnection.init(user, record, includeSensitiveInformation);
|
activeConnection.init(user, record, hasPrivilegedAccess, hasPrivilegedAccess);
|
||||||
activeConnections.add(activeConnection);
|
activeConnections.add(activeConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,15 +21,20 @@ package org.apache.guacamole.auth.jdbc.activeconnection;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
|
import org.apache.guacamole.auth.jdbc.base.RestrictedObject;
|
||||||
import org.apache.guacamole.auth.jdbc.connection.ModeledConnection;
|
import org.apache.guacamole.auth.jdbc.connection.ModeledConnection;
|
||||||
import org.apache.guacamole.auth.jdbc.sharing.ConnectionSharingService;
|
import org.apache.guacamole.auth.jdbc.sharing.ConnectionSharingService;
|
||||||
|
import org.apache.guacamole.auth.jdbc.sharing.connection.SharedConnectionDefinition;
|
||||||
import org.apache.guacamole.auth.jdbc.tunnel.ActiveConnectionRecord;
|
import org.apache.guacamole.auth.jdbc.tunnel.ActiveConnectionRecord;
|
||||||
|
import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
|
||||||
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
|
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
|
||||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||||
import org.apache.guacamole.net.auth.ActiveConnection;
|
import org.apache.guacamole.net.auth.ActiveConnection;
|
||||||
import org.apache.guacamole.net.auth.credentials.UserCredentials;
|
import org.apache.guacamole.net.auth.credentials.UserCredentials;
|
||||||
|
import org.apache.guacamole.protocol.GuacamoleClientInformation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of the ActiveConnection object which has an associated
|
* An implementation of the ActiveConnection object which has an associated
|
||||||
@@ -43,6 +48,12 @@ public class TrackedActiveConnection extends RestrictedObject implements ActiveC
|
|||||||
@Inject
|
@Inject
|
||||||
private ConnectionSharingService sharingService;
|
private ConnectionSharingService sharingService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for creating and tracking tunnels.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private GuacamoleTunnelService tunnelService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The identifier of this active connection.
|
* The identifier of this active connection.
|
||||||
*/
|
*/
|
||||||
@@ -84,6 +95,11 @@ public class TrackedActiveConnection extends RestrictedObject implements ActiveC
|
|||||||
*/
|
*/
|
||||||
private GuacamoleTunnel tunnel;
|
private GuacamoleTunnel tunnel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether connections to this TrackedActiveConnection are allowed.
|
||||||
|
*/
|
||||||
|
private boolean connectable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes this TrackedActiveConnection, copying the data associated
|
* Initializes this TrackedActiveConnection, copying the data associated
|
||||||
* with the given active connection record. At a minimum, the identifier
|
* with the given active connection record. At a minimum, the identifier
|
||||||
@@ -102,13 +118,19 @@ public class TrackedActiveConnection extends RestrictedObject implements ActiveC
|
|||||||
* Whether sensitive data should be copied from the connection record
|
* Whether sensitive data should be copied from the connection record
|
||||||
* as well. This includes the remote host, associated tunnel, and
|
* as well. This includes the remote host, associated tunnel, and
|
||||||
* username.
|
* username.
|
||||||
|
*
|
||||||
|
* @param connectable
|
||||||
|
* Whether the user that retrieved this object should be allowed to
|
||||||
|
* join the active connection.
|
||||||
*/
|
*/
|
||||||
public void init(ModeledAuthenticatedUser currentUser,
|
public void init(ModeledAuthenticatedUser currentUser,
|
||||||
ActiveConnectionRecord activeConnectionRecord,
|
ActiveConnectionRecord activeConnectionRecord,
|
||||||
boolean includeSensitiveInformation) {
|
boolean includeSensitiveInformation,
|
||||||
|
boolean connectable) {
|
||||||
|
|
||||||
super.init(currentUser);
|
super.init(currentUser);
|
||||||
this.connectionRecord = activeConnectionRecord;
|
this.connectionRecord = activeConnectionRecord;
|
||||||
|
this.connectable = connectable;
|
||||||
|
|
||||||
// Copy all non-sensitive data from given record
|
// Copy all non-sensitive data from given record
|
||||||
this.connection = activeConnectionRecord.getConnection();
|
this.connection = activeConnectionRecord.getConnection();
|
||||||
@@ -169,11 +191,32 @@ public class TrackedActiveConnection extends RestrictedObject implements ActiveC
|
|||||||
this.sharingProfileIdentifier = sharingProfileIdentifier;
|
this.sharingProfileIdentifier = sharingProfileIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shares this active connection with the user that retrieved it, returning
|
||||||
|
* a SharedConnectionDefinition that can be used to establish a tunnel to
|
||||||
|
* the shared connection. If provided, access within the shared connection
|
||||||
|
* will be restricted by the sharing profile with the given identifier.
|
||||||
|
*
|
||||||
|
* @param identifier
|
||||||
|
* The identifier of the sharing profile that defines the restrictions
|
||||||
|
* applying to the shared connection, or null if no such restrictions
|
||||||
|
* apply.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new SharedConnectionDefinition which can be used to establish a
|
||||||
|
* tunnel to the shared connection.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If permission to share this active connection is denied.
|
||||||
|
*/
|
||||||
|
private SharedConnectionDefinition share(String identifier) throws GuacamoleException {
|
||||||
|
return sharingService.shareConnection(getCurrentUser(), connectionRecord, identifier);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserCredentials getSharingCredentials(String identifier)
|
public UserCredentials getSharingCredentials(String identifier)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
return sharingService.generateTemporaryCredentials(getCurrentUser(),
|
return sharingService.getSharingCredentials(share(identifier));
|
||||||
connectionRecord, identifier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -216,4 +259,26 @@ public class TrackedActiveConnection extends RestrictedObject implements ActiveC
|
|||||||
this.tunnel = tunnel;
|
this.tunnel = tunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isConnectable() {
|
||||||
|
return connectable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuacamoleTunnel connect(GuacamoleClientInformation info,
|
||||||
|
Map<String, String> tokens) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Establish connection only if connecting is allowed
|
||||||
|
if (isConnectable())
|
||||||
|
return tunnelService.getGuacamoleTunnel(getCurrentUser(), share(null), info, tokens);
|
||||||
|
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getActiveConnections() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ package org.apache.guacamole.auth.jdbc.sharing;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
|
import org.apache.guacamole.auth.jdbc.user.ModeledAuthenticatedUser;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
@@ -30,11 +31,14 @@ import org.apache.guacamole.auth.jdbc.sharing.user.SharedAuthenticatedUser;
|
|||||||
import org.apache.guacamole.auth.jdbc.sharingprofile.ModeledSharingProfile;
|
import org.apache.guacamole.auth.jdbc.sharingprofile.ModeledSharingProfile;
|
||||||
import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileService;
|
import org.apache.guacamole.auth.jdbc.sharingprofile.SharingProfileService;
|
||||||
import org.apache.guacamole.auth.jdbc.tunnel.ActiveConnectionRecord;
|
import org.apache.guacamole.auth.jdbc.tunnel.ActiveConnectionRecord;
|
||||||
|
import org.apache.guacamole.auth.jdbc.tunnel.GuacamoleTunnelService;
|
||||||
|
import org.apache.guacamole.auth.jdbc.user.RemoteAuthenticatedUser;
|
||||||
import org.apache.guacamole.form.Field;
|
import org.apache.guacamole.form.Field;
|
||||||
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
import org.apache.guacamole.net.auth.Credentials;
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
import org.apache.guacamole.net.auth.credentials.CredentialsInfo;
|
||||||
import org.apache.guacamole.net.auth.credentials.UserCredentials;
|
import org.apache.guacamole.net.auth.credentials.UserCredentials;
|
||||||
|
import org.apache.guacamole.protocol.GuacamoleClientInformation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service which provides convenience methods for sharing active connections.
|
* Service which provides convenience methods for sharing active connections.
|
||||||
@@ -75,10 +79,16 @@ public class ConnectionSharingService {
|
|||||||
));
|
));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a set of temporary credentials which can be used to connect to
|
* Creates a new SharedConnectionDefinition which can be used to connect to
|
||||||
* the given connection using the given sharing profile. If the user does
|
* the given connection, optionally restricting access to the shared
|
||||||
* not have permission to share the connection via the given sharing
|
* connection using the given sharing profile. If the user does not have
|
||||||
* profile, permission will be denied.
|
* permission to share the connection via the given sharing profile,
|
||||||
|
* permission will be denied.
|
||||||
|
*
|
||||||
|
* @see GuacamoleTunnelService#getGuacamoleTunnel(RemoteAuthenticatedUser,
|
||||||
|
* SharedConnectionDefinition, GuacamoleClientInformation, Map)
|
||||||
|
*
|
||||||
|
* @see #getSharingCredentials(SharedConnectionDefinition)
|
||||||
*
|
*
|
||||||
* @param user
|
* @param user
|
||||||
* The user sharing the connection.
|
* The user sharing the connection.
|
||||||
@@ -88,42 +98,67 @@ public class ConnectionSharingService {
|
|||||||
*
|
*
|
||||||
* @param sharingProfileIdentifier
|
* @param sharingProfileIdentifier
|
||||||
* The identifier of the sharing profile dictating the semantics or
|
* The identifier of the sharing profile dictating the semantics or
|
||||||
* restrictions applying to the shared session.
|
* restrictions applying to the shared session, or null if no such
|
||||||
|
* restrictions should apply.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* A newly-generated set of temporary credentials which can be used to
|
* A new SharedConnectionDefinition which can be used to connect to the
|
||||||
* connect to the given connection.
|
* given connection.
|
||||||
*
|
*
|
||||||
* @throws GuacamoleException
|
* @throws GuacamoleException
|
||||||
* If permission to share the given connection is denied.
|
* If permission to share the given connection is denied.
|
||||||
*/
|
*/
|
||||||
public UserCredentials generateTemporaryCredentials(ModeledAuthenticatedUser user,
|
public SharedConnectionDefinition shareConnection(ModeledAuthenticatedUser user,
|
||||||
ActiveConnectionRecord activeConnection,
|
ActiveConnectionRecord activeConnection,
|
||||||
String sharingProfileIdentifier) throws GuacamoleException {
|
String sharingProfileIdentifier) throws GuacamoleException {
|
||||||
|
|
||||||
// Pull sharing profile (verifying access)
|
// If a sharing profile is provided, verify that permission to use that
|
||||||
ModeledSharingProfile sharingProfile =
|
// profile to share the given connection is actually granted
|
||||||
sharingProfileService.retrieveObject(user,
|
ModeledSharingProfile sharingProfile = null;
|
||||||
sharingProfileIdentifier);
|
if (sharingProfileIdentifier != null) {
|
||||||
|
|
||||||
// Verify that this profile is indeed a sharing profile for the
|
// Pull sharing profile (verifying access)
|
||||||
// requested connection
|
sharingProfile = sharingProfileService.retrieveObject(user, sharingProfileIdentifier);
|
||||||
String connectionIdentifier = activeConnection.getConnectionIdentifier();
|
|
||||||
if (sharingProfile == null || !sharingProfile.getPrimaryConnectionIdentifier().equals(connectionIdentifier))
|
// Verify that this profile is indeed a sharing profile for the
|
||||||
throw new GuacamoleSecurityException("Permission denied.");
|
// requested connection
|
||||||
|
String connectionIdentifier = activeConnection.getConnectionIdentifier();
|
||||||
|
if (sharingProfile == null || !sharingProfile.getPrimaryConnectionIdentifier().equals(connectionIdentifier))
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a share key for the requested connection
|
// Generate a share key for the requested connection
|
||||||
String key = keyGenerator.getShareKey();
|
String key = keyGenerator.getShareKey();
|
||||||
connectionMap.add(new SharedConnectionDefinition(activeConnection,
|
SharedConnectionDefinition definition = new SharedConnectionDefinition(activeConnection, sharingProfile, key);
|
||||||
sharingProfile, key));
|
connectionMap.add(definition);
|
||||||
|
|
||||||
// Ensure the share key is properly invalidated when the original
|
// Ensure the share key is properly invalidated when the original
|
||||||
// connection is closed
|
// connection is closed
|
||||||
activeConnection.registerShareKey(key);
|
activeConnection.registerShareKey(key);
|
||||||
|
|
||||||
|
return definition;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a set of temporary credentials which can be used to connect to
|
||||||
|
* the given connection shared by the SharedConnectionDefinition.
|
||||||
|
*
|
||||||
|
* @param definition
|
||||||
|
* The SharedConnectionDefinition which defines the connection being
|
||||||
|
* shared and any applicable restrictions.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A newly-generated set of temporary credentials which can be used to
|
||||||
|
* connect to the connection shared by the given
|
||||||
|
* SharedConnectionDefinition.
|
||||||
|
*/
|
||||||
|
public UserCredentials getSharingCredentials(SharedConnectionDefinition definition) {
|
||||||
|
|
||||||
// Return credentials defining a single expected parameter
|
// Return credentials defining a single expected parameter
|
||||||
return new UserCredentials(SHARE_KEY,
|
return new UserCredentials(SHARE_KEY,
|
||||||
Collections.singletonMap(SHARE_KEY_NAME, key));
|
Collections.singletonMap(SHARE_KEY_NAME, definition.getShareKey()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,9 +29,11 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the semantics/restrictions of a shared connection by associating an
|
* Defines the semantics/restrictions of a shared connection by associating an
|
||||||
* active connection with a sharing profile. The sharing profile defines the
|
* active connection with an optional sharing profile. The sharing profile, if
|
||||||
* access provided to users of the shared active connection through its
|
* present, defines the access provided to users of the shared active
|
||||||
* connection parameters.
|
* connection through its connection parameters. If no sharing profile is
|
||||||
|
* present, the shared connection has the same level of access as the original
|
||||||
|
* connection.
|
||||||
*/
|
*/
|
||||||
public class SharedConnectionDefinition {
|
public class SharedConnectionDefinition {
|
||||||
|
|
||||||
@@ -88,7 +90,8 @@ public class SharedConnectionDefinition {
|
|||||||
*
|
*
|
||||||
* @param sharingProfile
|
* @param sharingProfile
|
||||||
* A sharing profile whose associated parameters dictate the level of
|
* A sharing profile whose associated parameters dictate the level of
|
||||||
* access provided to the shared connection.
|
* access provided to the shared connection, or null if the connection
|
||||||
|
* should be given full access.
|
||||||
*
|
*
|
||||||
* @param shareKey
|
* @param shareKey
|
||||||
* The unique key with which a user may access the shared connection.
|
* The unique key with which a user may access the shared connection.
|
||||||
|
@@ -202,8 +202,10 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a guacamole configuration containing the protocol and parameters
|
* Returns a guacamole configuration containing the protocol and parameters
|
||||||
* from the given connection. If tokens are used in the connection
|
* from the given connection. If the ID of an active connection is
|
||||||
* parameter values, credentials from the given user will be substituted
|
* provided, that connection will be joined instead of starting a new
|
||||||
|
* primary connection. If tokens are used in the connection parameter
|
||||||
|
* values, credentials from the given user will be substituted
|
||||||
* appropriately.
|
* appropriately.
|
||||||
*
|
*
|
||||||
* @param user
|
* @param user
|
||||||
@@ -213,19 +215,29 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
|
|||||||
* The connection whose protocol and parameters should be added to the
|
* The connection whose protocol and parameters should be added to the
|
||||||
* returned configuration.
|
* returned configuration.
|
||||||
*
|
*
|
||||||
|
* @param connectionID
|
||||||
|
* The ID of the active connection to be joined, as returned by guacd,
|
||||||
|
* or null if a new primary connection should be established.
|
||||||
|
*
|
||||||
* @return
|
* @return
|
||||||
* A GuacamoleConfiguration containing the protocol and parameters from
|
* A GuacamoleConfiguration containing the protocol and parameters from
|
||||||
* the given connection.
|
* the given connection.
|
||||||
*/
|
*/
|
||||||
private GuacamoleConfiguration getGuacamoleConfiguration(RemoteAuthenticatedUser user,
|
private GuacamoleConfiguration getGuacamoleConfiguration(RemoteAuthenticatedUser user,
|
||||||
ModeledConnection connection) {
|
ModeledConnection connection, String connectionID) {
|
||||||
|
|
||||||
// Generate configuration from available data
|
// Generate configuration from available data
|
||||||
GuacamoleConfiguration config = new GuacamoleConfiguration();
|
GuacamoleConfiguration config = new GuacamoleConfiguration();
|
||||||
|
|
||||||
// Set protocol from connection
|
// Join existing active connection, if any
|
||||||
ConnectionModel model = connection.getModel();
|
if (connectionID != null)
|
||||||
config.setProtocol(model.getProtocol());
|
config.setConnectionID(connectionID);
|
||||||
|
|
||||||
|
// Set protocol from connection if not joining an active connection
|
||||||
|
else {
|
||||||
|
ConnectionModel model = connection.getModel();
|
||||||
|
config.setProtocol(model.getProtocol());
|
||||||
|
}
|
||||||
|
|
||||||
// Set parameters from associated data
|
// Set parameters from associated data
|
||||||
Collection<ConnectionParameterModel> parameters = connectionParameterMapper.select(connection.getIdentifier());
|
Collection<ConnectionParameterModel> parameters = connectionParameterMapper.select(connection.getIdentifier());
|
||||||
@@ -470,16 +482,17 @@ public abstract class AbstractGuacamoleTunnelService implements GuacamoleTunnelS
|
|||||||
// Retrieve connection information associated with given connection record
|
// Retrieve connection information associated with given connection record
|
||||||
ModeledConnection connection = activeConnection.getConnection();
|
ModeledConnection connection = activeConnection.getConnection();
|
||||||
|
|
||||||
// Pull configuration directly from the connection if we are not
|
// Pull configuration directly from the connection, additionally
|
||||||
// joining an active connection
|
// joining the existing active connection (without sharing profile
|
||||||
|
// restrictions) if such a connection exists
|
||||||
if (activeConnection.isPrimaryConnection()) {
|
if (activeConnection.isPrimaryConnection()) {
|
||||||
activeConnections.put(connection.getIdentifier(), activeConnection);
|
activeConnections.put(connection.getIdentifier(), activeConnection);
|
||||||
activeConnectionGroups.put(connection.getParentIdentifier(), activeConnection);
|
activeConnectionGroups.put(connection.getParentIdentifier(), activeConnection);
|
||||||
config = getGuacamoleConfiguration(activeConnection.getUser(), connection);
|
config = getGuacamoleConfiguration(activeConnection.getUser(), connection, activeConnection.getConnectionID());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we ARE joining an active connection, generate a configuration
|
// If we ARE joining an active connection under the restrictions of
|
||||||
// which does so
|
// a sharing profile, generate a configuration which does so
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// Verify that the connection ID is known
|
// Verify that the connection ID is known
|
||||||
|
@@ -32,7 +32,6 @@ import org.apache.guacamole.net.AbstractGuacamoleTunnel;
|
|||||||
import org.apache.guacamole.net.GuacamoleSocket;
|
import org.apache.guacamole.net.GuacamoleSocket;
|
||||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||||
import org.apache.guacamole.net.auth.ConnectionRecord;
|
import org.apache.guacamole.net.auth.ConnectionRecord;
|
||||||
import org.apache.guacamole.protocol.ConfiguredGuacamoleSocket;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -202,8 +201,8 @@ public class ActiveConnectionRecord implements ConnectionRecord {
|
|||||||
*
|
*
|
||||||
* @param sharingProfile
|
* @param sharingProfile
|
||||||
* The sharing profile that was used to share access to the given
|
* The sharing profile that was used to share access to the given
|
||||||
* connection. As a record created in this way always refers to a
|
* connection, or null if no sharing profile should be used (access to
|
||||||
* shared connection, this value may NOT be null.
|
* the connection is unrestricted).
|
||||||
*/
|
*/
|
||||||
public void init(RemoteAuthenticatedUser user,
|
public void init(RemoteAuthenticatedUser user,
|
||||||
ActiveConnectionRecord activeConnection,
|
ActiveConnectionRecord activeConnection,
|
||||||
|
@@ -20,13 +20,18 @@
|
|||||||
package org.apache.guacamole.net.auth;
|
package org.apache.guacamole.net.auth;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||||
|
import org.apache.guacamole.protocol.GuacamoleClientInformation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A pairing of username and GuacamoleTunnel representing an active usage of a
|
* A pairing of username and GuacamoleTunnel representing an active usage of a
|
||||||
* particular connection.
|
* particular connection.
|
||||||
*/
|
*/
|
||||||
public interface ActiveConnection extends Identifiable, Shareable<SharingProfile> {
|
public interface ActiveConnection extends Identifiable, Connectable,
|
||||||
|
Shareable<SharingProfile> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the identifier of the connection being actively used. Unlike the
|
* Returns the identifier of the connection being actively used. Unlike the
|
||||||
@@ -137,4 +142,30 @@ public interface ActiveConnection extends Identifiable, Shareable<SharingProfile
|
|||||||
*/
|
*/
|
||||||
void setTunnel(GuacamoleTunnel tunnel);
|
void setTunnel(GuacamoleTunnel tunnel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this ActiveConnection may be joined through a call to
|
||||||
|
* {@link #connect(org.apache.guacamole.protocol.GuacamoleClientInformation, java.util.Map)}
|
||||||
|
* by the user that retrieved this ActiveConnection.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* true if the user that retrieved this ActiveConnection may join the
|
||||||
|
* ActiveConnection through a call to
|
||||||
|
* {@link #connect(org.apache.guacamole.protocol.GuacamoleClientInformation, java.util.Map)},
|
||||||
|
* false otherwise.
|
||||||
|
*/
|
||||||
|
default boolean isConnectable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default GuacamoleTunnel connect(GuacamoleClientInformation info,
|
||||||
|
Map<String, String> tokens) throws GuacamoleException {
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default int getActiveConnections() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -54,6 +54,11 @@ public class APIActiveConnection {
|
|||||||
*/
|
*/
|
||||||
private final String username;
|
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
|
* Creates a new APIActiveConnection, copying the information from the given
|
||||||
* active connection.
|
* active connection.
|
||||||
@@ -67,6 +72,7 @@ public class APIActiveConnection {
|
|||||||
this.startDate = connection.getStartDate();
|
this.startDate = connection.getStartDate();
|
||||||
this.remoteHost = connection.getRemoteHost();
|
this.remoteHost = connection.getRemoteHost();
|
||||||
this.username = connection.getUsername();
|
this.username = connection.getUsername();
|
||||||
|
this.connectable = connection.isConnectable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,4 +128,15 @@ public class APIActiveConnection {
|
|||||||
return identifier;
|
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 java.util.List;
|
||||||
import org.apache.guacamole.GuacamoleClientException;
|
import org.apache.guacamole.GuacamoleClientException;
|
||||||
import org.apache.guacamole.GuacamoleClientException;
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
|
||||||
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";
|
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.
|
* 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
|
* If the type was not present in the request, or if the type requested
|
||||||
* is in the wrong format.
|
* is in the wrong format.
|
||||||
*/
|
*/
|
||||||
public Type getType() throws GuacamoleException {
|
public TunnelRequestType getType() throws GuacamoleException {
|
||||||
|
|
||||||
String type = getRequiredParameter(TYPE_PARAMETER);
|
TunnelRequestType type = TunnelRequestType.parseType(getRequiredParameter(TYPE_PARAMETER));
|
||||||
|
if (type != null)
|
||||||
// For each possible object type
|
return type;
|
||||||
for (Type possibleType : Type.values()) {
|
|
||||||
|
|
||||||
// Match against defined parameter value
|
|
||||||
if (type.equals(possibleType.PARAMETER_VALUE))
|
|
||||||
return possibleType;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new GuacamoleClientException("Illegal identifier - unknown type.");
|
throw new GuacamoleClientException("Illegal identifier - unknown type.");
|
||||||
|
|
||||||
|
@@ -24,15 +24,13 @@ import com.google.inject.Singleton;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
import org.apache.guacamole.GuacamoleSession;
|
||||||
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
||||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
import org.apache.guacamole.net.auth.Connectable;
|
||||||
import org.apache.guacamole.net.auth.ConnectionGroup;
|
|
||||||
import org.apache.guacamole.net.auth.Credentials;
|
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.auth.UserContext;
|
||||||
import org.apache.guacamole.net.event.TunnelCloseEvent;
|
import org.apache.guacamole.net.event.TunnelCloseEvent;
|
||||||
import org.apache.guacamole.net.event.TunnelConnectEvent;
|
import org.apache.guacamole.net.event.TunnelConnectEvent;
|
||||||
@@ -204,58 +202,20 @@ public class TunnelRequestService {
|
|||||||
* If an error occurs while creating the tunnel.
|
* If an error occurs while creating the tunnel.
|
||||||
*/
|
*/
|
||||||
protected GuacamoleTunnel createConnectedTunnel(UserContext context,
|
protected GuacamoleTunnel createConnectedTunnel(UserContext context,
|
||||||
final TunnelRequest.Type type, String id,
|
final TunnelRequestType type, String id,
|
||||||
GuacamoleClientInformation info, Map<String, String> tokens)
|
GuacamoleClientInformation info, Map<String, String> tokens)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// Create connected tunnel from identifier
|
// Retrieve requested destination object
|
||||||
GuacamoleTunnel tunnel = null;
|
Connectable connectable = type.getConnectable(context, id);
|
||||||
switch (type) {
|
if (connectable == null)
|
||||||
|
throw new GuacamoleResourceNotFoundException("Requested tunnel "
|
||||||
// Connection identifiers
|
+ "destination does not exist.");
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Connect tunnel to destination
|
||||||
|
GuacamoleTunnel tunnel = connectable.connect(info, tokens);
|
||||||
|
logger.info("User \"{}\" connected to {} \"{}\".",
|
||||||
|
context.self().getIdentifier(), type.NAME, id);
|
||||||
return tunnel;
|
return tunnel;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -297,7 +257,7 @@ public class TunnelRequestService {
|
|||||||
*/
|
*/
|
||||||
protected GuacamoleTunnel createAssociatedTunnel(final GuacamoleTunnel tunnel,
|
protected GuacamoleTunnel createAssociatedTunnel(final GuacamoleTunnel tunnel,
|
||||||
final String authToken, final GuacamoleSession session,
|
final String authToken, final GuacamoleSession session,
|
||||||
final UserContext context, final TunnelRequest.Type type,
|
final UserContext context, final TunnelRequestType type,
|
||||||
final String id) throws GuacamoleException {
|
final String id) throws GuacamoleException {
|
||||||
|
|
||||||
// Monitor tunnel closure and data
|
// Monitor tunnel closure and data
|
||||||
@@ -320,26 +280,9 @@ public class TunnelRequestService {
|
|||||||
long connectionEndTime = System.currentTimeMillis();
|
long connectionEndTime = System.currentTimeMillis();
|
||||||
long duration = connectionEndTime - connectionStartTime;
|
long duration = connectionEndTime - connectionStartTime;
|
||||||
|
|
||||||
// Log closure
|
logger.info("User \"{}\" disconnected from {} \"{}\". Duration: {} milliseconds",
|
||||||
switch (type) {
|
session.getAuthenticatedUser().getIdentifier(),
|
||||||
|
type.NAME, id, duration);
|
||||||
// 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);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@@ -390,7 +333,7 @@ public class TunnelRequestService {
|
|||||||
// Parse request parameters
|
// Parse request parameters
|
||||||
String authToken = request.getAuthenticationToken();
|
String authToken = request.getAuthenticationToken();
|
||||||
String id = request.getIdentifier();
|
String id = request.getIdentifier();
|
||||||
TunnelRequest.Type type = request.getType();
|
TunnelRequestType type = request.getType();
|
||||||
String authProviderIdentifier = request.getAuthenticationProviderIdentifier();
|
String authProviderIdentifier = request.getAuthenticationProviderIdentifier();
|
||||||
GuacamoleClientInformation info = getClientInformation(request);
|
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');
|
var ManagedShareLink = $injector.get('ManagedShareLink');
|
||||||
|
|
||||||
// Required services
|
// Required services
|
||||||
var $document = $injector.get('$document');
|
var $document = $injector.get('$document');
|
||||||
var $q = $injector.get('$q');
|
var $q = $injector.get('$q');
|
||||||
var $rootScope = $injector.get('$rootScope');
|
var $rootScope = $injector.get('$rootScope');
|
||||||
var $window = $injector.get('$window');
|
var $window = $injector.get('$window');
|
||||||
var authenticationService = $injector.get('authenticationService');
|
var activeConnectionService = $injector.get('activeConnectionService');
|
||||||
var connectionGroupService = $injector.get('connectionGroupService');
|
var authenticationService = $injector.get('authenticationService');
|
||||||
var connectionService = $injector.get('connectionService');
|
var connectionGroupService = $injector.get('connectionGroupService');
|
||||||
var preferenceService = $injector.get('preferenceService');
|
var connectionService = $injector.get('connectionService');
|
||||||
var requestService = $injector.get('requestService');
|
var preferenceService = $injector.get('preferenceService');
|
||||||
var schemaService = $injector.get('schemaService');
|
var requestService = $injector.get('requestService');
|
||||||
var tunnelService = $injector.get('tunnelService');
|
var schemaService = $injector.get('schemaService');
|
||||||
var guacAudio = $injector.get('guacAudio');
|
var tunnelService = $injector.get('tunnelService');
|
||||||
var guacHistory = $injector.get('guacHistory');
|
var guacAudio = $injector.get('guacAudio');
|
||||||
var guacImage = $injector.get('guacImage');
|
var guacHistory = $injector.get('guacHistory');
|
||||||
var guacVideo = $injector.get('guacVideo');
|
var guacImage = $injector.get('guacImage');
|
||||||
|
var guacVideo = $injector.get('guacVideo');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The minimum amount of time to wait between updates to the client
|
* 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);
|
}, 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;
|
return managedClient;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@@ -89,7 +89,14 @@ angular.module('client').factory('ClientIdentifier', ['$injector',
|
|||||||
*
|
*
|
||||||
* @type String
|
* @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 = {};
|
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,
|
* Makes a request to the REST API to get the list of active tunnels,
|
||||||
* returning a promise that provides a map of @link{ActiveConnection}
|
* 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;
|
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;
|
return ActiveConnection;
|
||||||
|
@@ -35,6 +35,7 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
|
|
||||||
// Required types
|
// Required types
|
||||||
var ActiveConnectionWrapper = $injector.get('ActiveConnectionWrapper');
|
var ActiveConnectionWrapper = $injector.get('ActiveConnectionWrapper');
|
||||||
|
var ClientIdentifier = $injector.get('ClientIdentifier');
|
||||||
var ConnectionGroup = $injector.get('ConnectionGroup');
|
var ConnectionGroup = $injector.get('ConnectionGroup');
|
||||||
var SortOrder = $injector.get('SortOrder');
|
var SortOrder = $injector.get('SortOrder');
|
||||||
|
|
||||||
@@ -337,6 +338,36 @@ angular.module('settings').directive('guacSettingsSessions', [function guacSetti
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* 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><guac-user-item username="wrapper.activeConnection.username"></guac-user-item></td>
|
||||||
<td>{{wrapper.startDate}}</td>
|
<td>{{wrapper.startDate}}</td>
|
||||||
<td>{{wrapper.activeConnection.remoteHost}}</td>
|
<td>{{wrapper.activeConnection.remoteHost}}</td>
|
||||||
<td>{{wrapper.name}}</td>
|
<td><a ng-href="{{
|
||||||
|
getClientURL(wrapper.dataSource, wrapper.activeConnection)
|
||||||
|
}}">{{wrapper.name}}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
Reference in New Issue
Block a user