mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
Merge pull request #22 from glyptodon/cleanup-angular
Rewrite an absolute ton of Angular and REST code
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
*~
|
||||
target/
|
||||
nb-configuration.xml
|
||||
guacamole/customs.json
|
||||
|
@@ -162,4 +162,31 @@ public class GuacamoleConfiguration implements Serializable {
|
||||
return Collections.unmodifiableSet(parameters.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map which contains parameter name/value pairs as key/value
|
||||
* pairs. Changes to this map will affect the parameters stored within
|
||||
* this configuration.
|
||||
*
|
||||
* @return
|
||||
* A map which contains all parameter name/value pairs as key/value
|
||||
* pairs.
|
||||
*/
|
||||
public Map<String, String> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all current parameters with the parameters defined within the
|
||||
* given map. Key/value pairs within the map represent parameter name/value
|
||||
* pairs.
|
||||
*
|
||||
* @param parameters
|
||||
* A map which contains all parameter name/value pairs as key/value
|
||||
* pairs.
|
||||
*/
|
||||
public void setParameters(Map<String, String> parameters) {
|
||||
this.parameters.clear();
|
||||
this.parameters.putAll(parameters);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -23,11 +23,7 @@
|
||||
package org.glyptodon.guacamole.net.basic.rest;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connectiongroup.ConnectionGroupService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.permission.PermissionService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.protocol.ProtocolRetrievalService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.user.UserService;
|
||||
|
||||
/**
|
||||
* A Guice Module for setting up dependency injection for the
|
||||
@@ -41,10 +37,6 @@ public class RESTModule extends AbstractModule {
|
||||
protected void configure() {
|
||||
|
||||
// Bind generic low-level services
|
||||
bind(ConnectionService.class);
|
||||
bind(ConnectionGroupService.class);
|
||||
bind(PermissionService.class);
|
||||
bind(UserService.class);
|
||||
bind(ProtocolRetrievalService.class);
|
||||
|
||||
}
|
||||
|
@@ -30,7 +30,6 @@ import org.glyptodon.guacamole.net.basic.rest.auth.TokenRESTService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.clipboard.ClipboardRESTService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connection.ConnectionRESTService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connectiongroup.ConnectionGroupRESTService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.permission.PermissionRESTService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.protocol.ProtocolRESTService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.user.UserRESTService;
|
||||
|
||||
@@ -48,7 +47,6 @@ public class RESTServletModule extends ServletModule {
|
||||
bind(ClipboardRESTService.class);
|
||||
bind(ConnectionRESTService.class);
|
||||
bind(ConnectionGroupRESTService.class);
|
||||
bind(PermissionRESTService.class);
|
||||
bind(ProtocolRESTService.class);
|
||||
bind(UserRESTService.class);
|
||||
bind(TokenRESTService.class);
|
||||
|
@@ -48,7 +48,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
@Path("/token")
|
||||
@Path("/tokens")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class TokenRESTService {
|
||||
|
||||
|
@@ -22,14 +22,11 @@
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest.connection;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
|
||||
import org.glyptodon.guacamole.net.basic.rest.APIConstants;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connectiongroup.APIConnectionGroup;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
|
||||
|
||||
/**
|
||||
@@ -60,15 +57,10 @@ public class APIConnection {
|
||||
*/
|
||||
private String protocol;
|
||||
|
||||
/**
|
||||
* The history records associated with this connection.
|
||||
*/
|
||||
private List<? extends ConnectionRecord> history;
|
||||
|
||||
/**
|
||||
* Map of all associated parameter values, indexed by parameter name.
|
||||
*/
|
||||
private Map<String, String> parameters = new HashMap<String, String>();
|
||||
private Map<String, String> parameters;
|
||||
|
||||
/**
|
||||
* Create an empty APIConnection.
|
||||
@@ -76,7 +68,9 @@ public class APIConnection {
|
||||
public APIConnection() {}
|
||||
|
||||
/**
|
||||
* Create an APIConnection from a Connection record.
|
||||
* Create an APIConnection from a Connection record. Parameters for the
|
||||
* connection will not be included.
|
||||
*
|
||||
* @param connection The connection to create this APIConnection from.
|
||||
* @throws GuacamoleException If a problem is encountered while
|
||||
* instantiating this new APIConnection.
|
||||
@@ -84,21 +78,18 @@ public class APIConnection {
|
||||
public APIConnection(Connection connection)
|
||||
throws GuacamoleException {
|
||||
|
||||
// Set identifying information
|
||||
this.name = connection.getName();
|
||||
this.identifier = connection.getIdentifier();
|
||||
|
||||
// Set proper parent identifier, using root identifier if needed
|
||||
this.parentIdentifier = connection.getParentIdentifier();
|
||||
this.history = connection.getHistory();
|
||||
|
||||
// Use the explicit ROOT group ID
|
||||
if (this.parentIdentifier == null)
|
||||
this.parentIdentifier = APIConstants.ROOT_CONNECTION_GROUP_IDENTIFIER;
|
||||
|
||||
this.parentIdentifier = APIConnectionGroup.ROOT_IDENTIFIER;
|
||||
|
||||
// Set protocol from configuration
|
||||
GuacamoleConfiguration configuration = connection.getConfiguration();
|
||||
|
||||
this.protocol = configuration.getProtocol();
|
||||
|
||||
for (String key: configuration.getParameterNames())
|
||||
this.parameters.put(key, configuration.getParameter(key));
|
||||
|
||||
}
|
||||
|
||||
@@ -151,14 +142,6 @@ public class APIConnection {
|
||||
this.parentIdentifier = parentIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the history records associated with this connection.
|
||||
* @return The history records associated with this connection.
|
||||
*/
|
||||
public List<? extends ConnectionRecord> getHistory() {
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parameter map for this connection.
|
||||
* @return The parameter map for this connection.
|
||||
|
@@ -22,6 +22,7 @@
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest.connection;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
@@ -78,15 +79,14 @@ public class APIConnectionWrapper implements Connection {
|
||||
@Override
|
||||
public GuacamoleConfiguration getConfiguration() {
|
||||
|
||||
// Create the GuacamoleConfiguration from the parameter map
|
||||
// Create the GuacamoleConfiguration with current protocol
|
||||
GuacamoleConfiguration configuration = new GuacamoleConfiguration();
|
||||
|
||||
Map<String, String> parameters = apiConnection.getParameters();
|
||||
|
||||
for(Map.Entry<String, String> entry : parameters.entrySet())
|
||||
configuration.setParameter(entry.getKey(), entry.getValue());
|
||||
|
||||
configuration.setProtocol(apiConnection.getProtocol());
|
||||
|
||||
// Add parameters, if available
|
||||
Map<String, String> parameters = apiConnection.getParameters();
|
||||
if (parameters != null)
|
||||
configuration.setParameters(parameters);
|
||||
|
||||
return configuration;
|
||||
}
|
||||
@@ -94,13 +94,10 @@ public class APIConnectionWrapper implements Connection {
|
||||
@Override
|
||||
public void setConfiguration(GuacamoleConfiguration config) {
|
||||
|
||||
// Create a parameter map from the GuacamoleConfiguration
|
||||
Map<String, String> parameters = apiConnection.getParameters();
|
||||
for(String key : config.getParameterNames())
|
||||
parameters.put(key, config.getParameter(key));
|
||||
|
||||
// Set the protocol
|
||||
// Set protocol and parameters
|
||||
apiConnection.setProtocol(config.getProtocol());
|
||||
apiConnection.setParameters(config.getParameters());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,7 +107,7 @@ public class APIConnectionWrapper implements Connection {
|
||||
|
||||
@Override
|
||||
public List<? extends ConnectionRecord> getHistory() throws GuacamoleException {
|
||||
return apiConnection.getHistory();
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ package org.glyptodon.guacamole.net.basic.rest.connection;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
@@ -34,16 +35,18 @@ import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionRecord;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
|
||||
import org.glyptodon.guacamole.net.basic.rest.HTTPException;
|
||||
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connectiongroup.APIConnectionGroup;
|
||||
import org.glyptodon.guacamole.protocol.GuacamoleConfiguration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -52,7 +55,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
@Path("/connection")
|
||||
@Path("/connections")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public class ConnectionRESTService {
|
||||
@@ -69,59 +72,20 @@ public class ConnectionRESTService {
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* A service for managing the REST endpoint APIConnection objects.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionService connectionService;
|
||||
|
||||
/**
|
||||
* Gets a list of connections with the given ConnectionGroup parentID.
|
||||
* If no parentID is provided, returns the connections from the root group.
|
||||
* Retrieves an individual connection.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param parentID The ID of the ConnectionGroup the connections
|
||||
* belong to. If null, the root connection group will be used.
|
||||
* @return The connection list.
|
||||
* @throws GuacamoleException If a problem is encountered while listing connections.
|
||||
*/
|
||||
@GET
|
||||
@AuthProviderRESTExposure
|
||||
public List<APIConnection> getConnections(@QueryParam("token") String authToken, @QueryParam("parentID") String parentID)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// If the parent connection group is passed in, try to find it.
|
||||
ConnectionGroup parentConnectionGroup;
|
||||
if (parentID == null)
|
||||
parentConnectionGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
else {
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory = rootGroup.getConnectionGroupDirectory();
|
||||
parentConnectionGroup = connectionGroupDirectory.get(parentID);
|
||||
}
|
||||
|
||||
if (parentConnectionGroup == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No ConnectionGroup found with the provided parentID.");
|
||||
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
parentConnectionGroup.getConnectionDirectory();
|
||||
|
||||
// Return the converted connection directory
|
||||
return connectionService.convertConnectionList(connectionDirectory);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an individual connection.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param connectionID The ID of the Connection..
|
||||
* @return The connection.
|
||||
* @throws GuacamoleException If a problem is encountered while retrieving the connection.
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connectionID
|
||||
* The identifier of the connection to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The connection having the given identifier.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the connection.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{connectionID}")
|
||||
@@ -139,19 +103,105 @@ public class ConnectionRESTService {
|
||||
// Get the connection
|
||||
Connection connection = connectionDirectory.get(connectionID);
|
||||
if (connection == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No Connection found with the provided ID.");
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + connectionID + "\"");
|
||||
|
||||
return new APIConnection(connection);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the parameters associated with a single connection.
|
||||
*
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connectionID
|
||||
* The identifier of the connection.
|
||||
*
|
||||
* @return
|
||||
* A map of parameter name/value pairs.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the connection parameters.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{connectionID}/parameters")
|
||||
@AuthProviderRESTExposure
|
||||
public Map<String, String> getConnectionParameters(@QueryParam("token") String authToken,
|
||||
@PathParam("connectionID") String connectionID) throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the connection directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
rootGroup.getConnectionDirectory();
|
||||
|
||||
// Get the connection
|
||||
Connection connection = connectionDirectory.get(connectionID);
|
||||
if (connection == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + connectionID + "\"");
|
||||
|
||||
// Retrieve connection configuration
|
||||
GuacamoleConfiguration config = connection.getConfiguration();
|
||||
|
||||
// Return parameter map
|
||||
return config.getParameters();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the usage history of a single connection.
|
||||
*
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connectionID
|
||||
* The identifier of the connection.
|
||||
*
|
||||
* @return
|
||||
* A list of connection records, describing the start and end times of
|
||||
* various usages of this connection.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the connection history.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{connectionID}/history")
|
||||
@AuthProviderRESTExposure
|
||||
public List<? extends ConnectionRecord> getConnectionHistory(@QueryParam("token") String authToken,
|
||||
@PathParam("connectionID") String connectionID) throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the connection directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
rootGroup.getConnectionDirectory();
|
||||
|
||||
// Get the connection
|
||||
Connection connection = connectionDirectory.get(connectionID);
|
||||
if (connection == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + connectionID + "\"");
|
||||
|
||||
return connection.getHistory();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an individual connection.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param connectionID The ID of the Connection to delete.
|
||||
* @throws GuacamoleException If a problem is encountered while deleting the connection.
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connectionID
|
||||
* The identifier of the connection to delete.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while deleting the connection.
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{connectionID}")
|
||||
@@ -168,72 +218,112 @@ public class ConnectionRESTService {
|
||||
|
||||
// Make sure the connection is there before trying to delete
|
||||
if (connectionDirectory.get(connectionID) == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No Connection found with the provided ID.");
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + connectionID + "\"");
|
||||
|
||||
// Delete the connection
|
||||
connectionDirectory.remove(connectionID);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new connection and returns the identifier of the new connection.
|
||||
* If a parentID is provided, the connection will be created in the
|
||||
* connection group with the parentID. Otherwise, the root connection group
|
||||
* will be used.
|
||||
* Retrieves a single connection group from the given user context. If
|
||||
* the given identifier is null or the root identifier, the root connection
|
||||
* group will be returned.
|
||||
*
|
||||
* @param userContext
|
||||
* The user context to retrieve the connection group from.
|
||||
*
|
||||
* @param identifier
|
||||
* The identifier of the connection group to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The connection group having the given identifier, or the root
|
||||
* connection group if the identifier is null or the root identifier.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the connection group, or if the
|
||||
* connection group does not exist.
|
||||
*/
|
||||
private ConnectionGroup retrieveConnectionGroup(UserContext userContext,
|
||||
String identifier) throws GuacamoleException {
|
||||
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Use root group if identifier is null (or the standard root identifier)
|
||||
if (identifier == null || identifier.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||
return rootGroup;
|
||||
|
||||
// Pull specified connection group otherwise
|
||||
Directory<String, ConnectionGroup> directory = rootGroup.getConnectionGroupDirectory();
|
||||
ConnectionGroup connectionGroup = directory.get(identifier);
|
||||
|
||||
if (connectionGroup == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + identifier + "\"");
|
||||
|
||||
return connectionGroup;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new connection and returns the identifier of the new
|
||||
* connection.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param parentID The ID of the ConnectionGroup the connections
|
||||
* belong to. If null, the root connection group will be used.
|
||||
* @param connection The connection to create.
|
||||
* @return The identifier of the new connection.
|
||||
* @throws GuacamoleException If a problem is encountered while creating the connection.
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connection
|
||||
* The connection to create.
|
||||
*
|
||||
* @return
|
||||
* The identifier of the new connection.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while creating the connection.
|
||||
*/
|
||||
@POST
|
||||
@AuthProviderRESTExposure
|
||||
public String createConnection(@QueryParam("token") String authToken,
|
||||
@QueryParam("parentID") String parentID, APIConnection connection) throws GuacamoleException {
|
||||
public String createConnection(@QueryParam("token") String authToken,
|
||||
APIConnection connection) throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Validate that connection data was provided
|
||||
if (connection == null)
|
||||
throw new GuacamoleClientException("A connection is required for this request.");
|
||||
throw new GuacamoleClientException("Connection JSON must be submitted when creating connections.");
|
||||
|
||||
// If the parent connection group is passed in, try to find it.
|
||||
ConnectionGroup parentConnectionGroup;
|
||||
if (parentID == null)
|
||||
parentConnectionGroup = userContext.getRootConnectionGroup();
|
||||
// Retrieve parent group
|
||||
String parentID = connection.getParentIdentifier();
|
||||
ConnectionGroup parentConnectionGroup = retrieveConnectionGroup(userContext, parentID);
|
||||
|
||||
else {
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory = rootGroup.getConnectionGroupDirectory();
|
||||
parentConnectionGroup = connectionGroupDirectory.get(parentID);
|
||||
}
|
||||
|
||||
if (parentConnectionGroup == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No ConnectionGroup found with the provided parentID.");
|
||||
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
parentConnectionGroup.getConnectionDirectory();
|
||||
|
||||
// Create the connection
|
||||
// Add the new connection
|
||||
Directory<String, Connection> connectionDirectory = parentConnectionGroup.getConnectionDirectory();
|
||||
connectionDirectory.add(new APIConnectionWrapper(connection));
|
||||
|
||||
// Return the new connection identifier
|
||||
return connection.getIdentifier();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates a connection.
|
||||
* Updates an existing connection. If the parent identifier of the
|
||||
* connection is changed, the connection will also be moved to the new
|
||||
* parent group.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param connectionID The ID of the Connection to move.
|
||||
* @param connection The connection to update.
|
||||
* @throws GuacamoleException If a problem is encountered while updating the connection.
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connectionID
|
||||
* The identifier of the connection to update.
|
||||
*
|
||||
* @param connection
|
||||
* The connection data to update the specified connection with.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while updating the connection.
|
||||
*/
|
||||
@POST
|
||||
@PUT
|
||||
@Path("/{connectionID}")
|
||||
@AuthProviderRESTExposure
|
||||
public void updateConnection(@QueryParam("token") String authToken,
|
||||
@@ -241,62 +331,30 @@ public class ConnectionRESTService {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Validate that connection data was provided
|
||||
if (connection == null)
|
||||
throw new GuacamoleClientException("A connection is required for this request.");
|
||||
throw new GuacamoleClientException("Connection JSON must be submitted when updating connections.");
|
||||
|
||||
// Get the connection directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
rootGroup.getConnectionDirectory();
|
||||
|
||||
Connection connectionFromAuthProvider = connectionDirectory.get(connectionID);
|
||||
|
||||
// Make sure the connection is there before trying to update
|
||||
if (connectionFromAuthProvider == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No Connection found with the provided ID.");
|
||||
Connection existingConnection = connectionDirectory.get(connectionID);
|
||||
if (existingConnection == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + connectionID + "\"");
|
||||
|
||||
// Copy the information from this connection over to an object from the Auth Provider
|
||||
APIConnectionWrapper wrappedConnection = new APIConnectionWrapper(connection);
|
||||
connectionFromAuthProvider.setConfiguration(wrappedConnection.getConfiguration());
|
||||
connectionFromAuthProvider.setName(wrappedConnection.getName());
|
||||
// Retrieve connection configuration
|
||||
GuacamoleConfiguration config = new GuacamoleConfiguration();
|
||||
config.setProtocol(connection.getProtocol());
|
||||
config.setParameters(connection.getParameters());
|
||||
|
||||
// Update the connection
|
||||
connectionDirectory.update(connectionFromAuthProvider);
|
||||
existingConnection.setConfiguration(config);
|
||||
existingConnection.setName(connection.getName());
|
||||
connectionDirectory.update(existingConnection);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves an individual connection to a different connection group.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param connectionID The ID of the Connection to move.
|
||||
* @param parentID The ID of the ConnectionGroup the connection is to be moved to.
|
||||
* @throws GuacamoleException If a problem is encountered while moving the connection.
|
||||
*/
|
||||
@PUT
|
||||
@Path("/{connectionID}")
|
||||
@AuthProviderRESTExposure
|
||||
public void moveConnection(@QueryParam("token") String authToken,
|
||||
@PathParam("connectionID") String connectionID, @QueryParam("parentID") String parentID)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the connection directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
Directory<String, Connection> connectionDirectory =
|
||||
rootGroup.getConnectionDirectory();
|
||||
|
||||
// Find the new parent connection group
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory = rootGroup.getConnectionGroupDirectory();
|
||||
ConnectionGroup parentConnectionGroup = connectionGroupDirectory.get(parentID);
|
||||
|
||||
if (parentConnectionGroup == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No ConnectionGroup found with the provided parentID.");
|
||||
|
||||
// Move the connection
|
||||
connectionDirectory.move(connectionID, parentConnectionGroup.getConnectionDirectory());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest.connection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
|
||||
/**
|
||||
* A service for performing useful manipulations on REST Connections.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class ConnectionService {
|
||||
|
||||
/**
|
||||
* Converts a Connection Directory to a list of APIConnection objects for
|
||||
* exposing with the REST endpoints.
|
||||
*
|
||||
* @param connectionDirectory The Connection Directory to convert for REST endpoint use.
|
||||
* @return A List of APIConnection objects for use with the REST endpoint.
|
||||
* @throws GuacamoleException If an error occurs while converting the
|
||||
* connection directory.
|
||||
*/
|
||||
public List<APIConnection> convertConnectionList(Directory<String, Connection> connectionDirectory)
|
||||
throws GuacamoleException {
|
||||
|
||||
List<APIConnection> restConnections = new ArrayList<APIConnection>();
|
||||
|
||||
for (String connectionID : connectionDirectory.getIdentifiers())
|
||||
restConnections.add(new APIConnection(connectionDirectory.get(connectionID)));
|
||||
|
||||
return restConnections;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -22,10 +22,11 @@
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest.connectiongroup;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup.Type;
|
||||
import org.glyptodon.guacamole.net.basic.rest.APIConstants;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connection.APIConnection;
|
||||
|
||||
/**
|
||||
* A simple connection group to expose through the REST endpoints.
|
||||
@@ -35,6 +36,11 @@ import org.glyptodon.guacamole.net.basic.rest.APIConstants;
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class APIConnectionGroup {
|
||||
|
||||
/**
|
||||
* The identifier of the root connection group.
|
||||
*/
|
||||
public static final String ROOT_IDENTIFIER = "ROOT";
|
||||
|
||||
/**
|
||||
* The name of this connection group.
|
||||
*/
|
||||
@@ -54,6 +60,18 @@ public class APIConnectionGroup {
|
||||
* The type of this connection group.
|
||||
*/
|
||||
private Type type;
|
||||
|
||||
/**
|
||||
* All child connection groups. If children are not being queried, this may
|
||||
* be omitted.
|
||||
*/
|
||||
private Collection<APIConnectionGroup> childConnectionGroups;
|
||||
|
||||
/**
|
||||
* All child connections. If children are not being queried, this may be
|
||||
* omitted.
|
||||
*/
|
||||
private Collection<APIConnection> childConnections;
|
||||
|
||||
/**
|
||||
* Create an empty APIConnectionGroup.
|
||||
@@ -73,7 +91,7 @@ public class APIConnectionGroup {
|
||||
|
||||
// Use the explicit ROOT group ID
|
||||
if (this.parentIdentifier == null)
|
||||
this.parentIdentifier = APIConstants.ROOT_CONNECTION_GROUP_IDENTIFIER;
|
||||
this.parentIdentifier = ROOT_IDENTIFIER;
|
||||
|
||||
this.name = connectionGroup.getName();
|
||||
this.type = connectionGroup.getType();
|
||||
@@ -144,4 +162,52 @@ public class APIConnectionGroup {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of all child connection groups, or null if children
|
||||
* have not been queried.
|
||||
*
|
||||
* @return
|
||||
* A collection of all child connection groups, or null if children
|
||||
* have not been queried.
|
||||
*/
|
||||
public Collection<APIConnectionGroup> getChildConnectionGroups() {
|
||||
return childConnectionGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the collection of all child connection groups to the given
|
||||
* collection, which may be null if children have not been queried.
|
||||
*
|
||||
* @param childConnectionGroups
|
||||
* The collection containing all child connection groups of this
|
||||
* connection group, or null if children have not been queried.
|
||||
*/
|
||||
public void setChildConnectionGroups(Collection<APIConnectionGroup> childConnectionGroups) {
|
||||
this.childConnectionGroups = childConnectionGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of all child connections, or null if children have
|
||||
* not been queried.
|
||||
*
|
||||
* @return
|
||||
* A collection of all child connections, or null if children have not
|
||||
* been queried.
|
||||
*/
|
||||
public Collection<APIConnection> getChildConnections() {
|
||||
return childConnections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the collection of all child connections to the given collection,
|
||||
* which may be null if children have not been queried.
|
||||
*
|
||||
* @param childConnections
|
||||
* The collection containing all child connections of this connection
|
||||
* group, or null if children have not been queried.
|
||||
*/
|
||||
public void setChildConnections(Collection<APIConnection> childConnections) {
|
||||
this.childConnections = childConnections;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -23,7 +23,8 @@
|
||||
package org.glyptodon.guacamole.net.basic.rest.connectiongroup;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
@@ -34,15 +35,19 @@ import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
||||
import org.glyptodon.guacamole.net.auth.Connection;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
||||
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
|
||||
import org.glyptodon.guacamole.net.basic.rest.HTTPException;
|
||||
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.connection.APIConnection;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -51,7 +56,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
@Path("/connectionGroup")
|
||||
@Path("/connectionGroups")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public class ConnectionGroupRESTService {
|
||||
@@ -68,63 +73,124 @@ public class ConnectionGroupRESTService {
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* A service for managing the REST endpoint APIConnection objects.
|
||||
*/
|
||||
@Inject
|
||||
private ConnectionGroupService connectionGroupService;
|
||||
|
||||
/**
|
||||
* The ID that will be guaranteed to refer to the root connection group.
|
||||
*/
|
||||
private static final String ROOT_CONNECTION_GROUP_ID = "ROOT";
|
||||
|
||||
/**
|
||||
* Gets a list of connection groups with the given ConnectionGroup parentID.
|
||||
* If no parentID is provided, returns the connection groups from the root group.
|
||||
* Retrieves the given connection group from the user context, including
|
||||
* all descendant connections and groups if requested.
|
||||
*
|
||||
* @param userContext
|
||||
* The user context from which to retrieve the connection group.
|
||||
*
|
||||
* @param identifier
|
||||
* The unique identifier of the connection group to retrieve.
|
||||
*
|
||||
* @param includeDescendants
|
||||
* Whether the descendant connections and groups of the given
|
||||
* connection group should also be retrieved.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param parentID The ID of the ConnectionGroup the connection groups
|
||||
* belong to. If null, the root connection group will be used.
|
||||
* @return The connection list.
|
||||
* @throws GuacamoleException If a problem is encountered while listing connection groups.
|
||||
* @param permission
|
||||
* The permission the current user must have for a connection or
|
||||
* connection group to be returned in the results, if any. If null
|
||||
* is specified, no filtering by permission will be performed.
|
||||
*
|
||||
* @return
|
||||
* The requested connection group, or null if no such connection group
|
||||
* exists.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the requested connection group
|
||||
* or any of its descendants.
|
||||
*/
|
||||
@GET
|
||||
@AuthProviderRESTExposure
|
||||
public List<APIConnectionGroup> getConnectionGroups(@QueryParam("token") String authToken, @QueryParam("parentID") String parentID)
|
||||
private APIConnectionGroup retrieveConnectionGroup(UserContext userContext,
|
||||
String identifier, boolean includeDescendants, ObjectPermission.Type permission)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
User self = userContext.self();
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// If the parent connection group is passed in, try to find it.
|
||||
ConnectionGroup parentConnectionGroup;
|
||||
if (parentID == null)
|
||||
parentConnectionGroup = userContext.getRootConnectionGroup();
|
||||
ConnectionGroup connectionGroup;
|
||||
|
||||
// Use root group if requested
|
||||
if (identifier == null || identifier.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||
connectionGroup = rootGroup;
|
||||
|
||||
// Otherwise, query requested group using root group directory
|
||||
else {
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory = rootGroup.getConnectionGroupDirectory();
|
||||
parentConnectionGroup = connectionGroupDirectory.get(parentID);
|
||||
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory =
|
||||
rootGroup.getConnectionGroupDirectory();
|
||||
|
||||
// Get the connection group from root directory
|
||||
connectionGroup = connectionGroupDirectory.get(identifier);
|
||||
if (connectionGroup == null)
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
if (parentConnectionGroup == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No connection group found with the provided parentID.");
|
||||
// Wrap queried connection group
|
||||
APIConnectionGroup apiConnectionGroup = new APIConnectionGroup(connectionGroup);
|
||||
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory =
|
||||
parentConnectionGroup.getConnectionGroupDirectory();
|
||||
// Recursively query all descendants if necessary
|
||||
if (includeDescendants) {
|
||||
|
||||
// Query all child connections
|
||||
Collection<APIConnection> apiConnections = new ArrayList<APIConnection>();
|
||||
Directory<String, Connection> connectionDirectory = connectionGroup.getConnectionDirectory();
|
||||
|
||||
for (String childIdentifier : connectionDirectory.getIdentifiers()) {
|
||||
|
||||
// Pull current connection - silently ignore if connection was removed prior to read
|
||||
Connection childConnection = connectionDirectory.get(childIdentifier);
|
||||
if (childConnection == null)
|
||||
continue;
|
||||
|
||||
// Filter based on permission, if requested
|
||||
if (permission == null || self.hasPermission(new ConnectionPermission(permission, childIdentifier)))
|
||||
apiConnections.add(new APIConnection(childConnection));
|
||||
|
||||
}
|
||||
|
||||
// Associate child connections with current connection group
|
||||
apiConnectionGroup.setChildConnections(apiConnections);
|
||||
|
||||
// Query all child connection groups
|
||||
Collection<APIConnectionGroup> apiConnectionGroups = new ArrayList<APIConnectionGroup>();
|
||||
Directory<String, ConnectionGroup> groupDirectory = connectionGroup.getConnectionGroupDirectory();
|
||||
|
||||
for (String childIdentifier : groupDirectory.getIdentifiers()) {
|
||||
|
||||
// Pull current connection group - silently ignore if connection group was removed prior to read
|
||||
APIConnectionGroup childConnectionGroup = retrieveConnectionGroup(userContext, childIdentifier, true, permission);
|
||||
if (childConnectionGroup == null)
|
||||
continue;
|
||||
|
||||
apiConnectionGroups.add(childConnectionGroup);
|
||||
|
||||
}
|
||||
|
||||
// Associate child groups with current connection group
|
||||
apiConnectionGroup.setChildConnectionGroups(apiConnectionGroups);
|
||||
|
||||
}
|
||||
|
||||
// Return the connectiion group
|
||||
return apiConnectionGroup;
|
||||
|
||||
// Return the converted connection group list
|
||||
return connectionGroupService.convertConnectionGroupList(connectionGroupDirectory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets an individual connection group.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param connectionGroupID The ID of the ConnectionGroup.
|
||||
* @return The connection group.
|
||||
* @throws GuacamoleException If a problem is encountered while retrieving the connection group.
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connectionGroupID
|
||||
* The ID of the connection group to retrieve.
|
||||
*
|
||||
* @return
|
||||
* The connection group, without any descendants.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If a problem is encountered while retrieving the connection group.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{connectionGroupID}")
|
||||
@@ -133,34 +199,70 @@ public class ConnectionGroupRESTService {
|
||||
@PathParam("connectionGroupID") String connectionGroupID) throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the connection group directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Return the root group if it was asked for
|
||||
if (connectionGroupID != null && connectionGroupID.equals(ROOT_CONNECTION_GROUP_ID))
|
||||
return new APIConnectionGroup(rootGroup);
|
||||
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory =
|
||||
rootGroup.getConnectionGroupDirectory();
|
||||
|
||||
// Get the connection group
|
||||
ConnectionGroup connectionGroup = connectionGroupDirectory.get(connectionGroupID);
|
||||
// Retrieve requested connection group only
|
||||
APIConnectionGroup connectionGroup = retrieveConnectionGroup(userContext, connectionGroupID, false, null);
|
||||
if (connectionGroup == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No ConnectionGroup found with the provided ID.");
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\"");
|
||||
|
||||
// Return the connectiion group
|
||||
return new APIConnectionGroup(connectionGroup);
|
||||
return connectionGroup;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets an individual connection group and all children.
|
||||
*
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connectionGroupID
|
||||
* The ID of the connection group to retrieve.
|
||||
*
|
||||
* @param permission
|
||||
* If specified, limit the returned list to only those connections for
|
||||
* which the current user has the given permission. Otherwise, all
|
||||
* visible connections are returned. Connection groups are unaffected
|
||||
* by this parameter.
|
||||
*
|
||||
* @return
|
||||
* The requested connection group, including all descendants.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If a problem is encountered while retrieving the connection group or
|
||||
* its descendants.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{connectionGroupID}/tree")
|
||||
@AuthProviderRESTExposure
|
||||
public APIConnectionGroup getConnectionGroupTree(@QueryParam("token") String authToken,
|
||||
@PathParam("connectionGroupID") String connectionGroupID,
|
||||
@QueryParam("permission") ObjectPermission.Type permission)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Retrieve requested connection group and all descendants
|
||||
APIConnectionGroup connectionGroup = retrieveConnectionGroup(userContext, connectionGroupID, true, permission);
|
||||
if (connectionGroup == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\"");
|
||||
|
||||
return connectionGroup;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an individual connection group.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param connectionGroupID The ID of the ConnectionGroup to delete.
|
||||
* @throws GuacamoleException If a problem is encountered while deleting the connection group.
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connectionGroupID
|
||||
* The identifier of the connection group to delete.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while deleting the connection group.
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{connectionGroupID}")
|
||||
@@ -174,7 +276,7 @@ public class ConnectionGroupRESTService {
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Use the root group if it was asked for
|
||||
if (connectionGroupID != null && connectionGroupID.equals(ROOT_CONNECTION_GROUP_ID))
|
||||
if (connectionGroupID != null && connectionGroupID.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||
connectionGroupID = rootGroup.getIdentifier();
|
||||
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory =
|
||||
@@ -182,7 +284,7 @@ public class ConnectionGroupRESTService {
|
||||
|
||||
// Make sure the connection is there before trying to delete
|
||||
if (connectionGroupDirectory.get(connectionGroupID) == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No ConnectionGroup found with the provided ID.");
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\"");
|
||||
|
||||
// Delete the connection group
|
||||
connectionGroupDirectory.remove(connectionGroupID);
|
||||
@@ -195,42 +297,49 @@ public class ConnectionGroupRESTService {
|
||||
* connection group with the parentID. Otherwise, the root connection group
|
||||
* will be used.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param parentID The ID of the ConnectionGroup the connection groups
|
||||
* belong to. If null, the root connection group will be used.
|
||||
* @param connectionGroup The connection group to create.
|
||||
* @return The identifier of the new connection group.
|
||||
* @throws GuacamoleException If a problem is encountered while creating the connection group.
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connectionGroup
|
||||
* The connection group to create.
|
||||
*
|
||||
* @return
|
||||
* The identifier of the new connection group.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while creating the connection group.
|
||||
*/
|
||||
@POST
|
||||
@AuthProviderRESTExposure
|
||||
public String createConnectionGroup(@QueryParam("token") String authToken,
|
||||
@QueryParam("parentID") String parentID, APIConnectionGroup connectionGroup) throws GuacamoleException {
|
||||
public String createConnectionGroup(@QueryParam("token") String authToken,
|
||||
APIConnectionGroup connectionGroup) throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Validate that connection group data was provided
|
||||
if (connectionGroup == null)
|
||||
throw new GuacamoleClientException("A connection group is required for this request.");
|
||||
throw new GuacamoleClientException("Connection group JSON must be submitted when creating connections groups.");
|
||||
|
||||
// If the parent connection group is passed in, try to find it.
|
||||
String parentID = connectionGroup.getParentIdentifier();
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Use root group if no parent is specified
|
||||
ConnectionGroup parentConnectionGroup;
|
||||
if (parentID == null)
|
||||
parentConnectionGroup = userContext.getRootConnectionGroup();
|
||||
parentConnectionGroup = rootGroup;
|
||||
|
||||
// Pull specified connection group otherwise
|
||||
else {
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory = rootGroup.getConnectionGroupDirectory();
|
||||
parentConnectionGroup = connectionGroupDirectory.get(parentID);
|
||||
|
||||
if (parentConnectionGroup == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + parentID + "\"");
|
||||
}
|
||||
|
||||
if (parentConnectionGroup == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No ConnectionGroup found with the provided parentID.");
|
||||
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory =
|
||||
parentConnectionGroup.getConnectionGroupDirectory();
|
||||
|
||||
// Create the connection group
|
||||
// Add the new connection group
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory = parentConnectionGroup.getConnectionGroupDirectory();
|
||||
connectionGroupDirectory.add(new APIConnectionGroupWrapper(connectionGroup));
|
||||
|
||||
// Return the new connection group identifier
|
||||
@@ -239,15 +348,24 @@ public class ConnectionGroupRESTService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a connection group.
|
||||
* Updates a connection group. If the parent identifier of the
|
||||
* connection group is changed, the connection group will also be moved to
|
||||
* the new parent group.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param connectionGroupID The ID of the ConnectionGroup to update.
|
||||
* @param connectionGroup The connection group to update.
|
||||
* @throws GuacamoleException If a problem is encountered while updating the connection group.
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param connectionGroupID
|
||||
* The identifier of the existing connection group to update.
|
||||
*
|
||||
* @param connectionGroup
|
||||
* The data to update the existing connection group with.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while updating the connection group.
|
||||
*/
|
||||
@POST
|
||||
@PUT
|
||||
@Path("/{connectionGroupID}")
|
||||
@AuthProviderRESTExposure
|
||||
public void updateConnectionGroup(@QueryParam("token") String authToken,
|
||||
@@ -256,14 +374,15 @@ public class ConnectionGroupRESTService {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Validate that connection group data was provided
|
||||
if (connectionGroup == null)
|
||||
throw new GuacamoleClientException("A connection group is required for this request.");
|
||||
throw new GuacamoleClientException("Connection group JSON must be submitted when updating connection groups.");
|
||||
|
||||
// Get the connection directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Use the root group if it was asked for
|
||||
if (connectionGroupID != null && connectionGroupID.equals(ROOT_CONNECTION_GROUP_ID))
|
||||
if (connectionGroupID != null && connectionGroupID.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||
connectionGroupID = rootGroup.getIdentifier();
|
||||
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory =
|
||||
@@ -271,51 +390,11 @@ public class ConnectionGroupRESTService {
|
||||
|
||||
// Make sure the connection group is there before trying to update
|
||||
if (connectionGroupDirectory.get(connectionGroupID) == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No ConnectionGroup found with the provided ID.");
|
||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + connectionGroupID + "\"");
|
||||
|
||||
// Update the connection group
|
||||
connectionGroupDirectory.update(new APIConnectionGroupWrapper(connectionGroup));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves an individual connection group to a different connection group.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param connectionGroupID The ID of the ConnectionGroup to move.
|
||||
* @param parentID The ID of the ConnectionGroup the connection group is to be moved to.
|
||||
* @throws GuacamoleException If a problem is encountered while moving the connection group.
|
||||
*/
|
||||
@PUT
|
||||
@Path("/{connectionGroupID}")
|
||||
@AuthProviderRESTExposure
|
||||
public void moveConnectionGroup(@QueryParam("token") String authToken,
|
||||
@PathParam("connectionGroupID") String connectionGroupID,
|
||||
@QueryParam("parentID") String parentID) throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the connection group directory
|
||||
ConnectionGroup rootGroup = userContext.getRootConnectionGroup();
|
||||
|
||||
// Use the root group if it was asked for
|
||||
if (connectionGroupID != null && connectionGroupID.equals(ROOT_CONNECTION_GROUP_ID))
|
||||
connectionGroupID = rootGroup.getIdentifier();
|
||||
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory =
|
||||
rootGroup.getConnectionGroupDirectory();
|
||||
|
||||
// Find the new parent connection group
|
||||
Directory<String, ConnectionGroup> newConnectionGroupDirectory = rootGroup.getConnectionGroupDirectory();
|
||||
ConnectionGroup parentConnectionGroup = newConnectionGroupDirectory.get(parentID);
|
||||
|
||||
if (parentConnectionGroup == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "No ConnectionGroup found with the provided parentID.");
|
||||
|
||||
// Move the connection group
|
||||
connectionGroupDirectory.move(connectionGroupID, parentConnectionGroup.getConnectionGroupDirectory());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest.connectiongroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.ConnectionGroup;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
|
||||
/**
|
||||
* A service for performing useful manipulations on REST ConnectionGroups.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class ConnectionGroupService {
|
||||
|
||||
/**
|
||||
* Converts a ConnectionGroup directory to a list of APIConnectionGroup
|
||||
* objects for exposing with the REST endpoints.
|
||||
*
|
||||
* @param connectionGroupDirectory The ConnectionGroup Directory to convert for REST endpoint use.
|
||||
* @return A List of APIConnectionGroup objects for use with the REST endpoint.
|
||||
* @throws GuacamoleException If an error occurs while converting the
|
||||
* connection group directory.
|
||||
*/
|
||||
public List<APIConnectionGroup> convertConnectionGroupList(
|
||||
Directory<String, ConnectionGroup> connectionGroupDirectory) throws GuacamoleException {
|
||||
|
||||
List<APIConnectionGroup> restConnectionGroups = new ArrayList<APIConnectionGroup>();
|
||||
|
||||
for (String connectionGroupID : connectionGroupDirectory.getIdentifiers())
|
||||
restConnectionGroups.add(new APIConnectionGroup(connectionGroupDirectory.get(connectionGroupID)));
|
||||
|
||||
return restConnectionGroups;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,228 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest.permission;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ConnectionGroupPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.UserPermission;
|
||||
|
||||
/**
|
||||
* A simple user permission to expose through the REST endpoints.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
|
||||
public class APIPermission {
|
||||
|
||||
/**
|
||||
* Create an empty APIPermission.
|
||||
*/
|
||||
public APIPermission() {}
|
||||
|
||||
/**
|
||||
* The type of object that this permission refers to.
|
||||
*/
|
||||
private ObjectType objectType;
|
||||
|
||||
/**
|
||||
* The type of object that a permission can refer to.
|
||||
*/
|
||||
public enum ObjectType {
|
||||
|
||||
/**
|
||||
* A normal connection.
|
||||
*/
|
||||
CONNECTION,
|
||||
|
||||
/**
|
||||
* A connection group.
|
||||
*/
|
||||
CONNECTION_GROUP,
|
||||
|
||||
/**
|
||||
* A Guacamole user.
|
||||
*/
|
||||
USER,
|
||||
|
||||
/**
|
||||
* The Guacamole system itself.
|
||||
*/
|
||||
SYSTEM
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The identifier of the object that this permission refers to.
|
||||
*/
|
||||
private String objectIdentifier;
|
||||
|
||||
/**
|
||||
* The object permission type for this APIPermission, if relevant. This is
|
||||
* only used if this.objectType is CONNECTION, CONNECTION_GROUP, or USER.
|
||||
*/
|
||||
private ObjectPermission.Type objectPermissionType;
|
||||
|
||||
/**
|
||||
* The system permission type for this APIPermission, if relevant. This is
|
||||
* only used if this.objectType is SYSTEM.
|
||||
*/
|
||||
private SystemPermission.Type systemPermissionType;
|
||||
|
||||
/**
|
||||
* Create an APIConnection from a Connection record.
|
||||
*
|
||||
* @param permission The permission to create this APIPermission from.
|
||||
*/
|
||||
public APIPermission(Permission permission) {
|
||||
|
||||
// Connection permission
|
||||
if (permission instanceof ConnectionPermission) {
|
||||
this.objectType = ObjectType.CONNECTION;
|
||||
this.objectPermissionType = ((ConnectionPermission) permission).getType();
|
||||
this.objectIdentifier = ((ConnectionPermission) permission).getObjectIdentifier();
|
||||
}
|
||||
|
||||
// Connection group permission
|
||||
else if (permission instanceof ConnectionGroupPermission) {
|
||||
this.objectType = ObjectType.CONNECTION_GROUP;
|
||||
this.objectPermissionType = ((ConnectionGroupPermission) permission).getType();
|
||||
this.objectIdentifier = ((ConnectionGroupPermission) permission).getObjectIdentifier();
|
||||
}
|
||||
|
||||
// User permission
|
||||
else if (permission instanceof UserPermission) {
|
||||
this.objectType = ObjectType.USER;
|
||||
this.objectPermissionType = ((UserPermission) permission).getType();
|
||||
this.objectIdentifier = ((UserPermission) permission).getObjectIdentifier();
|
||||
}
|
||||
|
||||
// System permission
|
||||
else if (permission instanceof SystemPermission) {
|
||||
this.objectType = ObjectType.SYSTEM;
|
||||
this.systemPermissionType = ((SystemPermission) permission).getType();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of object that this permission refers to.
|
||||
*
|
||||
* @return The type of object that this permission refers to.
|
||||
*/
|
||||
public ObjectType getObjectType() {
|
||||
return objectType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of object that this permission refers to.
|
||||
* @param objectType The type of object that this permission refers to.
|
||||
*/
|
||||
public void setObjectType(ObjectType objectType) {
|
||||
this.objectType = objectType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the permission type.
|
||||
*
|
||||
* @return A string representation of the permission type.
|
||||
*/
|
||||
public String getPermissionType() {
|
||||
switch(this.objectType) {
|
||||
case CONNECTION:
|
||||
case CONNECTION_GROUP:
|
||||
case USER:
|
||||
return this.objectPermissionType.toString();
|
||||
case SYSTEM:
|
||||
return this.systemPermissionType.toString();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the permission type from a string representation of that type.
|
||||
* Since it's not clear at this point whether this is an object permission or
|
||||
* system permission, try to set both of them.
|
||||
*
|
||||
* @param permissionType The string representation of the permission type.
|
||||
*/
|
||||
public void setPermissionType(String permissionType) {
|
||||
try {
|
||||
this.objectPermissionType = ObjectPermission.Type.valueOf(permissionType);
|
||||
} catch(IllegalArgumentException e) {}
|
||||
|
||||
try {
|
||||
this.systemPermissionType = SystemPermission.Type.valueOf(permissionType);
|
||||
} catch(IllegalArgumentException e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier of the object that this permission refers to.
|
||||
*
|
||||
* @return The identifier of the object that this permission refers to.
|
||||
*/
|
||||
public String getObjectIdentifier() {
|
||||
return objectIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the identifier of the object that this permission refers to.
|
||||
*
|
||||
* @param objectIdentifier The identifier of the object that this permission refers to.
|
||||
*/
|
||||
public void setObjectIdentifier(String objectIdentifier) {
|
||||
this.objectIdentifier = objectIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an org.glyptodon.guacamole.net.auth.permission.Permission
|
||||
* representation of this APIPermission.
|
||||
*
|
||||
* @return An org.glyptodon.guacamole.net.auth.permission.Permission
|
||||
* representation of this APIPermission.
|
||||
*/
|
||||
public Permission toPermission() {
|
||||
switch(this.objectType) {
|
||||
case CONNECTION:
|
||||
return new ConnectionPermission
|
||||
(this.objectPermissionType, this.objectIdentifier);
|
||||
case CONNECTION_GROUP:
|
||||
return new ConnectionGroupPermission
|
||||
(this.objectPermissionType, this.objectIdentifier);
|
||||
case USER:
|
||||
return new UserPermission
|
||||
(this.objectPermissionType, this.objectIdentifier);
|
||||
case SYSTEM:
|
||||
return new SystemPermission(this.systemPermissionType);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest.permission;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleServerException;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ConnectionGroupPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.UserPermission;
|
||||
|
||||
/**
|
||||
* The set of permissions which are granted to a specific user, organized by
|
||||
* object type and, if applicable, identifier. This object can be constructed
|
||||
* with arbitrary permissions present, or manipulated after creation through
|
||||
* the manipulation or replacement of its collections of permissions, but is
|
||||
* otherwise not intended for internal use as a data structure for permissions.
|
||||
* Its primary purpose is as a hierarchical format for exchanging granted
|
||||
* permissions with REST clients.
|
||||
*/
|
||||
public class APIPermissionSet {
|
||||
|
||||
/**
|
||||
* Map of connection ID to the set of granted permissions.
|
||||
*/
|
||||
private Map<String, EnumSet<ObjectPermission.Type>> connectionPermissions = new HashMap<String, EnumSet<ObjectPermission.Type>>();
|
||||
|
||||
/**
|
||||
* Map of connection group ID to the set of granted permissions.
|
||||
*/
|
||||
private Map<String, EnumSet<ObjectPermission.Type>> connectionGroupPermissions = new HashMap<String, EnumSet<ObjectPermission.Type>>();
|
||||
|
||||
/**
|
||||
* Map of user ID to the set of granted permissions.
|
||||
*/
|
||||
private Map<String, EnumSet<ObjectPermission.Type>> userPermissions = new HashMap<String, EnumSet<ObjectPermission.Type>>();
|
||||
|
||||
/**
|
||||
* Set of all granted system-level permissions.
|
||||
*/
|
||||
private EnumSet<SystemPermission.Type> systemPermissions = EnumSet.noneOf(SystemPermission.Type.class);
|
||||
|
||||
/**
|
||||
* Adds the given object permission to the given map of object identifier
|
||||
* to permission set.
|
||||
*
|
||||
* @param permissions
|
||||
* The map to add the given permission to.
|
||||
*
|
||||
* @param permission
|
||||
* The permission to add.
|
||||
*/
|
||||
private void addPermission(Map<String, EnumSet<ObjectPermission.Type>> permissions, ObjectPermission<String> permission) {
|
||||
|
||||
// Pull set of permissions for given object
|
||||
String id = permission.getObjectIdentifier();
|
||||
EnumSet<ObjectPermission.Type> types = permissions.get(id);
|
||||
|
||||
// If set does not yet exist, create it
|
||||
if (types == null) {
|
||||
types = EnumSet.of(permission.getType());
|
||||
permissions.put(id, types);
|
||||
}
|
||||
|
||||
// Otherwise, add the specified permission
|
||||
else
|
||||
types.add(permission.getType());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given system-level permission to the given set of granted
|
||||
* system permissions.
|
||||
*
|
||||
* @param permissions
|
||||
* The set of system permissions to add the given permission to.
|
||||
*
|
||||
* @param permission
|
||||
* The permission to add.
|
||||
*/
|
||||
private void addPermission(EnumSet<SystemPermission.Type> permissions, SystemPermission permission) {
|
||||
permissions.add(permission.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given permission to the appropriate type-specific set or map of
|
||||
* permissions based on the permission class. Only connection, connection
|
||||
* group, user, and system permissions are supported. Unsupported
|
||||
* permission types will result in a GuacamoleException being thrown.
|
||||
*
|
||||
* @param permission The permission to add.
|
||||
* @throws GuacamoleException If the permission is of an unsupported type.
|
||||
*/
|
||||
private void addPermission(Permission<?> permission) throws GuacamoleException {
|
||||
|
||||
// Connection permissions
|
||||
if (permission instanceof ConnectionPermission)
|
||||
addPermission(connectionPermissions, (ConnectionPermission) permission);
|
||||
|
||||
// Connection group permissions
|
||||
else if (permission instanceof ConnectionGroupPermission)
|
||||
addPermission(connectionGroupPermissions, (ConnectionGroupPermission) permission);
|
||||
|
||||
// User permissions
|
||||
else if (permission instanceof UserPermission)
|
||||
addPermission(userPermissions, (UserPermission) permission);
|
||||
|
||||
// System permissions
|
||||
else if (permission instanceof SystemPermission)
|
||||
addPermission(systemPermissions, (SystemPermission) permission);
|
||||
|
||||
// Unknown / unsupported permission type
|
||||
else
|
||||
throw new GuacamoleServerException("Serialization of permission type \"" + permission.getClass() + "\" not implemented.");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new permission set which contains no granted permissions. Any
|
||||
* permissions must be added by manipulating or replacing the applicable
|
||||
* permission collection.
|
||||
*/
|
||||
public APIPermissionSet() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new permission set having the given permissions.
|
||||
*
|
||||
* @param permissions
|
||||
* The permissions to initially store within the permission set.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If any of the given permissions are of an unsupported type.
|
||||
*/
|
||||
public APIPermissionSet(Iterable<Permission> permissions) throws GuacamoleException {
|
||||
|
||||
// Add all provided permissions
|
||||
for (Permission permission : permissions)
|
||||
addPermission(permission);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new permission set having the given permissions.
|
||||
*
|
||||
* @param permissions
|
||||
* The permissions to initially store within the permission set.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If any of the given permissions are of an unsupported type.
|
||||
*/
|
||||
public APIPermissionSet(Permission... permissions) throws GuacamoleException {
|
||||
|
||||
// Add all provided permissions
|
||||
for (Permission permission : permissions)
|
||||
addPermission(permission);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of connection IDs to the set of permissions granted for
|
||||
* that connection. If no permissions are granted to a particular
|
||||
* connection, its ID will not be present as a key in the map. This map is
|
||||
* mutable, and changes to this map will affect the permission set
|
||||
* directly.
|
||||
*
|
||||
* @return
|
||||
* A map of connection IDs to the set of permissions granted for that
|
||||
* connection.
|
||||
*/
|
||||
public Map<String, EnumSet<ObjectPermission.Type>> getConnectionPermissions() {
|
||||
return connectionPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of connection group IDs to the set of permissions granted
|
||||
* for that connection group. If no permissions are granted to a particular
|
||||
* connection group, its ID will not be present as a key in the map. This
|
||||
* map is mutable, and changes to this map will affect the permission set
|
||||
* directly.
|
||||
*
|
||||
* @return
|
||||
* A map of connection group IDs to the set of permissions granted for
|
||||
* that connection group.
|
||||
*/
|
||||
public Map<String, EnumSet<ObjectPermission.Type>> getConnectionGroupPermissions() {
|
||||
return connectionGroupPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of user IDs to the set of permissions granted for that
|
||||
* user. If no permissions are granted to a particular user, its ID will
|
||||
* not be present as a key in the map. This map is mutable, and changes to
|
||||
* to this map will affect the permission set directly.
|
||||
*
|
||||
* @return
|
||||
* A map of user IDs to the set of permissions granted for that user.
|
||||
*/
|
||||
public Map<String, EnumSet<ObjectPermission.Type>> getUserPermissions() {
|
||||
return userPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of granted system-level permissions. If no permissions
|
||||
* are granted at the system level, this will be an empty set. This set is
|
||||
* mutable, and changes to this set will affect the permission set
|
||||
* directly.
|
||||
*
|
||||
* @return
|
||||
* The set of granted system-level permissions.
|
||||
*/
|
||||
public EnumSet<SystemPermission.Type> getSystemPermissions() {
|
||||
return systemPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current map of connection permissions with the given map,
|
||||
* which must map connection ID to its corresponding set of granted
|
||||
* permissions. If a connection has no permissions, its ID must not be
|
||||
* present as a key in the map.
|
||||
*
|
||||
* @param connectionPermissions
|
||||
* The map which must replace the currently-stored map of permissions.
|
||||
*/
|
||||
public void setConnectionPermissions(Map<String, EnumSet<ObjectPermission.Type>> connectionPermissions) {
|
||||
this.connectionPermissions = connectionPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current map of connection group permissions with the given
|
||||
* map, which must map connection group ID to its corresponding set of
|
||||
* granted permissions. If a connection group has no permissions, its ID
|
||||
* must not be present as a key in the map.
|
||||
*
|
||||
* @param connectionGroupPermissions
|
||||
* The map which must replace the currently-stored map of permissions.
|
||||
*/
|
||||
public void setConnectionGroupPermissions(Map<String, EnumSet<ObjectPermission.Type>> connectionGroupPermissions) {
|
||||
this.connectionGroupPermissions = connectionGroupPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current map of user permissions with the given map, which
|
||||
* must map user ID to its corresponding set of granted permissions. If a
|
||||
* user has no permissions, its ID must not be present as a key in the map.
|
||||
*
|
||||
* @param userPermissions
|
||||
* The map which must replace the currently-stored map of permissions.
|
||||
*/
|
||||
public void setUserPermissions(Map<String, EnumSet<ObjectPermission.Type>> userPermissions) {
|
||||
this.userPermissions = userPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current set of system-level permissions with the given set.
|
||||
* If no system-level permissions are granted, the empty set must be
|
||||
* specified.
|
||||
*
|
||||
* @param systemPermissions
|
||||
* The set which must replace the currently-stored set of permissions.
|
||||
*/
|
||||
public void setSystemPermissions(EnumSet<SystemPermission.Type> systemPermissions) {
|
||||
this.systemPermissions = systemPermissions;
|
||||
}
|
||||
|
||||
}
|
@@ -1,217 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest.permission;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
||||
import org.glyptodon.guacamole.net.basic.rest.APIPatch;
|
||||
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
|
||||
import org.glyptodon.guacamole.net.basic.rest.HTTPException;
|
||||
import org.glyptodon.guacamole.net.basic.rest.PATCH;
|
||||
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A REST Service for handling connection CRUD operations.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
@Path("/permission")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public class PermissionRESTService {
|
||||
|
||||
/**
|
||||
* Logger for this class.
|
||||
*/
|
||||
private static final Logger logger = LoggerFactory.getLogger(PermissionRESTService.class);
|
||||
|
||||
/**
|
||||
* A service for authenticating users from auth tokens.
|
||||
*/
|
||||
@Inject
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* A service for managing the REST endpoint APIPermission objects.
|
||||
*/
|
||||
@Inject
|
||||
private PermissionService permissionService;
|
||||
|
||||
/**
|
||||
* Gets a list of permissions for the user with the given userID.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param userID The ID of the user to retrieve permissions for.
|
||||
* @return The permission list.
|
||||
* @throws GuacamoleException If a problem is encountered while listing permissions.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{userID}")
|
||||
@AuthProviderRESTExposure
|
||||
public List<APIPermission> getPermissions(@QueryParam("token") String authToken, @PathParam("userID") String userID)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the user
|
||||
User user = userContext.getUserDirectory().get(userID);
|
||||
if (user == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "User not found with the provided userID.");
|
||||
|
||||
return permissionService.convertPermissionList(user.getPermissions());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a permissions for a user with the given userID.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param userID The user ID to add the permission for.
|
||||
* @param permission The permission to add for the user with the given userID.
|
||||
* @throws GuacamoleException If a problem is encountered while adding the permission.
|
||||
*/
|
||||
@POST
|
||||
@Path("/{userID}")
|
||||
@AuthProviderRESTExposure
|
||||
public void addPermission(@QueryParam("token") String authToken,
|
||||
@PathParam("userID") String userID, APIPermission permission)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the user
|
||||
User user = userContext.getUserDirectory().get(userID);
|
||||
if (user == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "User not found with the provided userID.");
|
||||
|
||||
// Add the new permission
|
||||
user.addPermission(permission.toPermission());
|
||||
userContext.getUserDirectory().update(user);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a permissions for a user with the given userID.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param userID The user ID to remove the permission for.
|
||||
* @param permission The permission to remove for the user with the given userID.
|
||||
* @throws GuacamoleException If a problem is encountered while removing the permission.
|
||||
*/
|
||||
@POST
|
||||
@Path("/remove/{userID}/")
|
||||
@AuthProviderRESTExposure
|
||||
public void removePermission(@QueryParam("token") String authToken,
|
||||
@PathParam("userID") String userID, APIPermission permission)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the user
|
||||
User user = userContext.getUserDirectory().get(userID);
|
||||
if (user == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "User not found with the provided userID.");
|
||||
|
||||
// Remove the permission
|
||||
user.removePermission(permission.toPermission());
|
||||
userContext.getUserDirectory().update(user);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies a given list of permission patches.
|
||||
*
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param patches The permission patches to apply for this request.
|
||||
* @throws GuacamoleException If a problem is encountered while removing the permission.
|
||||
*/
|
||||
@PATCH
|
||||
@AuthProviderRESTExposure
|
||||
public void patchPermissions(@QueryParam("token") String authToken,
|
||||
List<APIPatch<APIPermission>> patches) throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the user directory
|
||||
Directory<String, User> userDirectory = userContext.getUserDirectory();
|
||||
|
||||
// All users who have had permissions added or removed
|
||||
Map<String, User> modifiedUsers = new HashMap<String, User>();
|
||||
|
||||
for (APIPatch<APIPermission> patch : patches) {
|
||||
|
||||
String userID = patch.getPath();
|
||||
Permission permission = patch.getValue().toPermission();
|
||||
|
||||
// See if we've already modified this user in this request
|
||||
User user = modifiedUsers.get(userID);
|
||||
if (user == null)
|
||||
user = userDirectory.get(userID);
|
||||
|
||||
if (user == null)
|
||||
throw new HTTPException(Status.NOT_FOUND, "User not found with userID " + userID + ".");
|
||||
|
||||
// Only the add and remove operations are supported for permissions
|
||||
switch(patch.getOp()) {
|
||||
case add:
|
||||
user.addPermission(permission);
|
||||
modifiedUsers.put(userID, user);
|
||||
break;
|
||||
case remove:
|
||||
user.removePermission(permission);
|
||||
modifiedUsers.put(userID, user);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Save the permission changes for all modified users
|
||||
for (User user : modifiedUsers.values())
|
||||
userDirectory.update(user);
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest.permission;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
||||
|
||||
/**
|
||||
* A service for performing useful manipulations on REST Permissions.
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
public class PermissionService {
|
||||
|
||||
/**
|
||||
* Converts a list of Permission to a list of APIPermission objects for
|
||||
* exposing with the REST endpoints.
|
||||
*
|
||||
* @param permissions The Connections to convert for REST endpoint use.
|
||||
* @return A List of APIPermission objects for use with the REST endpoint.
|
||||
*/
|
||||
public List<APIPermission> convertPermissionList(Iterable<? extends Permission> permissions) {
|
||||
|
||||
List<APIPermission> restPermissions = new ArrayList<APIPermission>();
|
||||
|
||||
for(Permission permission : permissions)
|
||||
restPermissions.add(new APIPermission(permission));
|
||||
|
||||
return restPermissions;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of APIPermission to a set of Permission objects for internal
|
||||
* Guacamole use.
|
||||
*
|
||||
* @param restPermissions The APIPermission objects from the REST endpoints.
|
||||
* @return a List of Permission objects for internal Guacamole use.
|
||||
*/
|
||||
public Set<Permission> convertAPIPermissionList(Iterable<APIPermission> restPermissions) {
|
||||
|
||||
Set<Permission> permissions = new HashSet<Permission>();
|
||||
|
||||
for(APIPermission restPermission : restPermissions)
|
||||
permissions.add(restPermission.toPermission());
|
||||
|
||||
return permissions;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -24,14 +24,15 @@ package org.glyptodon.guacamole.net.basic.rest.protocol;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Map;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.basic.ProtocolInfo;
|
||||
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
|
||||
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -40,9 +41,8 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
@Path("/protocol")
|
||||
@Path("/protocols")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public class ProtocolRESTService {
|
||||
|
||||
/**
|
||||
@@ -50,6 +50,12 @@ public class ProtocolRESTService {
|
||||
*/
|
||||
private static final Logger logger = LoggerFactory.getLogger(ProtocolRESTService.class);
|
||||
|
||||
/**
|
||||
* A service for authenticating users from auth tokens.
|
||||
*/
|
||||
@Inject
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* Service for retrieving protocol definitions.
|
||||
*/
|
||||
@@ -59,15 +65,27 @@ public class ProtocolRESTService {
|
||||
/**
|
||||
* Gets a map of protocols defined in the system - protocol name to protocol.
|
||||
*
|
||||
* @return The protocol map.
|
||||
* @throws GuacamoleException If a problem is encountered while listing protocols.
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @return
|
||||
* A map of protocol information, where each key is the unique name
|
||||
* associated with that protocol.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the available protocols.
|
||||
*/
|
||||
@GET
|
||||
@AuthProviderRESTExposure
|
||||
public Map<String, ProtocolInfo> getProtocols() throws GuacamoleException {
|
||||
public Map<String, ProtocolInfo> getProtocols(@QueryParam("token") String authToken) throws GuacamoleException {
|
||||
|
||||
// Verify the given auth token is valid
|
||||
authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get and return a map of all protocols.
|
||||
return protocolRetrievalservice.getProtocolMap();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -23,25 +23,40 @@
|
||||
package org.glyptodon.guacamole.net.basic.rest.user;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
import org.glyptodon.guacamole.net.auth.UserContext;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ConnectionGroupPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ConnectionPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.ObjectPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||
import org.glyptodon.guacamole.net.auth.permission.UserPermission;
|
||||
import org.glyptodon.guacamole.net.basic.rest.APIPatch;
|
||||
import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.add;
|
||||
import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.remove;
|
||||
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
|
||||
import org.glyptodon.guacamole.net.basic.rest.HTTPException;
|
||||
import org.glyptodon.guacamole.net.basic.rest.PATCH;
|
||||
import org.glyptodon.guacamole.net.basic.rest.auth.AuthenticationService;
|
||||
import org.glyptodon.guacamole.net.basic.rest.permission.APIPermissionSet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -50,7 +65,7 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author James Muehlner
|
||||
*/
|
||||
@Path("/user")
|
||||
@Path("/users")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public class UserRESTService {
|
||||
@@ -59,6 +74,30 @@ public class UserRESTService {
|
||||
* Logger for this class.
|
||||
*/
|
||||
private static final Logger logger = LoggerFactory.getLogger(UserRESTService.class);
|
||||
|
||||
/**
|
||||
* The prefix of any path within an operation of a JSON patch which
|
||||
* modifies the permissions of a user regarding a specific connection.
|
||||
*/
|
||||
private static final String CONNECTION_PERMISSION_PATCH_PATH_PREFIX = "/connectionPermissions/";
|
||||
|
||||
/**
|
||||
* The prefix of any path within an operation of a JSON patch which
|
||||
* modifies the permissions of a user regarding a specific connection group.
|
||||
*/
|
||||
private static final String CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX = "/connectionGroupPermissions/";
|
||||
|
||||
/**
|
||||
* The prefix of any path within an operation of a JSON patch which
|
||||
* modifies the permissions of a user regarding another, specific user.
|
||||
*/
|
||||
private static final String USER_PERMISSION_PATCH_PATH_PREFIX = "/userPermissions/";
|
||||
|
||||
/**
|
||||
* The path of any operation within a JSON patch which modifies the
|
||||
* permissions of a user regarding the entire system.
|
||||
*/
|
||||
private static final String SYSTEM_PERMISSION_PATCH_PATH = "/systemPermissions";
|
||||
|
||||
/**
|
||||
* A service for authenticating users from auth tokens.
|
||||
@@ -67,44 +106,73 @@ public class UserRESTService {
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* A service for managing the REST endpoint APIPermission objects.
|
||||
*/
|
||||
@Inject
|
||||
private UserService userService;
|
||||
|
||||
/**
|
||||
* Gets a list of users in the system.
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @return The user list.
|
||||
* @throws GuacamoleException If a problem is encountered while listing users.
|
||||
* Gets a list of users in the system, filtering the returned list by the
|
||||
* given permission, if specified.
|
||||
*
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param permission
|
||||
* If specified, limit the returned list to only those users for whom
|
||||
* the current user has the given permission. Otherwise, all visible
|
||||
* users are returned.
|
||||
*
|
||||
* @return
|
||||
* A list of all visible users. If a permission was specified, this
|
||||
* list will contain only those users for whom the current user has
|
||||
* that permission.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error is encountered while retrieving users.
|
||||
*/
|
||||
@GET
|
||||
@AuthProviderRESTExposure
|
||||
public List<APIUser> getUsers(@QueryParam("token") String authToken) throws GuacamoleException {
|
||||
public List<APIUser> getUsers(@QueryParam("token") String authToken,
|
||||
@QueryParam("permission") UserPermission.Type permission)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
User self = userContext.self();
|
||||
|
||||
// Get the directory
|
||||
Directory<String, User> userDirectory = userContext.getUserDirectory();
|
||||
|
||||
// Convert and return the user directory listing
|
||||
return userService.convertUserList(userDirectory);
|
||||
List<APIUser> users = new ArrayList<APIUser>();
|
||||
|
||||
// Add all users matching the given permission filter
|
||||
for (String username : userDirectory.getIdentifiers()) {
|
||||
|
||||
if (permission == null || self.hasPermission(new UserPermission(permission, username)))
|
||||
users.add(new APIUser(userDirectory.get(username)));
|
||||
|
||||
}
|
||||
|
||||
// Return the user directory listing
|
||||
return users;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an individual user.
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param userID The ID of the user to retrieve.
|
||||
* @return user The user.
|
||||
* @throws GuacamoleException If a problem is encountered while retrieving the user.
|
||||
* Retrieves an individual user.
|
||||
*
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user to retrieve.
|
||||
*
|
||||
* @return user
|
||||
* The user having the given username.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving the user.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{userID}")
|
||||
@Path("/{username}")
|
||||
@AuthProviderRESTExposure
|
||||
public APIUser getUser(@QueryParam("token") String authToken, @PathParam("userID") String userID)
|
||||
public APIUser getUser(@QueryParam("token") String authToken, @PathParam("username") String username)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
@@ -113,9 +181,9 @@ public class UserRESTService {
|
||||
Directory<String, User> userDirectory = userContext.getUserDirectory();
|
||||
|
||||
// Get the user
|
||||
User user = userDirectory.get(userID);
|
||||
User user = userDirectory.get(username);
|
||||
if (user == null)
|
||||
throw new HTTPException(Response.Status.NOT_FOUND, "User not found with the provided userID.");
|
||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
|
||||
|
||||
// Return the user
|
||||
return new APIUser(user);
|
||||
@@ -154,16 +222,25 @@ public class UserRESTService {
|
||||
|
||||
/**
|
||||
* Updates an individual existing user.
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param userID The unique identifier of the user to update.
|
||||
* @param user The updated user.
|
||||
* @throws GuacamoleException If a problem is encountered while updating the user.
|
||||
*
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user to update.
|
||||
*
|
||||
* @param user
|
||||
* The data to update the user with.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while updating the user.
|
||||
*/
|
||||
@POST
|
||||
@Path("/{userID}")
|
||||
@PUT
|
||||
@Path("/{username}")
|
||||
@AuthProviderRESTExposure
|
||||
public void updateUser(@QueryParam("token") String authToken, @PathParam("userID") String userID, APIUser user)
|
||||
public void updateUser(@QueryParam("token") String authToken,
|
||||
@PathParam("username") String username, APIUser user)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
@@ -171,37 +248,43 @@ public class UserRESTService {
|
||||
// Get the directory
|
||||
Directory<String, User> userDirectory = userContext.getUserDirectory();
|
||||
|
||||
if (!user.getUsername().equals(userID))
|
||||
throw new HTTPException(Response.Status.BAD_REQUEST, "Username does not match provided userID.");
|
||||
// Validate data and path are sane
|
||||
if (!user.getUsername().equals(username))
|
||||
throw new HTTPException(Response.Status.BAD_REQUEST,
|
||||
"Username in path does not match username provided JSON data.");
|
||||
|
||||
// Get the user
|
||||
User existingUser = userDirectory.get(userID);
|
||||
User existingUser = userDirectory.get(username);
|
||||
if (existingUser == null)
|
||||
throw new HTTPException(Response.Status.NOT_FOUND, "User not found with the provided userID.");
|
||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
|
||||
|
||||
// Do not update the user password if no password was provided
|
||||
if (user.getPassword() != null) {
|
||||
/*
|
||||
* Update the user with the permission set from the existing user
|
||||
* since the user REST endpoints do not expose permissions.
|
||||
*/
|
||||
if (user.getPassword() != null)
|
||||
existingUser.setPassword(user.getPassword());
|
||||
userDirectory.update(existingUser);
|
||||
}
|
||||
|
||||
// Update the user
|
||||
userDirectory.update(existingUser);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an individual existing user.
|
||||
* @param authToken The authentication token that is used to authenticate
|
||||
* the user performing the operation.
|
||||
* @param userID The unique identifier of the user to delete.
|
||||
* @throws GuacamoleException If a problem is encountered while deleting the user.
|
||||
*
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user to delete.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while deleting the user.
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{userID}")
|
||||
@Path("/{username}")
|
||||
@AuthProviderRESTExposure
|
||||
public void deleteUser(@QueryParam("token") String authToken, @PathParam("userID") String userID)
|
||||
public void deleteUser(@QueryParam("token") String authToken,
|
||||
@PathParam("username") String username)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
@@ -210,12 +293,168 @@ public class UserRESTService {
|
||||
Directory<String, User> userDirectory = userContext.getUserDirectory();
|
||||
|
||||
// Get the user
|
||||
User existingUser = userDirectory.get(userID);
|
||||
User existingUser = userDirectory.get(username);
|
||||
if (existingUser == null)
|
||||
throw new HTTPException(Response.Status.NOT_FOUND, "User not found with the provided userID.");
|
||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
|
||||
|
||||
// Delete the user
|
||||
userDirectory.remove(userID);
|
||||
userDirectory.remove(username);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of permissions for the user with the given username.
|
||||
*
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user to retrieve permissions for.
|
||||
*
|
||||
* @return
|
||||
* A list of all permissions granted to the specified user.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If an error occurs while retrieving permissions.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{username}/permissions")
|
||||
@AuthProviderRESTExposure
|
||||
public APIPermissionSet getPermissions(@QueryParam("token") String authToken,
|
||||
@PathParam("username") String username)
|
||||
throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the user
|
||||
User user = userContext.getUserDirectory().get(username);
|
||||
if (user == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
|
||||
|
||||
return new APIPermissionSet(user.getPermissions());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a given list of permission patches. Each patch specifies either
|
||||
* an "add" or a "remove" operation for a permission type, represented by
|
||||
* a string. Valid permission types depend on the path of each patch
|
||||
* operation, as the path dictates the permission being modified, such as
|
||||
* "/connectionPermissions/42" or "/systemPermissions".
|
||||
*
|
||||
* @param authToken
|
||||
* The authentication token that is used to authenticate the user
|
||||
* performing the operation.
|
||||
*
|
||||
* @param username
|
||||
* The username of the user to modify the permissions of.
|
||||
*
|
||||
* @param patches
|
||||
* The permission patches to apply for this request.
|
||||
*
|
||||
* @throws GuacamoleException
|
||||
* If a problem is encountered while modifying permissions.
|
||||
*/
|
||||
@PATCH
|
||||
@Path("/{username}/permissions")
|
||||
@AuthProviderRESTExposure
|
||||
public void patchPermissions(@QueryParam("token") String authToken,
|
||||
@PathParam("username") String username,
|
||||
List<APIPatch<String>> patches) throws GuacamoleException {
|
||||
|
||||
UserContext userContext = authenticationService.getUserContext(authToken);
|
||||
|
||||
// Get the user directory
|
||||
Directory<String, User> userDirectory = userContext.getUserDirectory();
|
||||
|
||||
// Get the user
|
||||
User user = userContext.getUserDirectory().get(username);
|
||||
if (user == null)
|
||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
|
||||
|
||||
// Apply all patch operations individually
|
||||
for (APIPatch<String> patch : patches) {
|
||||
|
||||
Permission permission;
|
||||
|
||||
String path = patch.getPath();
|
||||
|
||||
// Create connection permission if path has connection prefix
|
||||
if (path.startsWith(CONNECTION_PERMISSION_PATCH_PATH_PREFIX)) {
|
||||
|
||||
// Get identifier and type from patch operation
|
||||
String identifier = path.substring(CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length());
|
||||
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
|
||||
|
||||
// Create corresponding permission
|
||||
permission = new ConnectionPermission(type, identifier);
|
||||
|
||||
}
|
||||
|
||||
// Create connection group permission if path has connection group prefix
|
||||
else if (path.startsWith(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX)) {
|
||||
|
||||
// Get identifier and type from patch operation
|
||||
String identifier = path.substring(CONNECTION_GROUP_PERMISSION_PATCH_PATH_PREFIX.length());
|
||||
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
|
||||
|
||||
// Create corresponding permission
|
||||
permission = new ConnectionGroupPermission(type, identifier);
|
||||
|
||||
}
|
||||
|
||||
// Create user permission if path has user prefix
|
||||
else if (path.startsWith(USER_PERMISSION_PATCH_PATH_PREFIX)) {
|
||||
|
||||
// Get identifier and type from patch operation
|
||||
String identifier = path.substring(USER_PERMISSION_PATCH_PATH_PREFIX.length());
|
||||
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
|
||||
|
||||
// Create corresponding permission
|
||||
permission = new UserPermission(type, identifier);
|
||||
|
||||
}
|
||||
|
||||
// Create system permission if path is system path
|
||||
else if (path.startsWith(SYSTEM_PERMISSION_PATCH_PATH)) {
|
||||
|
||||
// Get identifier and type from patch operation
|
||||
SystemPermission.Type type = SystemPermission.Type.valueOf(patch.getValue());
|
||||
|
||||
// Create corresponding permission
|
||||
permission = new SystemPermission(type);
|
||||
|
||||
}
|
||||
|
||||
// Otherwise, the path is not supported
|
||||
else
|
||||
throw new HTTPException(Status.BAD_REQUEST, "Unsupported patch path: \"" + path + "\"");
|
||||
|
||||
// Add or remove permission based on operation
|
||||
switch (patch.getOp()) {
|
||||
|
||||
// Add permission
|
||||
case add:
|
||||
user.addPermission(permission);
|
||||
break;
|
||||
|
||||
// Remove permission
|
||||
case remove:
|
||||
user.removePermission(permission);
|
||||
break;
|
||||
|
||||
// Unsupported patch operation
|
||||
default:
|
||||
throw new HTTPException(Status.BAD_REQUEST,
|
||||
"Unsupported patch operation: \"" + patch.getOp() + "\"");
|
||||
|
||||
}
|
||||
|
||||
} // end for each patch operation
|
||||
|
||||
// Save the permission changes
|
||||
userDirectory.update(user);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -28,20 +28,33 @@ angular.module('auth').factory('authenticationService', ['$http', '$cookieStore'
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* The unique identifier of the local cookie which stores the user's
|
||||
* current authentication token and user ID.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
var AUTH_COOKIE_ID = "GUAC_AUTH";
|
||||
|
||||
/**
|
||||
* Makes a request to authenticate a user using the token REST API endpoint,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
* returning a promise that succeeds only if the login operation was
|
||||
* successful. The resulting authentication data can be retrieved later
|
||||
* via getCurrentToken() or getCurrentUserID().
|
||||
*
|
||||
* @param {String} username The username to log in with.
|
||||
* @param {String} password The password to log in with.
|
||||
* @returns {Promise} A promise for the HTTP call.
|
||||
* @param {String} username
|
||||
* The username to log in with.
|
||||
*
|
||||
* @param {String} password
|
||||
* The password to log in with.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise which succeeds only if the login operation was successful.
|
||||
*/
|
||||
service.login = function login(username, password) {
|
||||
return $http({
|
||||
method: 'POST',
|
||||
url: 'api/token',
|
||||
url: 'api/tokens',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
@@ -59,14 +72,17 @@ angular.module('auth').factory('authenticationService', ['$http', '$cookieStore'
|
||||
|
||||
/**
|
||||
* Makes a request to logout a user using the login REST API endpoint,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
* returning a promise succeeds only if the logout operation was
|
||||
* successful.
|
||||
*
|
||||
* @returns {Promise} A promise for the HTTP call.
|
||||
* @returns {Promise}
|
||||
* A promise which succeeds only if the logout operation was
|
||||
* successful.
|
||||
*/
|
||||
service.logout = function logout() {
|
||||
return $http({
|
||||
method: 'DELETE',
|
||||
url: 'api/token/' + encodeURIComponent(service.getCurrentToken())
|
||||
url: 'api/tokens/' + encodeURIComponent(service.getCurrentToken())
|
||||
});
|
||||
};
|
||||
|
||||
|
@@ -23,4 +23,4 @@
|
||||
/**
|
||||
* The module for code used to connect to a connection or balancing group.
|
||||
*/
|
||||
angular.module('client', ['auth', 'history']);
|
||||
angular.module('client', ['auth', 'history', 'rest']);
|
||||
|
@@ -132,10 +132,10 @@ angular.module('home').controller('clientController', ['$scope', '$routeParams',
|
||||
remaining: 15
|
||||
};
|
||||
|
||||
// Get DAO for reading connections and groups
|
||||
var connectionGroupDAO = $injector.get('connectionGroupDAO');
|
||||
var connectionService = $injector.get('connectionService');
|
||||
var ClientProperties = $injector.get('ClientProperties');
|
||||
// Get services for reading connections and groups
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
var connectionService = $injector.get('connectionService');
|
||||
var ClientProperties = $injector.get('ClientProperties');
|
||||
|
||||
// Client settings and state
|
||||
$scope.clientProperties = new ClientProperties();
|
||||
@@ -176,7 +176,7 @@ angular.module('home').controller('clientController', ['$scope', '$routeParams',
|
||||
|
||||
// Connection group
|
||||
case 'g':
|
||||
connectionGroupDAO.getConnectionGroup($routeParams.id).success(function (group) {
|
||||
connectionGroupService.getConnectionGroup($routeParams.id).success(function (group) {
|
||||
$scope.connectionName = $scope.page.title = group.name;
|
||||
});
|
||||
break;
|
||||
|
@@ -315,15 +315,18 @@ angular.module('client').directive('guacClient', [function guacClient() {
|
||||
* CONNECT / RECONNECT
|
||||
*/
|
||||
|
||||
// Connect to given ID whenever ID changes
|
||||
$scope.$watch('id', function(id, previousID) {
|
||||
|
||||
// If a client is already attached, ensure it is disconnected
|
||||
if (client)
|
||||
client.disconnect();
|
||||
/**
|
||||
* Store the thumbnail of the currently connected client within
|
||||
* the connection history under the given ID. If the client is not
|
||||
* connected, or if no ID is given, this function has no effect.
|
||||
*
|
||||
* @param {String} id
|
||||
* The ID of the history entry to update.
|
||||
*/
|
||||
var updateHistoryEntry = function updateHistoryEntry(id) {
|
||||
|
||||
// Update stored thumbnail of previous connection
|
||||
if (previousID && display && display.getWidth() > 0 && display.getHeight() > 0) {
|
||||
if (id && display && display.getWidth() > 0 && display.getHeight() > 0) {
|
||||
|
||||
// Get screenshot
|
||||
var canvas = display.flatten();
|
||||
@@ -343,10 +346,22 @@ angular.module('client').directive('guacClient', [function guacClient() {
|
||||
0, 0, thumbnail.width, thumbnail.height
|
||||
);
|
||||
|
||||
guacHistory.updateThumbnail(previousID, thumbnail.toDataURL("image/png"));
|
||||
guacHistory.updateThumbnail(id, thumbnail.toDataURL("image/png"));
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Connect to given ID whenever ID changes
|
||||
$scope.$watch('id', function(id, previousID) {
|
||||
|
||||
// If a client is already attached, ensure it is disconnected
|
||||
if (client)
|
||||
client.disconnect();
|
||||
|
||||
// Update stored thumbnail of previous connection
|
||||
updateHistoryEntry(previousID);
|
||||
|
||||
// Only proceed if a new client is attached
|
||||
if (!id)
|
||||
return;
|
||||
@@ -385,6 +400,14 @@ angular.module('client').directive('guacClient', [function guacClient() {
|
||||
|
||||
});
|
||||
|
||||
// Clean up when client directive is destroyed
|
||||
$scope.$on('$destroy', function destroyClient() {
|
||||
|
||||
// Update stored thumbnail of current connection
|
||||
updateHistoryEntry($scope.id);
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
* MOUSE EMULATION
|
||||
*/
|
||||
|
@@ -33,10 +33,7 @@
|
||||
<div id="text-input"><div id="text-input-field"><div id="sent-history"></div><textarea rows="1" id="target"></textarea></div><div id="text-input-buttons"><button class="key" data-keysym="0xFFE3" data-sticky="true">{{'client.ctrl' | translate}}</button><button class="key" data-keysym="0xFFE9" data-sticky="true">{{'client.alt' | translate}}</button><button class="key" data-keysym="0xFF1B">{{'client.esc' | translate}}</button><button class="key" data-keysym="0xFF09">{{'client.tab' | translate}}</button></div></div>
|
||||
|
||||
<!-- Dimensional clone of viewport -->
|
||||
<div id="viewportClone"/>
|
||||
|
||||
<!-- Notification area -->
|
||||
<div id="notificationArea"/>
|
||||
<div id="viewportClone"></div>
|
||||
|
||||
<!-- Menu -->
|
||||
<div ng-class="{open: menuShown}" id="menu">
|
||||
@@ -108,8 +105,8 @@
|
||||
|
||||
<!-- Images which should be preloaded -->
|
||||
<div id="preload">
|
||||
<img src="images/action-icons/guac-close.png"/>
|
||||
<img src="images/progress.png"/>
|
||||
<img src="images/action-icons/guac-close.png" alt=""/>
|
||||
<img src="images/progress.png" alt=""/>
|
||||
</div>
|
||||
|
||||
<ng-include src="app/client/template/clientError.html"/>
|
||||
|
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service for operating on connections via the REST API.
|
||||
*/
|
||||
angular.module('connection').factory('connectionService', ['$http', 'authenticationService',
|
||||
function connectionService($http, authenticationService) {
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get a single connection, returning a
|
||||
* promise that provides the corresponding @link{Connection} if successful.
|
||||
*
|
||||
* @param {String} id The ID of the connection.
|
||||
* @returns {Promise.<Connection>}
|
||||
* A promise which will resolve with a @link{Connection} upon success.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* connectionService.getConnection('myConnection').success(function(connection) {
|
||||
* // Do something with the connection
|
||||
* });
|
||||
*/
|
||||
service.getConnection = function getConnection(id) {
|
||||
return $http.get("api/connection/" + id + "?token=" + authenticationService.getCurrentToken());
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the list of connections,
|
||||
* returning a promise that can be used for processing the results of the
|
||||
* call.
|
||||
*
|
||||
* @param {string} parentID The parent ID for the connection.
|
||||
* If not passed in, it will query a list of the
|
||||
* connections in the root group.
|
||||
*
|
||||
* @returns {Promise.<Connection[]>}
|
||||
* A promise which will resolve with an array of @link{Connection}
|
||||
* objects upon success.
|
||||
*/
|
||||
service.getConnections = function getConnections(parentID) {
|
||||
|
||||
var parentIDParam = "";
|
||||
if(parentID !== undefined)
|
||||
parentIDParam = "&parentID=" + parentID;
|
||||
|
||||
return $http.get("api/connection?token=" + authenticationService.getCurrentToken() + parentIDParam);
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to save a connection, returning a
|
||||
* promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {Connection} connection The connection to update
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* save operation is successful.
|
||||
*/
|
||||
service.saveConnection = function saveConnection(connection) {
|
||||
|
||||
/*
|
||||
* FIXME: This should not be necessary. Perhaps the need for this is a
|
||||
* sign that history should be queried separately, and not reside as
|
||||
* part of the connection object?
|
||||
*/
|
||||
// Do not try to save the connection history records
|
||||
var connectionToSave = angular.copy(connection);
|
||||
delete connectionToSave.history;
|
||||
|
||||
// This is a new connection
|
||||
if(!connectionToSave.identifier) {
|
||||
return $http.post("api/connection/?token=" + authenticationService.getCurrentToken(), connectionToSave).success(
|
||||
function setConnectionID(connectionID){
|
||||
// Set the identifier on the new connection
|
||||
connection.identifier = connectionID; // FIXME: Functions with side effects = bad
|
||||
return connectionID; // FIXME: Why? Where does this value go?
|
||||
});
|
||||
} else {
|
||||
return $http.post(
|
||||
"api/connection/" + connectionToSave.identifier +
|
||||
"?token=" + authenticationService.getCurrentToken(),
|
||||
connectionToSave);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* FIXME: Why is this different from save?
|
||||
*
|
||||
* Makes a request to the REST API to move a connection to a different
|
||||
* group, returning a promise that can be used for processing the results
|
||||
* of the call.
|
||||
*
|
||||
* @param {Connection} connection The connection to move.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* move operation is successful.
|
||||
*/
|
||||
service.moveConnection = function moveConnection(connection) {
|
||||
|
||||
return $http.put(
|
||||
"api/connection/" + connection.identifier +
|
||||
"?token=" + authenticationService.getCurrentToken() +
|
||||
"&parentID=" + connection.parentIdentifier,
|
||||
connection);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to delete a connection,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {Connection} connection The connection to delete
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* delete operation is successful.
|
||||
*/
|
||||
service.deleteConnection = function deleteConnection(connection) {
|
||||
return $http['delete'](
|
||||
"api/connection/" + connection.identifier +
|
||||
"?token=" + authenticationService.getCurrentToken());
|
||||
};
|
||||
|
||||
return service;
|
||||
}]);
|
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The DAO for connection group operations agains the REST API.
|
||||
*/
|
||||
angular.module('connectionGroup').factory('connectionGroupDAO', ['$http', 'authenticationService',
|
||||
function connectionGrouDAO($http, authenticationService) {
|
||||
|
||||
/**
|
||||
* The ID of the root connection group.
|
||||
*/
|
||||
var ROOT_CONNECTION_GROUP_ID = "ROOT";
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the list of connection groups,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {string} parentID The parent ID for the connection group.
|
||||
* If not passed in, it will query a list of the
|
||||
* connection groups in the root group.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.getConnectionGroups = function getConnectionGroups(parentID) {
|
||||
|
||||
var parentIDParam = "";
|
||||
if(parentID !== undefined)
|
||||
parentIDParam = "&parentID=" + parentID;
|
||||
|
||||
return $http.get("api/connectionGroup?token=" + authenticationService.getCurrentToken() + parentIDParam);
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get an individual connection group,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {string} connectionGroupID The ID for the connection group.
|
||||
* If not passed in, it will query the
|
||||
* root connection group.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.getConnectionGroup = function getConnectionGroup(connectionGroupID) {
|
||||
|
||||
// Use the root connection group ID if no ID is passed in
|
||||
connectionGroupID = connectionGroupID || ROOT_CONNECTION_GROUP_ID;
|
||||
|
||||
return $http.get("api/connectionGroup/" + connectionGroupID + "?token=" + authenticationService.getCurrentToken());
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to save a connection group,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {object} connectionGroup The connection group to update
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.saveConnectionGroup = function saveConnectionGroup(connectionGroup) {
|
||||
// This is a new connection group
|
||||
if(!connectionGroup.identifier) {
|
||||
return $http.post("api/connectionGroup/?token=" + authenticationService.getCurrentToken(), connectionGroup).success(
|
||||
function setConnectionGroupID(connectionGroupID){
|
||||
// Set the identifier on the new connection
|
||||
connectionGroup.identifier = connectionGroupID;
|
||||
return connectionGroupID;
|
||||
});
|
||||
} else {
|
||||
return $http.post(
|
||||
"api/connectionGroup/" + connectionGroup.identifier +
|
||||
"?token=" + authenticationService.getCurrentToken(),
|
||||
connectionGroup);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to move a connection group to a different group,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {object} connectionGroup The connection group to move.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.moveConnectionGroup = function moveConnectionGroup(connectionGroup) {
|
||||
|
||||
return $http.put(
|
||||
"api/connectionGroup/" + connectionGroup.identifier +
|
||||
"?token=" + authenticationService.getCurrentToken() +
|
||||
"&parentID=" + connectionGroup.parentIdentifier,
|
||||
connectionGroup);
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to delete a connection group,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {object} connectionGroup The connection group to delete
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.deleteConnectionGroup = function deleteConnectionGroup(connectionGroup) {
|
||||
return $http['delete'](
|
||||
"api/connectionGroup/" + connectionGroup.identifier +
|
||||
"?token=" + authenticationService.getCurrentToken());
|
||||
};
|
||||
|
||||
return service;
|
||||
}]);
|
@@ -1,231 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A service for performing useful connection group related functionaltiy.
|
||||
*/
|
||||
angular.module('connectionGroup').factory('connectionGroupService', ['$injector', function connectionGroupService($injector) {
|
||||
|
||||
var connectionGroupDAO = $injector.get('connectionGroupDAO');
|
||||
var connectionService = $injector.get('connectionService');
|
||||
var permissionCheckService = $injector.get('permissionCheckService');
|
||||
var $q = $injector.get('$q');
|
||||
var displayObjectPreparationService = $injector.get('displayObjectPreparationService');
|
||||
|
||||
var service = {};
|
||||
|
||||
// Add all groups from this group to the parent group child list
|
||||
function addToParent(connectionGroup, parentGroup, context, includeConnections) {
|
||||
|
||||
// Include connections by default
|
||||
if(typeof includeConnections === 'undefined')
|
||||
includeConnections = true;
|
||||
|
||||
parentGroup.children.push(connectionGroup);
|
||||
|
||||
// Prepare this group for display
|
||||
displayObjectPreparationService.prepareConnectionGroup(connectionGroup);
|
||||
|
||||
if(includeConnections) {
|
||||
// Get all connections in the group and add them under this connection group
|
||||
context.openRequest();
|
||||
connectionService.getConnections(connectionGroup.identifier).success(function fetchConnections(connections) {
|
||||
for(var i = 0; i < connections.length; i++) {
|
||||
connections[i].isConnection = true;
|
||||
connectionGroup.children.push(connections[i]);
|
||||
}
|
||||
context.closeRequest();
|
||||
});
|
||||
}
|
||||
|
||||
// Get all connection groups in the group and repeat
|
||||
context.openRequest();
|
||||
connectionGroupDAO.getConnectionGroups(connectionGroup.identifier).success(function fetchConnectionGroups(connectionGroups) {
|
||||
for(var i = 0; i < connectionGroups.length; i++) {
|
||||
addToParent(connectionGroups[i], connectionGroup, context, includeConnections);
|
||||
}
|
||||
context.closeRequest();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries all connections and connection groups under the connection group
|
||||
* with the provided parent ID, and returns them in a heirarchical structure
|
||||
* with convinient display properties set on the objects.
|
||||
*
|
||||
* @param {array} items The root list of connections and groups. Should be an
|
||||
* initally empty array that will get filled in as the
|
||||
* connections and groups are loaded.
|
||||
*
|
||||
* @param {string} parentID The parent ID for the connection group.
|
||||
* If not passed in, it will begin with
|
||||
* the root connection group.
|
||||
*
|
||||
* @param {boolean} includeConnections Whether or not to include connections
|
||||
* in the structure. Defaults to true.
|
||||
*
|
||||
* @param {boolean} includeRoot Whether or not to include the root connection group
|
||||
* in the structure. Defaults to false.
|
||||
*
|
||||
* @return {promise} A promise that will be fulfilled when all connections
|
||||
* and groups have been loaded.
|
||||
*/
|
||||
service.getAllGroupsAndConnections = function getAllGroupsAndConnections(items, parentID, includeConnections, includeRoot) {
|
||||
|
||||
// Include connections by default
|
||||
if(typeof includeConnections === 'undefined')
|
||||
includeConnections = true;
|
||||
|
||||
var context = {
|
||||
// The number of requets to the server currently open
|
||||
openRequests : 0,
|
||||
|
||||
// Create the promise
|
||||
finishedFetching : $q.defer(),
|
||||
|
||||
// Notify the caller that the promise has been completed
|
||||
complete : function complete() {
|
||||
this.finishedFetching.resolve(items);
|
||||
},
|
||||
|
||||
/**
|
||||
* Indicate that a request has been started.
|
||||
*/
|
||||
openRequest : function openRequest() {
|
||||
this.openRequests++;
|
||||
},
|
||||
|
||||
/**
|
||||
* Indicate that a request has been completed. If this was the last
|
||||
* open request, fulfill the promise.
|
||||
*/
|
||||
closeRequest : function closeRequest() {
|
||||
if(--this.openRequests === 0)
|
||||
this.complete();
|
||||
}
|
||||
};
|
||||
|
||||
// Include the root only if it was asked for
|
||||
if(includeRoot) {
|
||||
context.openRequest();
|
||||
connectionGroupDAO.getConnectionGroup(parentID).success(function setRootGroup (rootGroup) {
|
||||
items.push(rootGroup);
|
||||
rootGroup.children = [];
|
||||
getChildrenOfRootGroup(rootGroup.children);
|
||||
context.closeRequest();
|
||||
});
|
||||
} else {
|
||||
getChildrenOfRootGroup(items);
|
||||
}
|
||||
|
||||
// Get the children of the root group
|
||||
function getChildrenOfRootGroup(children) {
|
||||
context.openRequest();
|
||||
connectionGroupDAO.getConnectionGroups(parentID).success(function fetchRootConnectionGroups(connectionGroups) {
|
||||
for(var i = 0; i < connectionGroups.length; i++) {
|
||||
addToParent(connectionGroups[i], {children: children}, context, includeConnections);
|
||||
}
|
||||
|
||||
if(includeConnections) {
|
||||
// Get all connections in the root group and add them under this connection group
|
||||
context.openRequest();
|
||||
connectionService.getConnections().success(function fetchRootConnections(connections) {
|
||||
for(var i = 0; i < connections.length; i++) {
|
||||
|
||||
// Prepare this connection for display
|
||||
displayObjectPreparationService.prepareConnection(connections[i]);
|
||||
|
||||
children.push(connections[i]);
|
||||
}
|
||||
context.closeRequest();
|
||||
});
|
||||
}
|
||||
|
||||
context.closeRequest();
|
||||
});
|
||||
}
|
||||
|
||||
// Return the promise
|
||||
return context.finishedFetching.promise;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Filters the list of connections and groups using the provided permissions.
|
||||
*
|
||||
* @param {array} items The heirarchical list of groups and connections.
|
||||
*
|
||||
* @param {object} permissionList The list of permissions to use
|
||||
* when filtering.
|
||||
*
|
||||
* @param {object} permissionCriteria A map of object type to permission type(s)
|
||||
* required for that object type.
|
||||
*
|
||||
* @return {array} The filtered list.
|
||||
*/
|
||||
service.filterConnectionsAndGroupByPermission = function filterConnectionsAndGroupByPermission(items, permissionList, permissionCriteria) {
|
||||
var requiredConnectionPermission = permissionCriteria.CONNECTION;
|
||||
var requiredConnectionGroupPermission = permissionCriteria.CONNECTION_GROUP;
|
||||
|
||||
for(var i = 0; i < items.length; i++) {
|
||||
var item = items[i];
|
||||
|
||||
if(item.isConnection && requiredConnectionPermission) {
|
||||
|
||||
/*
|
||||
* If item is a connection and a permission is required for this
|
||||
* item, check now to see if the permission exists. If not,
|
||||
* remove the item.
|
||||
*/
|
||||
if(!permissionCheckService.checkPermission(permissionList,
|
||||
"CONNECTION", item.identifier, requiredConnectionPermission)) {
|
||||
items.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
/*
|
||||
* If item is a group and a permission is required for this
|
||||
* item, check now to see if the permission exists. If not,
|
||||
* remove the item.
|
||||
*/
|
||||
if(requiredConnectionGroupPermission) {
|
||||
if(!permissionCheckService.checkPermission(permissionList,
|
||||
"CONNECTION_GROUP", item.identifier, requiredConnectionGroupPermission)) {
|
||||
items.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Filter the children of this connection group as well
|
||||
if(item.children && item.children.length)
|
||||
service.filterConnectionsAndGroupByPermission(items.children);
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
|
||||
};
|
||||
|
||||
return service;
|
||||
}]);
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A directive which displays the contents of a connection group.
|
||||
*/
|
||||
angular.module('groupList').directive('guacGroupList', [function guacGroupList() {
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
scope: {
|
||||
|
||||
/**
|
||||
* The connection group to display.
|
||||
*
|
||||
* @type ConnectionGroup|Object
|
||||
*/
|
||||
connectionGroup : '='
|
||||
|
||||
},
|
||||
|
||||
templateUrl: 'app/groupList/templates/guacGroupList.html',
|
||||
controller: ['$scope', '$injector', '$interval', function guacGroupListController($scope, $injector, $interval) {
|
||||
|
||||
// Get required types
|
||||
var GroupListItem = $injector.get('GroupListItem');
|
||||
|
||||
// Set contents whenever the connection group is assigned or changed
|
||||
$scope.$watch("connectionGroup", function setContents(connectionGroup) {
|
||||
|
||||
if (connectionGroup)
|
||||
$scope.rootItem = GroupListItem.fromConnectionGroup(connectionGroup);
|
||||
else
|
||||
$scope.rootItem = null;
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* Toggle the open/closed status of a group list item.
|
||||
*
|
||||
* @param {GroupListItem} groupListItem
|
||||
* The list item to expand, which should represent a
|
||||
* connection group.
|
||||
*/
|
||||
$scope.toggleExpanded = function toggleExpanded(groupListItem) {
|
||||
groupListItem.expanded = !groupListItem.expanded;
|
||||
};
|
||||
|
||||
}]
|
||||
|
||||
};
|
||||
}]);
|
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* The module for code relating to connection groups.
|
||||
* Module for displaying the contents of a connection group, allowing the user
|
||||
* to select individual connections or groups.
|
||||
*/
|
||||
angular.module('connectionGroup', ['auth', 'util', 'connection']);
|
||||
angular.module('groupList', ['rest']);
|
@@ -19,8 +19,3 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A module for code relating to users.
|
||||
*/
|
||||
angular.module('user', ['auth']);
|
@@ -0,0 +1,71 @@
|
||||
<div class="group-list">
|
||||
<!--
|
||||
Copyright (C) 2014 Glyptodon LLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<script type="text/ng-template" id="nestedGroup.html">
|
||||
|
||||
<!-- Connection -->
|
||||
<div class="connection" ng-show="item.isConnection">
|
||||
<a ng-href="#/client/c/{{item.identifier}}">
|
||||
<div class="caption">
|
||||
|
||||
<!-- Connection icon -->
|
||||
<div class="protocol">
|
||||
<div class="icon type" ng-class="item.protocol"></div>
|
||||
</div>
|
||||
|
||||
<!-- Connection name -->
|
||||
<span class="name">{{item.name}}</span>
|
||||
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Connection group -->
|
||||
<div class="group" ng-show="item.isConnectionGroup">
|
||||
|
||||
<div class="caption">
|
||||
|
||||
<!-- Connection group icon -->
|
||||
<div class="icon group type" ng-click="toggleExpanded(item)"
|
||||
ng-class="{expanded: item.isExpanded, empty: !item.children.length, balancer: item.isBalancing}"></div>
|
||||
|
||||
<!-- Connection group name -->
|
||||
<span class="name">
|
||||
<a ng-show="item.isBalancing" ng-href="#/client/g/{{item.identifier}}">{{item.name}}</a>
|
||||
<span ng-show="!item.isBalancing">{{item.name}}</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Children of this group -->
|
||||
<div class="children" ng-show="item.isExpanded">
|
||||
<div class="list-item" ng-repeat="item in item.children | orderBy : 'name'" ng-include="'nestedGroup.html'">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</script>
|
||||
|
||||
<div class="list-item" ng-repeat="item in rootItem.children | orderBy : 'name'" ng-include="'nestedGroup.html'"></div>
|
||||
|
||||
</div>
|
181
guacamole/src/main/webapp/app/groupList/types/GroupListItem.js
Normal file
181
guacamole/src/main/webapp/app/groupList/types/GroupListItem.js
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides the GroupListItem class definition.
|
||||
*/
|
||||
angular.module('groupList').factory('GroupListItem', ['ConnectionGroup', function defineGroupListItem(ConnectionGroup) {
|
||||
|
||||
/**
|
||||
* Creates a new GroupListItem, initializing the properties of that
|
||||
* GroupListItem with the corresponding properties of the given template.
|
||||
*
|
||||
* @constructor
|
||||
* @param {GroupListItem|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* GroupListItem.
|
||||
*/
|
||||
var GroupListItem = function GroupListItem(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The unique identifier associated with the connection or connection
|
||||
* group this item represents.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.identifier = template.identifier;
|
||||
|
||||
/**
|
||||
* The human-readable display name of this item.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.name = template.name;
|
||||
|
||||
/**
|
||||
* The unique identifier of the protocol, if this item represents a
|
||||
* connection. If this item does not represent a connection, this
|
||||
* property is not applicable.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.protocol = template.protocol;
|
||||
|
||||
/**
|
||||
* All children items of this item. If this item contains no children,
|
||||
* this will be an empty array.
|
||||
*
|
||||
* @type GroupListItem[]
|
||||
*/
|
||||
this.children = template.children || [];
|
||||
|
||||
/**
|
||||
* Whether this item represents a connection. If this item represents
|
||||
* a connection group, this MUST be false.
|
||||
*
|
||||
* @type Boolean
|
||||
*/
|
||||
this.isConnection = template.isConnection;
|
||||
|
||||
/**
|
||||
* Whether this item represents a connection group. If this item
|
||||
* represents a connection, this MUST be false.
|
||||
*
|
||||
* @type Boolean
|
||||
*/
|
||||
this.isConnectionGroup = template.isConnectionGroup;
|
||||
|
||||
/**
|
||||
* Whether this item represents a balancing connection group.
|
||||
*
|
||||
* @type Boolean
|
||||
*/
|
||||
this.isBalancing = template.isBalancing;
|
||||
|
||||
/**
|
||||
* Whether the children items should be displayed.
|
||||
*
|
||||
* @type Boolean
|
||||
*/
|
||||
this.isExpanded = template.isExpanded;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new GroupListItem using the contents of the given connection.
|
||||
*
|
||||
* @param {ConnectionGroup} connection
|
||||
* The connection whose contents should be represented by the new
|
||||
* GroupListItem.
|
||||
*
|
||||
* @returns {GroupListItem}
|
||||
* A new GroupListItem which represents the given connection.
|
||||
*/
|
||||
GroupListItem.fromConnection = function fromConnection(connection) {
|
||||
|
||||
// Return item representing the given connection
|
||||
return new GroupListItem({
|
||||
|
||||
// Identifying information
|
||||
name : connection.name,
|
||||
identifier : connection.identifier,
|
||||
protocol : connection.protocol,
|
||||
|
||||
// Type information
|
||||
isConnection : true,
|
||||
isConnectionGroup : false
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new GroupListItem using the contents and descendants of the
|
||||
* given connection group.
|
||||
*
|
||||
* @param {ConnectionGroup} connectionGroup
|
||||
* The connection group whose contents and descendants should be
|
||||
* represented by the new GroupListItem and its descendants.
|
||||
*
|
||||
* @returns {GroupListItem}
|
||||
* A new GroupListItem which represents the given connection group,
|
||||
* including all descendants.
|
||||
*/
|
||||
GroupListItem.fromConnectionGroup = function fromConnectionGroup(connectionGroup) {
|
||||
|
||||
var children = [];
|
||||
|
||||
// Add any child connections
|
||||
connectionGroup.childConnections.forEach(function addChildConnection(child) {
|
||||
children.push(GroupListItem.fromConnection(child));
|
||||
});
|
||||
|
||||
// Add any child groups
|
||||
connectionGroup.childConnectionGroups.forEach(function addChildGroup(child) {
|
||||
children.push(GroupListItem.fromConnectionGroup(child));
|
||||
});
|
||||
|
||||
// Return item representing the given connection group
|
||||
return new GroupListItem({
|
||||
|
||||
// Identifying information
|
||||
name : connectionGroup.name,
|
||||
identifier : connectionGroup.identifier,
|
||||
|
||||
// Type information
|
||||
isConnection : false,
|
||||
isConnectionGroup : true,
|
||||
isBalancing : connectionGroup.type === ConnectionGroup.Type.BALANCING,
|
||||
|
||||
// Already-converted children
|
||||
children : children
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
return GroupListItem;
|
||||
|
||||
}]);
|
@@ -37,7 +37,8 @@ angular.module('history').factory('HistoryEntry', [function defineHistoryEntry()
|
||||
var HistoryEntry = function HistoryEntry(id, thumbnail) {
|
||||
|
||||
/**
|
||||
* The ID of the connection associated with this history entry.
|
||||
* The ID of the connection associated with this history entry,
|
||||
* including type prefix.
|
||||
*/
|
||||
this.id = id;
|
||||
|
||||
|
@@ -25,71 +25,23 @@
|
||||
*/
|
||||
angular.module('home').controller('homeController', ['$scope', '$injector',
|
||||
function homeController($scope, $injector) {
|
||||
|
||||
// Get required types
|
||||
var ConnectionGroup = $injector.get("ConnectionGroup");
|
||||
|
||||
// The parameter name for getting the history from local storage
|
||||
var GUAC_HISTORY_STORAGE_KEY = "GUAC_HISTORY";
|
||||
|
||||
// Get the dependencies commonJS style
|
||||
// Get required services
|
||||
var connectionGroupService = $injector.get("connectionGroupService");
|
||||
var guacHistory = $injector.get("guacHistory");
|
||||
|
||||
// All the connections and connection groups in root
|
||||
$scope.connectionsAndGroups = [];
|
||||
|
||||
// All valid recent connections
|
||||
$scope.recentConnections = [];
|
||||
|
||||
// Set status to loading until we have all the connections and groups loaded
|
||||
$scope.loading = true;
|
||||
|
||||
/* Fetch all connections and groups, then find which recent connections
|
||||
* still refer to valid connections and groups.
|
||||
*/
|
||||
connectionGroupService.getAllGroupsAndConnections($scope.connectionsAndGroups)
|
||||
.then(function findRecentConnections() {
|
||||
|
||||
// TODONT: Munch the guacHistory recentConnections list into a legacy-style object
|
||||
var recentConnections = {};
|
||||
for (var i=0; i < guacHistory.recentConnections.length; i++) {
|
||||
var entry = guacHistory.recentConnections[i];
|
||||
recentConnections[encodeURIComponent(entry.id)] = {
|
||||
id : entry.id,
|
||||
thumbnail : entry.thumbnail
|
||||
};
|
||||
}
|
||||
|
||||
// Figure out which recent connection entries are valid
|
||||
$scope.connectionsAndGroups.forEach(function findValidEntries (connectionOrGroup) {
|
||||
|
||||
var type = connectionOrGroup.isConnection ? "c" : "g";
|
||||
|
||||
// Find the unique ID to index into the recent connections
|
||||
var uniqueId = encodeURIComponent(
|
||||
type + "/" + connectionOrGroup.identifier
|
||||
);
|
||||
|
||||
/*
|
||||
* If it's a valid recent connection, add it to the list,
|
||||
* along with enough information to make a connection url.
|
||||
*/
|
||||
var recentConnection = recentConnections[uniqueId];
|
||||
if(recentConnection) {
|
||||
recentConnection.type = type;
|
||||
recentConnection.id = connectionOrGroup.identifier;
|
||||
$scope.recentConnections.push(recentConnection);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Retrieve root group and all descendants
|
||||
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER)
|
||||
.success(function rootGroupRetrieved(rootConnectionGroup) {
|
||||
|
||||
$scope.rootConnectionGroup = rootConnectionGroup;
|
||||
$scope.loading = false;
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* Toggle the open/closed status of the connectionGroup.
|
||||
*
|
||||
* @param {object} connectionGroup The connection group to toggle.
|
||||
*/
|
||||
$scope.toggleExpanded = function toggleExpanded(connectionGroup) {
|
||||
connectionGroup.expanded = !connectionGroup.expanded;
|
||||
};
|
||||
|
||||
}]);
|
||||
|
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A directive which displays the contents of a connection group.
|
||||
*/
|
||||
angular.module('home').directive('guacRecentConnections', [function guacRecentConnections() {
|
||||
|
||||
return {
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
scope: {
|
||||
|
||||
/**
|
||||
* The root connection group, and all visible descendants.
|
||||
* Recent connections will only be shown if they exist within this
|
||||
* hierarchy, regardless of their existence within the history.
|
||||
*
|
||||
* @type ConnectionGroup
|
||||
*/
|
||||
rootGroup : '='
|
||||
|
||||
},
|
||||
|
||||
templateUrl: 'app/home/templates/guacRecentConnections.html',
|
||||
controller: ['$scope', '$injector', 'guacHistory', 'RecentConnection',
|
||||
function guacRecentConnectionsController($scope, $injector, guacHistory, RecentConnection) {
|
||||
|
||||
var visibleObjects = {};
|
||||
|
||||
/**
|
||||
* Adds the given connection to the internal set of visible
|
||||
* objects.
|
||||
*
|
||||
* @param {Connection} connection
|
||||
* The connection to add to the internal set of visible objects.
|
||||
*/
|
||||
var addVisibleConnection = function addVisibleConnection(connection) {
|
||||
|
||||
// Add given connection to set of visible objects
|
||||
visibleObjects['c/' + connection.identifier] = connection;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the given connection group to the internal set of visible
|
||||
* objects, along with any descendants.
|
||||
*
|
||||
* @param {ConnectionGroup} connectionGroup
|
||||
* The connection group to add to the internal set of visible
|
||||
* objects, along with any descendants.
|
||||
*/
|
||||
var addVisibleConnectionGroup = function addVisibleConnectionGroup(connectionGroup) {
|
||||
|
||||
// Add given connection group to set of visible objects
|
||||
visibleObjects['g/' + connectionGroup.identifier] = connectionGroup;
|
||||
|
||||
// Add all child connections
|
||||
if (connectionGroup.childConnections)
|
||||
connectionGroup.childConnections.forEach(addVisibleConnection);
|
||||
|
||||
// Add all child connection groups
|
||||
if (connectionGroup.childConnectionGroups)
|
||||
connectionGroup.childConnectionGroups.forEach(addVisibleConnectionGroup);
|
||||
|
||||
};
|
||||
|
||||
// Update visible objects when root group is set
|
||||
$scope.$watch("rootGroup", function setRootGroup(rootGroup) {
|
||||
|
||||
$scope.recentConnections = [];
|
||||
|
||||
// Produce collection of visible objects
|
||||
visibleObjects = {};
|
||||
if (rootGroup)
|
||||
addVisibleConnectionGroup(rootGroup);
|
||||
|
||||
// Add any recent connections that are visible
|
||||
guacHistory.recentConnections.forEach(function addRecentConnection(historyEntry) {
|
||||
|
||||
// Add recent connections for history entries with associated visible objects
|
||||
if (historyEntry.id in visibleObjects) {
|
||||
|
||||
var object = visibleObjects[historyEntry.id];
|
||||
$scope.recentConnections.push(new RecentConnection(object.name, historyEntry));
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}); // end rootGroup scope watch
|
||||
|
||||
}]
|
||||
|
||||
};
|
||||
}]);
|
@@ -20,4 +20,4 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
angular.module('home', ['connection', 'connectionGroup', 'history', 'user', 'permission']);
|
||||
angular.module('home', ['history', 'groupList', 'rest']);
|
||||
|
@@ -0,0 +1,44 @@
|
||||
<div>
|
||||
<!--
|
||||
Copyright (C) 2014 Glyptodon LLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- Text displayed if no recent connections exist -->
|
||||
<p class="no-recent" ng-hide="recentConnections.length">{{'home.noRecentConnections' | translate}}</p>
|
||||
|
||||
<!-- All recent connections -->
|
||||
<div ng-repeat="recentConnection in recentConnections" class="connection">
|
||||
<a href="#/client/{{recentConnection.entry.id}}/{{recentConnection.name}}">
|
||||
|
||||
<!-- Connection thumbnail -->
|
||||
<div class="thumbnail">
|
||||
<img alt="{{recentConnection.name}}" ng-src="{{recentConnection.entry.thumbnail}}"/>
|
||||
</div>
|
||||
|
||||
<!-- Connection name -->
|
||||
<div class="caption">
|
||||
<span class="name">{{recentConnection.name}}</span>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
@@ -20,31 +20,6 @@
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<script type="text/ng-template" id="nestedGroup.html">
|
||||
<div class="connection" ng-show="item.isConnection">
|
||||
<a ng-href="#/client/c/{{item.identifier}}">
|
||||
<div class="caption">
|
||||
<div class="protocol">
|
||||
<div class="icon type" ng-class="item.protocol"></div>
|
||||
</div>
|
||||
<span class="name">{{item.name}}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="group" ng-show="!item.isConnection">
|
||||
<div class="caption">
|
||||
<div class="icon group type" ng-click="toggleExpanded(item)" ng-class="{expanded: item.expanded, empty: !item.children.length, balancer: item.balancer && !item.children.length}"></div>
|
||||
<span class="name">
|
||||
<a ng-show="item.balancer" ng-href="#/client/g/{{item.identifier}}">{{item.name}}</a>
|
||||
<span ng-show="!item.balancer">{{item.name}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="children" ng-show="item.expanded">
|
||||
<div class="list-item" ng-repeat="item in item.children | orderBy : 'name'" ng-include="'nestedGroup.html'">
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<div class="connection-list-ui">
|
||||
|
||||
<div class="logout-panel">
|
||||
@@ -54,25 +29,14 @@
|
||||
|
||||
<!-- The recent connections for this user -->
|
||||
<h2>{{'home.recentConnections' | translate}}</h2>
|
||||
<div class="recent-connections" ng-hide="recentConnections.length">
|
||||
<p class="no-recent">{{'home.noRecentConnections' | translate}}</p>
|
||||
</div>
|
||||
<div class="recent-connections" ng-show="recentConnections.length">
|
||||
<div ng-repeat="recentConnection in recentConnections" class="connection">
|
||||
<a href="#/client/{{recentConnection.type}}/{{recentConnection.id}}/{{recentConnection.name}}">
|
||||
<div class="thumbnail">
|
||||
<img alt="{{recentConnection.name}}" ng-src="{{recentConnection.thumbnail}}"/>
|
||||
</div>
|
||||
<div class="caption">
|
||||
<span class="name">{{recentConnection.name}}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="recent-connections" ng-class="{loading: loading}">
|
||||
<guac-recent-connections root-group="rootConnectionGroup"/>
|
||||
</div>
|
||||
|
||||
<!-- All connections for this user -->
|
||||
<h2>{{'home.allConnections' | translate}}</h2>
|
||||
<div class="all-connections" ng-class="{loading: loading}">
|
||||
<div class="list-item" ng-repeat="item in connectionsAndGroups | orderBy : 'name'" ng-include="'nestedGroup.html'"></div>
|
||||
<guac-group-list connection-group="rootConnectionGroup"/>
|
||||
</div>
|
||||
|
||||
</div>
|
@@ -20,18 +20,36 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest;
|
||||
|
||||
/**
|
||||
* Useful constants for the REST API.
|
||||
*
|
||||
* @author James Muehlner
|
||||
* Provides the RecentConnection class used by the guacRecentConnections
|
||||
* directive.
|
||||
*/
|
||||
public class APIConstants {
|
||||
angular.module('home').factory('RecentConnection', [function defineRecentConnection() {
|
||||
|
||||
/**
|
||||
* The identifier of the ROOT connection group.
|
||||
* A recently-user connection, visible to the current user, with an
|
||||
* associated history entry.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
public static final String ROOT_CONNECTION_GROUP_IDENTIFIER = "ROOT";
|
||||
|
||||
}
|
||||
var RecentConnection = function RecentConnection(name, entry) {
|
||||
|
||||
/**
|
||||
* The human-readable name of this connection.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* The history entry associated with this recent connection.
|
||||
*
|
||||
* @type HistoryEntry
|
||||
*/
|
||||
this.entry = entry;
|
||||
|
||||
};
|
||||
|
||||
return RecentConnection;
|
||||
|
||||
}]);
|
@@ -25,10 +25,12 @@
|
||||
*/
|
||||
angular.module('index').controller('indexController', ['$scope', '$injector',
|
||||
function indexController($scope, $injector) {
|
||||
|
||||
// Get the dependencies commonJS style
|
||||
var permissionDAO = $injector.get("permissionDAO"),
|
||||
permissionCheckService = $injector.get("permissionCheckService"),
|
||||
|
||||
// Get class dependencies
|
||||
var PermissionSet = $injector.get("PermissionSet");
|
||||
|
||||
// Get services
|
||||
var permissionService = $injector.get("permissionService"),
|
||||
authenticationService = $injector.get("authenticationService"),
|
||||
$q = $injector.get("$q"),
|
||||
$document = $injector.get("$document"),
|
||||
@@ -166,16 +168,18 @@ angular.module('index').controller('indexController', ['$scope', '$injector',
|
||||
// Allow the permissions to be reloaded elsewhere if needed
|
||||
$scope.loadBasicPermissions = function loadBasicPermissions() {
|
||||
|
||||
permissionDAO.getPermissions($scope.currentUserID).success(function fetchCurrentUserPermissions(permissions) {
|
||||
permissionService.getPermissions($scope.currentUserID).success(function fetchCurrentUserPermissions(permissions) {
|
||||
$scope.currentUserPermissions = permissions;
|
||||
|
||||
// Will be true if the user is an admin
|
||||
$scope.currentUserIsAdmin = permissionCheckService.checkPermission($scope.currentUserPermissions, "SYSTEM", undefined, "ADMINISTER");
|
||||
// Whether the user has system-wide admin permission
|
||||
$scope.currentUserIsAdmin = PermissionSet.hasSystemPermission($scope.currentUserPermissions, PermissionSet.SystemPermissionType.ADMINISTER);
|
||||
|
||||
// Whether the user can update at least one object
|
||||
$scope.currentUserHasUpdate = $scope.currentUserIsAdmin
|
||||
|| PermissionSet.hasConnectionPermission($scope.currentUserPermissions, "UPDATE")
|
||||
|| PermissionSet.hasConnectionGroupPermission($scope.currentUserPermissions, "UPDATE")
|
||||
|| PermissionSet.hasUserPermission($scope.currentUserPermissions, "UPDATE");
|
||||
|
||||
// Will be true if the user is an admin or has update access to any object
|
||||
$scope.currentUserHasUpdate = $scope.currentUserIsAdmin ||
|
||||
permissionCheckService.checkPermission($scope.currentUserPermissions, undefined, undefined, "UPDATE");
|
||||
|
||||
permissionsLoaded.resolve();
|
||||
});
|
||||
};
|
||||
|
@@ -24,4 +24,4 @@
|
||||
* The module for the root of the application.
|
||||
*/
|
||||
angular.module('index', ['ngRoute', 'pascalprecht.translate',
|
||||
'auth', 'home', 'manage', 'login', 'client', 'notification']);
|
||||
'auth', 'home', 'manage', 'login', 'client', 'notification', 'rest']);
|
||||
|
@@ -260,7 +260,7 @@ div.section {
|
||||
border-left: 1px dotted rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.group.balancer > .caption .icon.type {
|
||||
.group.balancer:not(.empty) > .caption .icon.type {
|
||||
display: inline-block;
|
||||
background-image: url('images/protocol-icons/guac-monitor.png');
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ angular.module('manage').controller('connectionGroupEditModalController', ['$sco
|
||||
function connectionEditModalController($scope, $injector) {
|
||||
|
||||
var connectionGroupEditModal = $injector.get('connectionGroupEditModal');
|
||||
var connectionGroupDAO = $injector.get('connectionGroupDAO');
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
var displayObjectPreparationService = $injector.get('displayObjectPreparationService');
|
||||
|
||||
// Make a copy of the old connection group so that we can copy over the changes when done
|
||||
@@ -64,7 +64,7 @@ angular.module('manage').controller('connectionGroupEditModalController', ['$sco
|
||||
* Save the connection and close the modal.
|
||||
*/
|
||||
$scope.save = function save() {
|
||||
connectionGroupDAO.saveConnectionGroup($scope.connectionGroup).success(function successfullyUpdatedConnectionGroup() {
|
||||
connectionGroupService.saveConnectionGroup($scope.connectionGroup).success(function successfullyUpdatedConnectionGroup() {
|
||||
|
||||
// Prepare this connection group for display
|
||||
displayObjectPreparationService.prepareConnectionGroup($scope.connectionGroup);
|
||||
@@ -79,7 +79,7 @@ angular.module('manage').controller('connectionGroupEditModalController', ['$sco
|
||||
if(newConnectionGroup && newParentID === $scope.rootGroup.identifier) {
|
||||
$scope.moveItem($scope.connectionGroup, oldParentID, newParentID);
|
||||
} else {
|
||||
connectionGroupDAO.moveConnectionGroup($scope.connectionGroup).then(function moveConnectionGroup() {
|
||||
connectionGroupService.moveConnectionGroup($scope.connectionGroup).then(function moveConnectionGroup() {
|
||||
$scope.moveItem($scope.connectionGroup, oldParentID, newParentID);
|
||||
});
|
||||
}
|
||||
@@ -99,7 +99,7 @@ angular.module('manage').controller('connectionGroupEditModalController', ['$sco
|
||||
// Close the modal
|
||||
connectionGroupEditModal.deactivate();
|
||||
|
||||
connectionGroupDAO.deleteConnectionGroup($scope.connectionGroup).success(function successfullyDeletedConnectionGroup() {
|
||||
connectionGroupService.deleteConnectionGroup($scope.connectionGroup).success(function successfullyDeletedConnectionGroup() {
|
||||
var oldParentID = oldConnectionGroup.parentIdentifier;
|
||||
|
||||
// We have to remove this connection group from the heirarchy
|
||||
|
@@ -25,60 +25,39 @@
|
||||
*/
|
||||
angular.module('manage').controller('manageController', ['$scope', '$injector',
|
||||
function manageController($scope, $injector) {
|
||||
|
||||
// Get the dependencies commonJS style
|
||||
|
||||
// Required types
|
||||
var PermissionSet = $injector.get('PermissionSet');
|
||||
var ConnectionGroup = $injector.get('ConnectionGroup');
|
||||
|
||||
// Required services
|
||||
var connectionGroupService = $injector.get('connectionGroupService');
|
||||
var connectionEditModal = $injector.get('connectionEditModal');
|
||||
var connectionGroupEditModal = $injector.get('connectionGroupEditModal');
|
||||
var userEditModal = $injector.get('userEditModal');
|
||||
var protocolDAO = $injector.get('protocolDAO');
|
||||
var userDAO = $injector.get('userDAO');
|
||||
var protocolService = $injector.get('protocolService');
|
||||
var userService = $injector.get('userService');
|
||||
|
||||
// Set status to loading until we have all the connections, groups, and users have loaded
|
||||
$scope.loadingUsers = true;
|
||||
$scope.loadingConnections = true;
|
||||
|
||||
// All the connections and connection groups in root
|
||||
$scope.connectionsAndGroups = [];
|
||||
|
||||
// All users that the current user has permission to edit
|
||||
$scope.users = [];
|
||||
|
||||
$scope.basicPermissionsLoaded.then(function basicPermissionsHaveBeenLoaded() {
|
||||
connectionGroupService.getAllGroupsAndConnections([], undefined, true, true).then(function filterConnectionsAndGroups(rootGroupList) {
|
||||
$scope.rootGroup = rootGroupList[0];
|
||||
$scope.connectionsAndGroups = $scope.rootGroup.children;
|
||||
|
||||
// Filter the items to only include ones that we have UPDATE for
|
||||
if(!$scope.currentUserIsAdmin) {
|
||||
connectionGroupService.filterConnectionsAndGroupByPermission(
|
||||
$scope.connectionsAndGroups,
|
||||
$scope.currentUserPermissions,
|
||||
{
|
||||
'CONNECTION': 'UPDATE',
|
||||
'CONNECTION_GROUP': 'UPDATE'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Retrieve all users for whom we have UPDATE permission
|
||||
connectionGroupService.getConnectionGroupTree(ConnectionGroup.ROOT_IDENTIFIER, PermissionSet.ObjectPermissionType.UPDATE)
|
||||
.success(function connectionGroupReceived(rootGroup) {
|
||||
$scope.rootGroup = rootGroup;
|
||||
$scope.loadingConnections = false;
|
||||
});
|
||||
|
||||
userDAO.getUsers().success(function filterEditableUsers(users) {
|
||||
|
||||
// Retrieve all users for whom we have UPDATE permission
|
||||
userService.getUsers(PermissionSet.ObjectPermissionType.UPDATE)
|
||||
.success(function usersReceived(users) {
|
||||
$scope.users = users;
|
||||
|
||||
// Filter the users to only include ones that we have UPDATE for
|
||||
if(!$scope.currentUserIsAdmin) {
|
||||
userService.filterUsersByPermission(
|
||||
$scope.users,
|
||||
$scope.currentUserPermissions,
|
||||
'UPDATE'
|
||||
);
|
||||
}
|
||||
|
||||
$scope.loadingUsers = false;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -132,7 +111,7 @@ angular.module('manage').controller('manageController', ['$scope', '$injector',
|
||||
$scope.protocols = {};
|
||||
|
||||
// Get the protocol information from the server and copy it into the scope
|
||||
protocolDAO.getProtocols().success(function fetchProtocols(protocols) {
|
||||
protocolService.getProtocols().success(function fetchProtocols(protocols) {
|
||||
angular.extend($scope.protocols, protocols);
|
||||
});
|
||||
|
||||
@@ -236,7 +215,7 @@ angular.module('manage').controller('manageController', ['$scope', '$injector',
|
||||
username: $scope.newUsername
|
||||
};
|
||||
|
||||
userDAO.createUser(newUser).success(function addUserToList() {
|
||||
userService.createUser(newUser).success(function addUserToList() {
|
||||
$scope.users.push(newUser);
|
||||
});
|
||||
|
||||
|
@@ -26,9 +26,9 @@
|
||||
angular.module('manage').controller('userEditModalController', ['$scope', '$injector',
|
||||
function userEditModalController($scope, $injector) {
|
||||
|
||||
var userEditModal = $injector.get('userEditModal');
|
||||
var userDAO = $injector.get('userDAO');
|
||||
var permissionDAO = $injector.get('permissionDAO');
|
||||
var userEditModal = $injector.get('userEditModal');
|
||||
var userService = $injector.get('userService');
|
||||
var permissionService = $injector.get('permissionService');
|
||||
|
||||
// Make a copy of the old user so that we can copy over the changes when done
|
||||
var oldUser = $scope.user;
|
||||
@@ -73,7 +73,7 @@ angular.module('manage').controller('userEditModalController', ['$scope', '$inje
|
||||
return;
|
||||
}
|
||||
|
||||
userDAO.saveUser($scope.user).success(function successfullyUpdatedUser() {
|
||||
userService.saveUser($scope.user).success(function successfullyUpdatedUser() {
|
||||
|
||||
//Figure out what permissions have changed
|
||||
var connectionPermissionsToCreate = [],
|
||||
@@ -182,7 +182,7 @@ angular.module('manage').controller('userEditModalController', ['$scope', '$inje
|
||||
|
||||
if(permissionsToAdd.length || permissionsToRemove.length) {
|
||||
// Make the call to update the permissions
|
||||
permissionDAO.patchPermissions(
|
||||
permissionService.patchPermissions(
|
||||
$scope.user.username, permissionsToAdd, permissionsToRemove)
|
||||
.success(completeSaveProcess).error(handleFailure);
|
||||
} else {
|
||||
@@ -205,7 +205,7 @@ angular.module('manage').controller('userEditModalController', ['$scope', '$inje
|
||||
originalSystemPermissions;
|
||||
|
||||
// Get the permissions for the user we are editing
|
||||
permissionDAO.getPermissions($scope.user.username).success(function gotPermissions(permissions) {
|
||||
permissionService.getPermissions($scope.user.username).success(function gotPermissions(permissions) {
|
||||
$scope.permissions = permissions;
|
||||
|
||||
// Figure out if the user has any system level permissions
|
||||
@@ -239,7 +239,7 @@ angular.module('manage').controller('userEditModalController', ['$scope', '$inje
|
||||
* Delete the user and close the modal.
|
||||
*/
|
||||
$scope['delete'] = function deleteUser() {
|
||||
userDAO.deleteUser($scope.user).success(function successfullyDeletedUser() {
|
||||
userService.deleteUser($scope.user).success(function successfullyDeletedUser() {
|
||||
|
||||
// Remove the user from the list
|
||||
$scope.removeUser($scope.user);
|
||||
|
@@ -23,5 +23,5 @@
|
||||
/**
|
||||
* The module for the administration functionality.
|
||||
*/
|
||||
angular.module('manage', ['btford.modal', 'protocol', 'connection', 'connectionGroup', 'util']);
|
||||
angular.module('manage', ['btford.modal', 'groupList', 'rest', 'util']);
|
||||
|
||||
|
@@ -20,28 +20,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<script type="text/ng-template" id="nestedGroup.html">
|
||||
<div class="connection" ng-click="editConnection(item)" ng-show="item.isConnection">
|
||||
<div class="caption">
|
||||
<div class="protocol">
|
||||
<div class="icon type" ng-class="item.protocol"></div>
|
||||
</div>
|
||||
<span class="name">{{item.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="group" ng-show="!item.isConnection">
|
||||
<div class="caption">
|
||||
<div class="icon group type" ng-click="toggleExpanded(item)" ng-class="{expanded: item.expanded, empty: !item.children.length, balancer: item.balancer && !item.children.length}"></div>
|
||||
<span ng-click="editConnectionGroup(item)" class="name">
|
||||
<span>{{item.name}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="children" ng-show="item.expanded">
|
||||
<div class="list-item" ng-repeat="item in item.children | orderBy : 'name'" ng-include="'nestedGroup.html'">
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<div class="logout-panel">
|
||||
<a class="back button" href="#/">{{'manage.back' | translate}}</a>
|
||||
<a class="logout button" ng-click="logout()">{{'home.logout' | translate}}</a>
|
||||
@@ -85,7 +63,7 @@ THE SOFTWARE.
|
||||
|
||||
<!-- List of connections and groups this user has access to -->
|
||||
<div class="connection-list" ng-class="{loading: loadingConnections}">
|
||||
<div class="list-item" ng-repeat="item in connectionsAndGroups | orderBy : 'name'" ng-include="'nestedGroup.html'"></div>
|
||||
<guac-group-list connection-group="rootGroup"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A module for code relating to permissions.
|
||||
*/
|
||||
angular.module('permission', ['auth']);
|
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A service for checking if a specific permission exists
|
||||
* in a given list of permissions.
|
||||
*/
|
||||
angular.module('permission').factory('permissionCheckService', [
|
||||
function permissionCheckService() {
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* A service for checking if the given permission list contains the given
|
||||
* permission, defined by the objectType, objectID, and permissionType.
|
||||
* If the objectType or objectID are not passed, they will not be checked.
|
||||
*
|
||||
* For example, checkPermission(list, "CONNECTION", undefined, "READ") would
|
||||
* check if the permission list contains permission to read any connection.
|
||||
*
|
||||
* @param {array} permissions The array of permissions to check.
|
||||
* @param {string} objectType The object type for the permission.
|
||||
* If not passed, this will not be checked.
|
||||
* @param {string} objectID The ID of the object the permission is for.
|
||||
* If not passed, this will not be checked.
|
||||
* @param {string} permissionType The actual permission type to check for.
|
||||
* @returns {boolean} True if the given permissions contain the requested permission, false otherwise.
|
||||
*/
|
||||
service.checkPermission = function checkPermission(permissions, objectType, objectID, permissionType) {
|
||||
|
||||
// Loop through all the permissions and check if any of them match the given parameters
|
||||
for(var i = 0; i < permissions.length; i++) {
|
||||
var permission = permissions[i];
|
||||
|
||||
if(objectType === "SYSTEM") {
|
||||
// System permissions have no object ID, we only need to check the type.
|
||||
if(permission.permissionType === permissionType)
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// Object permissions need to match the object ID and type if given.
|
||||
if(permission.permissionType === permissionType &&
|
||||
(!objectType || permission.objectType === objectType) &&
|
||||
(!objectID || permission.objectID === objectID))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find any that matched
|
||||
return false;
|
||||
}
|
||||
|
||||
return service;
|
||||
}]);
|
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The DAO for permission operations agains the REST API.
|
||||
*/
|
||||
angular.module('permission').factory('permissionDAO', ['$http', 'authenticationService',
|
||||
function permissionDAO($http, authenticationService) {
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the list of permissions for a given user,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {string} userID The ID of the user to retrieve the permissions for.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.getPermissions = function getPermissions(userID) {
|
||||
return $http.get("api/permission/" + userID + "/?token=" + authenticationService.getCurrentToken());
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to add a permission for a given user,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {string} userID The ID of the user to add the permission for.
|
||||
* @param {object} permission The permission to add.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.addPermission = function addPermission(userID, permission) {
|
||||
return $http.post("api/permission/" + userID + "/?token=" + authenticationService.getCurrentToken(), permission);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to remove a permission for a given user,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {string} userID The ID of the user to remove the permission for.
|
||||
* @param {object} permission The permission to remove.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.removePermission = function removePermission(userID, permission) {
|
||||
return $http.post("api/permission/remove/" + userID + "/?token=" + authenticationService.getCurrentToken(), permission);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to modify the permissions for a given user,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {string} userID The ID of the user to remove the permission for.
|
||||
* @param {array} permissionsToAdd The permissions to add.
|
||||
* @param {array} permissionsToRemove The permissions to remove.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.patchPermissions = function patchPermissions(userID, permissionsToAdd, permissionsToRemove) {
|
||||
var permissionPatch = [];
|
||||
|
||||
// Add all the add operations to the patch
|
||||
for(var i = 0; i < permissionsToAdd.length; i++ ) {
|
||||
permissionPatch.push({
|
||||
op : "add",
|
||||
path : userID,
|
||||
value : permissionsToAdd[i]
|
||||
});
|
||||
}
|
||||
|
||||
// Add all the remove operations to the patch
|
||||
for(var i = 0; i < permissionsToRemove.length; i++ ) {
|
||||
permissionPatch.push({
|
||||
op : "remove",
|
||||
path : userID,
|
||||
value : permissionsToRemove[i]
|
||||
});
|
||||
}
|
||||
|
||||
// Make the HTTP call
|
||||
return $http({
|
||||
method : 'PATCH',
|
||||
url : "api/permission/?token=" + authenticationService.getCurrentToken(),
|
||||
data : permissionPatch
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return service;
|
||||
}]);
|
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* The module for the protocol functionality.
|
||||
* The module for code relating to communication with the REST API of the
|
||||
* Guacamole web application.
|
||||
*/
|
||||
angular.module('protocol', []);
|
||||
angular.module('rest', ['auth']);
|
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service for operating on connection groups via the REST API.
|
||||
*/
|
||||
angular.module('rest').factory('connectionGroupService', ['$http', 'authenticationService', 'ConnectionGroup',
|
||||
function connectionGroupService($http, authenticationService, ConnectionGroup) {
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get an individual connection group
|
||||
* and all descendants, returning a promise that provides the corresponding
|
||||
* @link{ConnectionGroup} if successful. Descendant groups and connections
|
||||
* will be stored as children of that connection group. If a permission
|
||||
* type is specified, the result will be filtering by that permission.
|
||||
*
|
||||
* @param {String} [connectionGroupID=ConnectionGroup.ROOT_IDENTIFIER]
|
||||
* The ID of the connection group to retrieve. If not provided, the
|
||||
* root connection group will be retrieved by default.
|
||||
*
|
||||
* @param {String} [permissionType]
|
||||
* The permission type string of the permission that the current user
|
||||
* must have for a given connection or connection group to appear
|
||||
* within the result. Valid values are listed within
|
||||
* PermissionSet.ObjectType.
|
||||
*
|
||||
* @returns {Promise.ConnectionGroup}
|
||||
* A promise which will resolve with a @link{ConnectionGroup} upon
|
||||
* success.
|
||||
*/
|
||||
service.getConnectionGroupTree = function getConnectionGroupTree(connectionGroupID, permissionType) {
|
||||
|
||||
// Use the root connection group ID if no ID is passed in
|
||||
connectionGroupID = connectionGroupID || ConnectionGroup.ROOT_IDENTIFIER;
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Add permission filter if specified
|
||||
if (permissionType)
|
||||
httpParameters.permission = permissionType;
|
||||
|
||||
// Retrieve connection group
|
||||
return $http({
|
||||
method : 'GET',
|
||||
url : 'api/connectionGroups/' + encodeURIComponent(connectionGroupID) + '/tree',
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get an individual connection group,
|
||||
* returning a promise that provides the corresponding
|
||||
* @link{ConnectionGroup} if successful.
|
||||
*
|
||||
* @param {String} [connectionGroupID=ConnectionGroup.ROOT_IDENTIFIER]
|
||||
* The ID of the connection group to retrieve. If not provided, the
|
||||
* root connection group will be retrieved by default.
|
||||
*
|
||||
* @returns {Promise.<ConnectionGroup>} A promise for the HTTP call.
|
||||
* A promise which will resolve with a @link{ConnectionGroup} upon
|
||||
* success.
|
||||
*/
|
||||
service.getConnectionGroup = function getConnectionGroup(connectionGroupID) {
|
||||
|
||||
// Use the root connection group ID if no ID is passed in
|
||||
connectionGroupID = connectionGroupID || ConnectionGroup.ROOT_IDENTIFIER;
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve connection group
|
||||
return $http({
|
||||
method : 'GET',
|
||||
url : 'api/connectionGroups/' + encodeURIComponent(connectionGroupID),
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to save a connection group, returning a
|
||||
* promise that can be used for processing the results of the call. If the
|
||||
* connection group is new, and thus does not yet have an associated
|
||||
* identifier, the identifier will be automatically set in the provided
|
||||
* connection group upon success.
|
||||
*
|
||||
* @param {ConnectionGroup} connectionGroup The connection group to update.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* save operation is successful.
|
||||
*/
|
||||
service.saveConnectionGroup = function saveConnectionGroup(connectionGroup) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// If connection group is new, add it and set the identifier automatically
|
||||
if (!connectionGroup.identifier) {
|
||||
return $http({
|
||||
method : 'POST',
|
||||
url : 'api/connectionGroups',
|
||||
params : httpParameters,
|
||||
data : connectionGroup
|
||||
})
|
||||
|
||||
// Set the identifier on the new connection group
|
||||
.success(function connectionGroupCreated(identifier){
|
||||
connectionGroup.identifier = identifier;
|
||||
});
|
||||
}
|
||||
|
||||
// Otherwise, update the existing connection group
|
||||
else {
|
||||
return $http({
|
||||
method : 'PUT',
|
||||
url : 'api/connectionGroups/' + encodeURIComponent(connectionGroup.identifier),
|
||||
params : httpParameters,
|
||||
data : connectionGroup
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to delete a connection group, returning
|
||||
* a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {ConnectionGroup} connectionGroup The connection group to delete.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* delete operation is successful.
|
||||
*/
|
||||
service.deleteConnectionGroup = function deleteConnectionGroup(connectionGroup) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Delete connection group
|
||||
return $http({
|
||||
method : 'DELETE',
|
||||
url : 'api/connectionGroups/' + encodeURIComponent(connectionGroup.identifier),
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
return service;
|
||||
}]);
|
192
guacamole/src/main/webapp/app/rest/services/connectionService.js
Normal file
192
guacamole/src/main/webapp/app/rest/services/connectionService.js
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service for operating on connections via the REST API.
|
||||
*/
|
||||
angular.module('rest').factory('connectionService', ['$http', 'authenticationService',
|
||||
function connectionService($http, authenticationService) {
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get a single connection, returning a
|
||||
* promise that provides the corresponding @link{Connection} if successful.
|
||||
*
|
||||
* @param {String} id The ID of the connection.
|
||||
*
|
||||
* @returns {Promise.<Connection>}
|
||||
* A promise which will resolve with a @link{Connection} upon success.
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* connectionService.getConnection('myConnection').success(function(connection) {
|
||||
* // Do something with the connection
|
||||
* });
|
||||
*/
|
||||
service.getConnection = function getConnection(id) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve connection
|
||||
return $http({
|
||||
method : 'GET',
|
||||
url : 'api/connections/' + encodeURIComponent(id),
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the usage history of a single
|
||||
* connection, returning a promise that provides the corresponding
|
||||
* array of @link{ConnectionHistoryEntry} objects if successful.
|
||||
*
|
||||
* @param {String} id
|
||||
* The identifier of the connection.
|
||||
*
|
||||
* @returns {Promise.<ConnectionHistoryEntry[]>}
|
||||
* A promise which will resolve with an array of
|
||||
* @link{ConnectionHistoryEntry} objects upon success.
|
||||
*/
|
||||
service.getConnectionHistory = function getConnectionHistory(id) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve connection history
|
||||
return $http({
|
||||
method : 'GET',
|
||||
url : 'api/connections/' + encodeURIComponent(id) + '/history',
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the parameters of a single
|
||||
* connection, returning a promise that provides the corresponding
|
||||
* map of parameter name/value pairs if successful.
|
||||
*
|
||||
* @param {String} id
|
||||
* The identifier of the connection.
|
||||
*
|
||||
* @returns {Promise.<Object.<String, String>>}
|
||||
* A promise which will resolve with an map of parameter name/value
|
||||
* pairs upon success.
|
||||
*/
|
||||
service.getConnectionParameters = function getConnectionParameters(id) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve connection parameters
|
||||
return $http({
|
||||
method : 'GET',
|
||||
url : 'api/connections/' + encodeURIComponent(id) + '/parameters',
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to save a connection, returning a
|
||||
* promise that can be used for processing the results of the call. If the
|
||||
* connection is new, and thus does not yet have an associated identifier,
|
||||
* the identifier will be automatically set in the provided connection
|
||||
* upon success.
|
||||
*
|
||||
* @param {Connection} connection The connection to update.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* save operation is successful.
|
||||
*/
|
||||
service.saveConnection = function saveConnection(connection) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// If connection is new, add it and set the identifier automatically
|
||||
if (!connection.identifier) {
|
||||
return $http({
|
||||
method : 'POST',
|
||||
url : 'api/connections',
|
||||
params : httpParameters,
|
||||
data : connection
|
||||
})
|
||||
|
||||
// Set the identifier on the new connection
|
||||
.success(function connectionCreated(identifier){
|
||||
connection.identifier = identifier;
|
||||
});
|
||||
}
|
||||
|
||||
// Otherwise, update the existing connection
|
||||
else {
|
||||
return $http({
|
||||
method : 'PUT',
|
||||
url : 'api/connections/' + encodeURIComponent(connection.identifier),
|
||||
params : httpParameters,
|
||||
data : connection
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to delete a connection,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {Connection} connection The connection to delete.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* delete operation is successful.
|
||||
*/
|
||||
service.deleteConnection = function deleteConnection(connection) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Delete connection
|
||||
return $http({
|
||||
method : 'DELETE',
|
||||
url : 'api/connections/' + encodeURIComponent(connection.identifier),
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
return service;
|
||||
}]);
|
216
guacamole/src/main/webapp/app/rest/services/permissionService.js
Normal file
216
guacamole/src/main/webapp/app/rest/services/permissionService.js
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service for operating on user permissions via the REST API.
|
||||
*/
|
||||
angular.module('rest').factory('permissionService', ['$http', 'authenticationService', 'PermissionPatch',
|
||||
function permissionService($http, authenticationService, PermissionPatch) {
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the list of permissions for a
|
||||
* given user, returning a promise that provides an array of
|
||||
* @link{Permission} objects if successful.
|
||||
*
|
||||
* @param {String} userID
|
||||
* The ID of the user to retrieve the permissions for.
|
||||
*
|
||||
* @returns {Promise.<PermissionSet>}
|
||||
* A promise which will resolve with a @link{PermissionSet} upon
|
||||
* success.
|
||||
*/
|
||||
service.getPermissions = function getPermissions(userID) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve user permissions
|
||||
return $http({
|
||||
method : 'GET',
|
||||
url : 'api/users/' + encodeURIComponent(userID) + '/permissions',
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to add permissions for a given user,
|
||||
* returning a promise that can be used for processing the results of the
|
||||
* call.
|
||||
*
|
||||
* @param {String} userID
|
||||
* The ID of the user to modify the permissions of.
|
||||
*
|
||||
* @param {PermissionSet} permissions
|
||||
* The set of permissions to add.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* add operation is successful.
|
||||
*/
|
||||
service.addPermissions = function addPermissions(userID, permissions) {
|
||||
return service.patchPermissions(userID, permissions, null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to remove permissions for a given user,
|
||||
* returning a promise that can be used for processing the results of the
|
||||
* call.
|
||||
*
|
||||
* @param {String} userID
|
||||
* The ID of the user to modify the permissions of.
|
||||
*
|
||||
* @param {PermissionSet} permissions
|
||||
* The set of permissions to remove.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* remove operation is successful.
|
||||
*/
|
||||
service.removePermissions = function removePermissions(userID, permissions) {
|
||||
return service.patchPermissions(userID, null, permissions);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds patches for modifying the permissions associated with specific
|
||||
* objects to the given array of patches.
|
||||
*
|
||||
* @param {PermissionPatch[]} patch
|
||||
* The array of patches to add new patches to.
|
||||
*
|
||||
* @param {String} operation
|
||||
* The operation to specify within each of the patches. Valid values
|
||||
* for this are defined within PermissionPatch.Operation.
|
||||
*
|
||||
* @param {String} path
|
||||
* The path of the permissions being patched. The path is a JSON path
|
||||
* describing the position of the permissions within a PermissionSet.
|
||||
*
|
||||
* @param {Object.<String, String[]>} permissions
|
||||
* A map of object identifiers to arrays of permission type strings,
|
||||
* where each type string is a value from
|
||||
* PermissionSet.ObjectPermissionType.
|
||||
*/
|
||||
var addObjectPatchOperations = function addObjectPatchOperations(patch, operation, path, permissions) {
|
||||
|
||||
// Add object permission operations to patch
|
||||
for (var identifier in permissions) {
|
||||
permissions[identifier].forEach(function addObjectPatch(type) {
|
||||
patch.push({
|
||||
op : operation,
|
||||
path : path + "/" + identifier,
|
||||
value : type
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds patches for modifying any permission that can be stored within a
|
||||
* @link{PermissionSet}.
|
||||
*
|
||||
* @param {PermissionPatch[]} patch
|
||||
* The array of patches to add new patches to.
|
||||
*
|
||||
* @param {String} operation
|
||||
* The operation to specify within each of the patches. Valid values
|
||||
* for this are defined within PermissionPatch.Operation.
|
||||
*
|
||||
* @param {PermissionSet} permissions
|
||||
* The set of permissions for which patches should be added.
|
||||
*/
|
||||
var addPatchOperations = function addPatchOperations(patch, operation, permissions) {
|
||||
|
||||
// Add connection permission operations to patch
|
||||
addObjectPatchOperations(patch, operation, "/connectionPermissions",
|
||||
permissions.connectionPermissions);
|
||||
|
||||
// Add connection group permission operations to patch
|
||||
addObjectPatchOperations(patch, operation, "/connectionGroupPermissions",
|
||||
permissions.connectionGroupPermissions);
|
||||
|
||||
// Add user permission operations to patch
|
||||
addObjectPatchOperations(patch, operation, "/userPermissions",
|
||||
permissions.userPermissions);
|
||||
|
||||
// Add system operations to patch
|
||||
permissions.systemPermissions.forEach(function addSystemPatch(type) {
|
||||
patch.push({
|
||||
op : operation,
|
||||
path : "/systemPermissions",
|
||||
value : type
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to modify the permissions for a given
|
||||
* user, returning a promise that can be used for processing the results of
|
||||
* the call.
|
||||
*
|
||||
* @param {String} userID
|
||||
* The ID of the user to modify the permissions of.
|
||||
*
|
||||
* @param {PermissionSet} [permissionsToAdd]
|
||||
* The set of permissions to add, if any.
|
||||
*
|
||||
* @param {PermissionSet} [permissionsToRemove]
|
||||
* The set of permissions to remove, if any.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* patch operation is successful.
|
||||
*/
|
||||
service.patchPermissions = function patchPermissions(userID, permissionsToAdd, permissionsToRemove) {
|
||||
|
||||
var permissionPatch = [];
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Add all the add operations to the patch
|
||||
addPatchOperations(permissionPatch, PermissionPatch.Operation.ADD, permissionsToAdd);
|
||||
|
||||
// Add all the remove operations to the patch
|
||||
addPatchOperations(permissionPatch, PermissionPatch.Operation.REMOVE, permissionsToRemove);
|
||||
|
||||
// Patch user permissions
|
||||
return $http({
|
||||
method : 'PATCH',
|
||||
url : 'api/users/' + encodeURIComponent(userID) + '/permissions',
|
||||
params : httpParameters,
|
||||
data : permissionPatch
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}]);
|
@@ -21,21 +21,38 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* The DAO for protocol operations agains the REST API.
|
||||
* Service for operating on protocol metadata via the REST API.
|
||||
*/
|
||||
angular.module('protocol').factory('protocolDAO', ['$http', function protocolDAO($http) {
|
||||
angular.module('rest').factory('protocolService', ['$http', 'authenticationService',
|
||||
function protocolService($http, authenticationService) {
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the list of protocols,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
* Makes a request to the REST API to get the list of protocols, returning
|
||||
* a promise that provides an array of @link{Protocol} objects if
|
||||
* successful.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
* @returns {Promise.<Protocol[]>}
|
||||
* A promise which will resolve with an array of @link{Protocol}
|
||||
* objects upon success.
|
||||
*/
|
||||
service.getProtocols = function getProtocols() {
|
||||
return $http.get("api/protocol");
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve available protocols
|
||||
return $http({
|
||||
method : 'GET',
|
||||
url : 'api/protocols',
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}]);
|
177
guacamole/src/main/webapp/app/rest/services/userService.js
Normal file
177
guacamole/src/main/webapp/app/rest/services/userService.js
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service for operating on users via the REST API.
|
||||
*/
|
||||
angular.module('rest').factory('userService', ['$http', 'authenticationService',
|
||||
function userService($http, authenticationService) {
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the list of users,
|
||||
* returning a promise that provides an array of @link{User} objects if
|
||||
* successful.
|
||||
*
|
||||
* @param {String} [permissionType]
|
||||
* The permission type string of the permission that the current user
|
||||
* must have for a given user to appear within the list. Valid values
|
||||
* are listed within PermissionSet.ObjectType.
|
||||
*
|
||||
* @returns {Promise.<User[]>}
|
||||
* A promise which will resolve with an array of @link{User} objects
|
||||
* upon success.
|
||||
*/
|
||||
service.getUsers = function getUsers(permissionType) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Add permission filter if specified
|
||||
if (permissionType)
|
||||
httpParameters.permission = permissionType;
|
||||
|
||||
// Retrieve users
|
||||
return $http({
|
||||
method : 'GET',
|
||||
url : 'api/users',
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the user having the given
|
||||
* username, returning a promise that provides the corresponding
|
||||
* @link{User} if successful.
|
||||
*
|
||||
* @param {String} username
|
||||
* The username of the user to retrieve.
|
||||
*
|
||||
* @returns {Promise.<User>}
|
||||
* A promise which will resolve with a @link{User} upon success.
|
||||
*/
|
||||
service.getUser = function getUser(username) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve user
|
||||
return $http({
|
||||
method : 'GET',
|
||||
url : 'api/users/' + encodeURIComponent(username),
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to delete a user, returning a promise
|
||||
* that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {User} user
|
||||
* The user to delete.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* delete operation is successful.
|
||||
*/
|
||||
service.deleteUser = function deleteUser(user) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve user
|
||||
return $http({
|
||||
method : 'DELETE',
|
||||
url : 'api/users/' + encodeURIComponent(user.username),
|
||||
params : httpParameters
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to create a user, returning a promise
|
||||
* that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {User} user
|
||||
* The user to create.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* create operation is successful.
|
||||
*/
|
||||
service.createUser = function createUser(user) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve user
|
||||
return $http({
|
||||
method : 'POST',
|
||||
url : 'api/users',
|
||||
params : httpParameters,
|
||||
data : user
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to save a user, returning a promise that
|
||||
* can be used for processing the results of the call.
|
||||
*
|
||||
* @param {User} user
|
||||
* The user to update.
|
||||
*
|
||||
* @returns {Promise}
|
||||
* A promise for the HTTP call which will succeed if and only if the
|
||||
* save operation is successful.
|
||||
*/
|
||||
service.saveUser = function saveUser(user) {
|
||||
|
||||
// Build HTTP parameters set
|
||||
var httpParameters = {
|
||||
token : authenticationService.getCurrentToken()
|
||||
};
|
||||
|
||||
// Retrieve user
|
||||
return $http({
|
||||
method : 'PUT',
|
||||
url : 'api/users/' + encodeURIComponent(user.username),
|
||||
params : httpParameters,
|
||||
data : user
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
}]);
|
@@ -23,7 +23,7 @@
|
||||
/**
|
||||
* Service which defines the Connection class.
|
||||
*/
|
||||
angular.module('connection').factory('Connection', [function defineConnection() {
|
||||
angular.module('rest').factory('Connection', [function defineConnection() {
|
||||
|
||||
/**
|
||||
* The object returned by REST API calls when representing the data
|
||||
@@ -70,24 +70,15 @@ angular.module('connection').factory('Connection', [function defineConnection()
|
||||
*/
|
||||
this.protocol = template.protocol;
|
||||
|
||||
/**
|
||||
* All previous and current usages of this connection, along with
|
||||
* associated users.
|
||||
*
|
||||
* @type ConnectionHistoryEntry[]
|
||||
*/
|
||||
this.history = template.history || [];
|
||||
|
||||
/**
|
||||
* Connection configuration parameters, as dictated by the protocol in
|
||||
* use, arranged as name/value pairs. This information may not be
|
||||
* available if the current user lacks permission to update
|
||||
* connection parameters, even if they otherwise have permission to
|
||||
* read and use the connection.
|
||||
* available until directly queried. If this information is
|
||||
* unavailable, this property will be null or undefined.
|
||||
*
|
||||
* @type Object.<String, String>
|
||||
*/
|
||||
this.parameters = template.parameters || {};
|
||||
this.parameters = template.parameters;
|
||||
|
||||
};
|
||||
|
127
guacamole/src/main/webapp/app/rest/types/ConnectionGroup.js
Normal file
127
guacamole/src/main/webapp/app/rest/types/ConnectionGroup.js
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service which defines the ConnectionGroup class.
|
||||
*/
|
||||
angular.module('rest').factory('ConnectionGroup', [function defineConnectionGroup() {
|
||||
|
||||
/**
|
||||
* The object returned by REST API calls when representing the data
|
||||
* associated with a connection group.
|
||||
*
|
||||
* @constructor
|
||||
* @param {ConnectionGroup|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* ConnectionGroup.
|
||||
*/
|
||||
var ConnectionGroup = function ConnectionGroup(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The unique identifier associated with this connection group.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.identifier = template.identifier;
|
||||
|
||||
/**
|
||||
* The unique identifier of the connection group that contains this
|
||||
* connection group.
|
||||
*
|
||||
* @type String
|
||||
* @default ConnectionGroup.ROOT_IDENTIFIER
|
||||
*/
|
||||
this.parentIdentifier = template.parentIdentifier || ConnectionGroup.ROOT_IDENTIFIER;
|
||||
|
||||
/**
|
||||
* The human-readable name of this connection group, which is not
|
||||
* necessarily unique.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.name = template.name;
|
||||
|
||||
/**
|
||||
* The type of this connection group, which may be either
|
||||
* ConnectionGroup.Type.ORGANIZATIONAL or
|
||||
* ConnectionGroup.Type.BALANCING.
|
||||
*
|
||||
* @type String
|
||||
* @default ConnectionGroup.Type.ORGANIZATIONAL
|
||||
*/
|
||||
this.type = template.type || ConnectionGroup.Type.ORGANIZATIONAL;
|
||||
|
||||
/**
|
||||
* An array of all child connections, if known. This property may be
|
||||
* null or undefined if children have not been queried, and thus the
|
||||
* child connections are unknown.
|
||||
*
|
||||
* @type Connection[]
|
||||
*/
|
||||
this.childConnections = template.childConnections;
|
||||
|
||||
/**
|
||||
* An array of all child connection groups, if known. This property may
|
||||
* be null or undefined if children have not been queried, and thus the
|
||||
* child connection groups are unknown.
|
||||
*
|
||||
* @type ConnectionGroup[]
|
||||
*/
|
||||
this.childConnectionGroups = template.childConnectionGroups;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* The reserved identifier which always represents the root connection
|
||||
* group.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
ConnectionGroup.ROOT_IDENTIFIER = "ROOT";
|
||||
|
||||
/**
|
||||
* All valid connection group types.
|
||||
*/
|
||||
ConnectionGroup.Type = {
|
||||
|
||||
/**
|
||||
* The type string associated with balancing connection groups.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
BALANCING : "BALANCING",
|
||||
|
||||
/**
|
||||
* The type string associated with organizational connection groups.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
ORGANIZATIONAL : "ORGANIZATIONAL"
|
||||
|
||||
};
|
||||
|
||||
return ConnectionGroup;
|
||||
|
||||
}]);
|
@@ -23,7 +23,7 @@
|
||||
/**
|
||||
* Service which defines the ConnectionHistoryEntry class.
|
||||
*/
|
||||
angular.module('connection').factory('ConnectionHistoryEntry', [function defineConnectionHistoryEntry() {
|
||||
angular.module('rest').factory('ConnectionHistoryEntry', [function defineConnectionHistoryEntry() {
|
||||
|
||||
/**
|
||||
* The object returned by REST API calls when representing the data
|
94
guacamole/src/main/webapp/app/rest/types/PermissionPatch.js
Normal file
94
guacamole/src/main/webapp/app/rest/types/PermissionPatch.js
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service which defines the PermissionPatch class.
|
||||
*/
|
||||
angular.module('rest').factory('PermissionPatch', [function definePermissionPatch() {
|
||||
|
||||
/**
|
||||
* The object returned by REST API calls when representing changes to the
|
||||
* permissions granted to a specific user.
|
||||
*
|
||||
* @constructor
|
||||
* @param {PermissionPatch|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* PermissionPatch.
|
||||
*/
|
||||
var PermissionPatch = function PermissionPatch(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The operation to apply to the permissions indicated by the path.
|
||||
* Valid operation values are defined within PermissionPatch.Operation.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.op = template.op;
|
||||
|
||||
/**
|
||||
* The path of the permissions to modify. Depending on the type of the
|
||||
* permission, this will be either "/connectionPermissions/ID",
|
||||
* "/connectionGroupPermissions/ID", "/userPermissions/ID", or
|
||||
* "/systemPermissions", where "ID" is the identifier of the object
|
||||
* to which the permissions apply, if any.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.path = template.path;
|
||||
|
||||
/**
|
||||
* The permissions being added or removed. If the permission applies to
|
||||
* an object, such as a connection or connection group, this will be a
|
||||
* value from PermissionSet.ObjectPermissionType. If the permission
|
||||
* applies to the system as a whole (the path is "/systemPermissions"),
|
||||
* this will be a value from PermissionSet.SystemPermissionType.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.value = template.value;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* All valid patch operations for permissions. Currently, only add and
|
||||
* remove are supported.
|
||||
*/
|
||||
PermissionPatch.Operation = {
|
||||
|
||||
/**
|
||||
* Adds (grants) the specified permission.
|
||||
*/
|
||||
ADD : "add",
|
||||
|
||||
/**
|
||||
* Removes (revokes) the specified permission.
|
||||
*/
|
||||
REMOVE : "remove"
|
||||
|
||||
};
|
||||
|
||||
return PermissionPatch;
|
||||
|
||||
}]);
|
280
guacamole/src/main/webapp/app/rest/types/PermissionSet.js
Normal file
280
guacamole/src/main/webapp/app/rest/types/PermissionSet.js
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service which defines the PermissionSet class.
|
||||
*/
|
||||
angular.module('rest').factory('PermissionSet', [function definePermissionSet() {
|
||||
|
||||
/**
|
||||
* The object returned by REST API calls when representing the permissions
|
||||
* granted to a specific user.
|
||||
*
|
||||
* @constructor
|
||||
* @param {PermissionSet|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* PermissionSet.
|
||||
*/
|
||||
var PermissionSet = function PermissionSet(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* Map of connection identifiers to the corresponding array of granted
|
||||
* permissions. Each permission is represented by a string listed
|
||||
* within PermissionSet.ObjectPermissionType.
|
||||
*
|
||||
* @type Object.<String, String[]>
|
||||
*/
|
||||
this.connectionPermissions = template.connectionPermissions || {};
|
||||
|
||||
/**
|
||||
* Map of connection group identifiers to the corresponding array of
|
||||
* granted permissions. Each permission is represented by a string
|
||||
* listed within PermissionSet.ObjectPermissionType.
|
||||
*
|
||||
* @type Object.<String, String[]>
|
||||
*/
|
||||
this.connectionGroupPermissions = template.connectionGroupPermissions || {};
|
||||
|
||||
/**
|
||||
* Map of user identifiers to the corresponding array of granted
|
||||
* permissions. Each permission is represented by a string listed
|
||||
* within PermissionSet.ObjectPermissionType.
|
||||
*
|
||||
* @type Object.<String, String[]>
|
||||
*/
|
||||
this.userPermissions = template.userPermissions || {};
|
||||
|
||||
/**
|
||||
* Array of granted system permissions. Each permission is represented
|
||||
* by a string listed within PermissionSet.SystemPermissionType.
|
||||
*
|
||||
* @type String[]
|
||||
*/
|
||||
this.systemPermissions = template.systemPermissions || [];
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Valid object permission type strings.
|
||||
*/
|
||||
PermissionSet.ObjectPermissionType = {
|
||||
|
||||
/**
|
||||
* Permission to read from the specified object.
|
||||
*/
|
||||
READ : "READ",
|
||||
|
||||
/**
|
||||
* Permission to update the specified object.
|
||||
*/
|
||||
UPDATE : "UPDATE",
|
||||
|
||||
/**
|
||||
* Permission to delete the specified object.
|
||||
*/
|
||||
DELETE : "DELETE",
|
||||
|
||||
/**
|
||||
* Permission to administer the specified object
|
||||
*/
|
||||
ADMINISTER : "ADMINISTER"
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Valid system permission type strings.
|
||||
*/
|
||||
PermissionSet.SystemPermissionType = {
|
||||
|
||||
/**
|
||||
* Permission to administer the entire system.
|
||||
*/
|
||||
ADMINISTER : "ADMINISTER",
|
||||
|
||||
/**
|
||||
* Permission to create new users.
|
||||
*/
|
||||
CREATE_USER : "CREATE_USER",
|
||||
|
||||
/**
|
||||
* Permission to create new connections.
|
||||
*/
|
||||
CREATE_CONNECTION : "CREATE_CONNECTION",
|
||||
|
||||
/**
|
||||
* Permission to create new connection groups.
|
||||
*/
|
||||
CREATE_CONNECTION_GROUP : "CREATE_CONNECTION_GROUP"
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the given permission is granted for at least one
|
||||
* arbitrary object, regardless of ID.
|
||||
*
|
||||
* @param {Object.<String, String[]>} permMap
|
||||
* The permission map to check, where each entry maps an object
|
||||
* identifer to the array of granted permissions.
|
||||
*
|
||||
* @param {String} type
|
||||
* The permission to search for, as defined by
|
||||
* PermissionSet.ObjectPermissionType.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the permission is present (granted), false otherwise.
|
||||
*/
|
||||
var containsPermission = function containsPermission(permMap, type) {
|
||||
|
||||
// Search all identifiers for given permission
|
||||
for (var identifier in permMap) {
|
||||
|
||||
// If permission is granted, then no further searching is necessary
|
||||
if (permMap[identifier].indexOf(type) !== -1)
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// No such permission exists
|
||||
return false;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the given permission is granted for the arbitrary
|
||||
* object having the given ID. If no ID is given, this function determines
|
||||
* whether the permission is granted at all for any such arbitrary object.
|
||||
*
|
||||
* @param {Object.<String, String[]>} permMap
|
||||
* The permission map to check, where each entry maps an object
|
||||
* identifer to the array of granted permissions.
|
||||
*
|
||||
* @param {String} type
|
||||
* The permission to search for, as defined by
|
||||
* PermissionSet.ObjectPermissionType.
|
||||
*
|
||||
* @param {String} [identifier]
|
||||
* The identifier of the object to which the permission applies.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the permission is present (granted), false otherwise.
|
||||
*/
|
||||
var hasPermission = function hasPermission(permMap, type, identifier) {
|
||||
|
||||
// If no identifier given, search ignoring the identifier
|
||||
if (!identifier)
|
||||
return containsPermission(permMap, type);
|
||||
|
||||
// If identifier not present at all, there are no such permissions
|
||||
if (!(identifier in permMap))
|
||||
return false;
|
||||
|
||||
return permMap[identifier].indexOf(type) !== -1;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the given permission is granted for the connection
|
||||
* having the given ID.
|
||||
*
|
||||
* @param {PermissionSet|Object} permSet
|
||||
* The permission set to check.
|
||||
*
|
||||
* @param {String} type
|
||||
* The permission to search for, as defined by
|
||||
* PermissionSet.ObjectPermissionType.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the connection to which the permission applies.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the permission is present (granted), false otherwise.
|
||||
*/
|
||||
PermissionSet.hasConnectionPermission = function hasConnectionPermission(permSet, type, identifier) {
|
||||
return hasPermission(permSet.connectionPermissions, type, identifier);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the given permission is granted for the connection group
|
||||
* having the given ID.
|
||||
*
|
||||
* @param {PermissionSet|Object} permSet
|
||||
* The permission set to check.
|
||||
*
|
||||
* @param {String} type
|
||||
* The permission to search for, as defined by
|
||||
* PermissionSet.ObjectPermissionType.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the connection group to which the permission
|
||||
* applies.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the permission is present (granted), false otherwise.
|
||||
*/
|
||||
PermissionSet.hasConnectionGroupPermission = function hasConnectionGroupPermission(permSet, type, identifier) {
|
||||
return hasPermission(permSet.connectionGroupPermissions, type, identifier);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the given permission is granted for the user having the
|
||||
* given ID.
|
||||
*
|
||||
* @param {PermissionSet|Object} permSet
|
||||
* The permission set to check.
|
||||
*
|
||||
* @param {String} type
|
||||
* The permission to search for, as defined by
|
||||
* PermissionSet.ObjectPermissionType.
|
||||
*
|
||||
* @param {String} identifier
|
||||
* The identifier of the user to which the permission applies.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the permission is present (granted), false otherwise.
|
||||
*/
|
||||
PermissionSet.hasUserPermission = function hasUserPermission(permSet, type, identifier) {
|
||||
return hasPermission(permSet.userPermissions, type, identifier);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the given permission is granted at the system level.
|
||||
*
|
||||
* @param {PermissionSet|Object} permSet
|
||||
* The permission set to check.
|
||||
*
|
||||
* @param {String} type
|
||||
* The permission to search for, as defined by
|
||||
* PermissionSet.SystemPermissionType.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the permission is present (granted), false otherwise.
|
||||
*/
|
||||
PermissionSet.hasSystemPermission = function hasSystemPermission(permSet, type) {
|
||||
return permSet.systemPermissions.indexOf(type) !== -1;
|
||||
};
|
||||
|
||||
return PermissionSet;
|
||||
|
||||
}]);
|
@@ -21,37 +21,49 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* A service for performing useful user related functionaltiy.
|
||||
* Service which defines the Protocol class.
|
||||
*/
|
||||
angular.module('user').factory('userService', ['$injector', function userService($injector) {
|
||||
angular.module('rest').factory('Protocol', [function defineProtocol() {
|
||||
|
||||
var permissionCheckService = $injector.get('permissionCheckService');
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Filters the list of users using the provided permissions.
|
||||
* The object returned by REST API calls when representing the data
|
||||
* associated with a supported remote desktop protocol.
|
||||
*
|
||||
* @param {array} users The user list.
|
||||
*
|
||||
* @param {object} permissionList The list of permissions to use
|
||||
* when filtering.
|
||||
*
|
||||
* @param {object} permissionCriteria The required permission for each user.
|
||||
*
|
||||
* @return {array} The filtered list.
|
||||
* @constructor
|
||||
* @param {Protocol|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* Protocol.
|
||||
*/
|
||||
service.filterUsersByPermission = function filterUsersByPermission(users, permissionList, permissionCriteria) {
|
||||
for(var i = 0; i < users.length; i++) {
|
||||
if(!permissionCheckService.checkPermission(permissionList,
|
||||
"USER", user.username, permissionCriteria)) {
|
||||
items.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return users;
|
||||
var Protocol = function Protocol(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The name which uniquely identifies this protocol.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.name = template.name;
|
||||
|
||||
/**
|
||||
* A human-readable name for this protocol.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.title = template.title;
|
||||
|
||||
/**
|
||||
* An array of all known parameters for this protocol, their types,
|
||||
* and other information.
|
||||
*
|
||||
* @type ProtocolParameter[]
|
||||
* @default []
|
||||
*/
|
||||
this.parameters = template.parameters || [];
|
||||
|
||||
};
|
||||
|
||||
return service;
|
||||
}]);
|
||||
|
||||
return Protocol;
|
||||
|
||||
}]);
|
152
guacamole/src/main/webapp/app/rest/types/ProtocolParameter.js
Normal file
152
guacamole/src/main/webapp/app/rest/types/ProtocolParameter.js
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service which defines the ProtocolParameter class.
|
||||
*/
|
||||
angular.module('rest').factory('ProtocolParameter', [function defineProtocolParameter() {
|
||||
|
||||
/**
|
||||
* The object returned by REST API calls when representing the data
|
||||
* associated with a configuration parameter of a remote desktop protocol.
|
||||
*
|
||||
* @constructor
|
||||
* @param {ProtocolParameter|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* ProtocolParameter.
|
||||
*/
|
||||
var ProtocolParameter = function ProtocolParameter(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The name which uniquely identifies this parameter.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.name = template.name;
|
||||
|
||||
/**
|
||||
* A human-readable name for this parameter.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.title = template.title;
|
||||
|
||||
/**
|
||||
* The type string defining which values this parameter may contain,
|
||||
* as well as what properties are applicable. Valid types are listed
|
||||
* within ProtocolParameter.Type.
|
||||
*
|
||||
* @type String
|
||||
* @default ProtocolParameter.Type.TEXT
|
||||
*/
|
||||
this.type = template.type || ProtocolParameter.Type.TEXT;
|
||||
|
||||
/**
|
||||
* The value to set the parameter to, in the case of a BOOLEAN
|
||||
* parameter, to enable that parameter's effect.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.value = template.value;
|
||||
|
||||
/**
|
||||
* All possible legal values for this parameter. This property is only
|
||||
* applicable to ENUM type parameters.
|
||||
*
|
||||
* @type ProtocolParameterOption[]
|
||||
*/
|
||||
this.options = template.options;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* All valid protocol parameter types.
|
||||
*/
|
||||
ProtocolParameter.Type = {
|
||||
|
||||
/**
|
||||
* The type string associated with parameters that may contain a single
|
||||
* line of arbitrary text.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
TEXT : "TEXT",
|
||||
|
||||
/**
|
||||
* The type string associated with parameters that may contain an
|
||||
* arbitrary string, where that string represents the username of the
|
||||
* user authenticating with the remote desktop service.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
USERNAME : "USERNAME",
|
||||
|
||||
/**
|
||||
* The type string associated with parameters that may contain an
|
||||
* arbitrary string, where that string represents the password of the
|
||||
* user authenticating with the remote desktop service.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
PASSWORD : "PASSWORD",
|
||||
|
||||
/**
|
||||
* The type string associated with parameters that may contain only
|
||||
* numeric values.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
NUMERIC : "NUMERIC",
|
||||
|
||||
/**
|
||||
* The type string associated with parameters that may contain only a
|
||||
* single possible value, where that value enables the parameter's
|
||||
* effect.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
BOOLEAN : "BOOLEAN",
|
||||
|
||||
/**
|
||||
* The type string associated with parameters that may contain a
|
||||
* strictly-defined set of possible values.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
ENUM : "ENUM",
|
||||
|
||||
/**
|
||||
* The type string associated with parameters that may contain any
|
||||
* number of lines of arbitrary text.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
MULTILINE : "MULTILINE"
|
||||
|
||||
};
|
||||
|
||||
return ProtocolParameter;
|
||||
|
||||
}]);
|
@@ -20,40 +20,42 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.glyptodon.guacamole.net.basic.rest.user;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.glyptodon.guacamole.GuacamoleException;
|
||||
import org.glyptodon.guacamole.net.auth.Directory;
|
||||
import org.glyptodon.guacamole.net.auth.User;
|
||||
|
||||
/**
|
||||
* A service for performing useful manipulations on REST Users.
|
||||
*
|
||||
* @author James Muehlner
|
||||
* Service which defines the ProtocolParameterOption class.
|
||||
*/
|
||||
public class UserService {
|
||||
|
||||
/**
|
||||
* Converts a user directory to a list of APIUser objects for
|
||||
* exposing with the REST endpoints.
|
||||
*
|
||||
* @param userDirectory The user directory to convert for REST endpoint use.
|
||||
* @return A List of APIUser objects for use with the REST endpoint.
|
||||
* @throws GuacamoleException If an error occurs while converting the
|
||||
* user directory.
|
||||
*/
|
||||
public List<APIUser> convertUserList(Directory<String, User> userDirectory)
|
||||
throws GuacamoleException {
|
||||
|
||||
List<APIUser> restUsers = new ArrayList<APIUser>();
|
||||
|
||||
for(String username : userDirectory.getIdentifiers())
|
||||
restUsers.add(new APIUser(userDirectory.get(username)));
|
||||
angular.module('rest').factory('ProtocolParameterOption', [function defineProtocolParameterOption() {
|
||||
|
||||
return restUsers;
|
||||
/**
|
||||
* The object returned by REST API calls when representing a single possible
|
||||
* legal value of a configuration parameter of a remote desktop protocol.
|
||||
*
|
||||
* @constructor
|
||||
* @param {ProtocolParameterOption|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* ProtocolParameterOption.
|
||||
*/
|
||||
var ProtocolParameterOption = function ProtocolParameterOption(template) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* A human-readable name for this parameter value.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.title = template.title;
|
||||
|
||||
/**
|
||||
* The actual value to set the parameter to, if this option is
|
||||
* selected.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.value = template.value;
|
||||
|
||||
};
|
||||
|
||||
return ProtocolParameterOption;
|
||||
|
||||
}]);
|
@@ -21,6 +21,43 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* The module for code relating to connections.
|
||||
* Service which defines the User class.
|
||||
*/
|
||||
angular.module('connection', ['auth']);
|
||||
angular.module('rest').factory('User', [function defineUser() {
|
||||
|
||||
/**
|
||||
* The object returned by REST API calls when representing the data
|
||||
* associated with a user.
|
||||
*
|
||||
* @constructor
|
||||
* @param {User|Object} [template={}]
|
||||
* The object whose properties should be copied within the new
|
||||
* User.
|
||||
*/
|
||||
var User = function User(template) {
|
||||
|
||||
// Use empty object by default
|
||||
template = template || {};
|
||||
|
||||
/**
|
||||
* The name which uniquely identifies this user.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.username = template.username;
|
||||
|
||||
/**
|
||||
* This user's password. Note that the REST API may not populate this
|
||||
* property for the sake of security. In most cases, it's not even
|
||||
* possible for the authentication layer to retrieve the user's true
|
||||
* password.
|
||||
*
|
||||
* @type String
|
||||
*/
|
||||
this.password = template.password;
|
||||
|
||||
};
|
||||
|
||||
return User;
|
||||
|
||||
}]);
|
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The DAO for connection operations agains the REST API.
|
||||
*/
|
||||
angular.module('user').factory('userDAO', ['$http', 'authenticationService',
|
||||
function userDAO($http, authenticationService) {
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the list of users,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.getUsers = function getUsers() {
|
||||
return $http.get("api/user?token=" + authenticationService.getCurrentToken());
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to get the list of users,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {string} userID The ID of the user to retrieve.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.getUser = function getUser(userID) {
|
||||
return $http.get("api/user/" + userID + "/?token=" + authenticationService.getCurrentToken());
|
||||
};
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to delete a user,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {object} user The user to delete.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.deleteUser = function deleteUser(user) {
|
||||
return $http['delete'](
|
||||
"api/user/" + user.username +
|
||||
"?token=" + authenticationService.getCurrentToken());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to create a user,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {object} user The user to create.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.createUser = function createUser(user) {
|
||||
return $http.post(
|
||||
"api/user/"
|
||||
+ "?token=" + authenticationService.getCurrentToken(),
|
||||
user
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a request to the REST API to save a user,
|
||||
* returning a promise that can be used for processing the results of the call.
|
||||
*
|
||||
* @param {object} user The user to update.
|
||||
*
|
||||
* @returns {promise} A promise for the HTTP call.
|
||||
*/
|
||||
service.saveUser = function saveUser(user) {
|
||||
return $http.post(
|
||||
"api/user/" + user.username +
|
||||
"?token=" + authenticationService.getCurrentToken(),
|
||||
user);
|
||||
};
|
||||
|
||||
return service;
|
||||
}]);
|
@@ -48,7 +48,7 @@ THE SOFTWARE.
|
||||
<div id="notificationArea">
|
||||
<div ng-repeat="wrapper in notifications">
|
||||
<guac-notification notification="wrapper.notification"/>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="guacamole.min.js"></script>
|
||||
|
Reference in New Issue
Block a user