mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 13:17:41 +00:00
GUACAMOLE-5: Merge REST resource refactor.
This commit is contained in:
@@ -290,6 +290,11 @@
|
|||||||
<artifactId>guice</artifactId>
|
<artifactId>guice</artifactId>
|
||||||
<version>3.0</version>
|
<version>3.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.inject.extensions</groupId>
|
||||||
|
<artifactId>guice-assistedinject</artifactId>
|
||||||
|
<version>3.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Guice Servlet -->
|
<!-- Guice Servlet -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@@ -26,6 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import org.apache.guacamole.environment.Environment;
|
import org.apache.guacamole.environment.Environment;
|
||||||
import org.apache.guacamole.net.GuacamoleTunnel;
|
import org.apache.guacamole.net.GuacamoleTunnel;
|
||||||
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
import org.apache.guacamole.tunnel.StreamInterceptingTunnel;
|
import org.apache.guacamole.tunnel.StreamInterceptingTunnel;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -126,6 +127,44 @@ public class GuacamoleSession {
|
|||||||
return Collections.unmodifiableList(userContexts);
|
return Collections.unmodifiableList(userContexts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the UserContext associated with this session that originated
|
||||||
|
* from the AuthenticationProvider with the given identifier. If no such
|
||||||
|
* UserContext exists, an exception is thrown.
|
||||||
|
*
|
||||||
|
* @param authProviderIdentifier
|
||||||
|
* The unique identifier of the AuthenticationProvider that created the
|
||||||
|
* UserContext being retrieved.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The UserContext that was created by the AuthenticationProvider
|
||||||
|
* having the given identifier.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If no such UserContext exists.
|
||||||
|
*/
|
||||||
|
public UserContext getUserContext(String authProviderIdentifier)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Locate and return the UserContext associated with the
|
||||||
|
// AuthenticationProvider having the given identifier, if any
|
||||||
|
for (UserContext userContext : getUserContexts()) {
|
||||||
|
|
||||||
|
// Get AuthenticationProvider associated with current UserContext
|
||||||
|
AuthenticationProvider authProvider = userContext.getAuthenticationProvider();
|
||||||
|
|
||||||
|
// If AuthenticationProvider identifier matches, done
|
||||||
|
if (authProvider.getIdentifier().equals(authProviderIdentifier))
|
||||||
|
return userContext;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new GuacamoleResourceNotFoundException("Session not associated "
|
||||||
|
+ "with authentication provider \"" + authProviderIdentifier + "\".");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces all UserContexts associated with this session with the given
|
* Replaces all UserContexts associated with this session with the given
|
||||||
* List of UserContexts.
|
* List of UserContexts.
|
||||||
|
@@ -21,6 +21,7 @@ package org.apache.guacamole.rest;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import javax.ws.rs.WebApplicationException;
|
import javax.ws.rs.WebApplicationException;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import org.apache.guacamole.form.Field;
|
import org.apache.guacamole.form.Field;
|
||||||
import org.apache.guacamole.protocol.GuacamoleStatus;
|
import org.apache.guacamole.protocol.GuacamoleStatus;
|
||||||
@@ -44,7 +45,10 @@ public class APIException extends WebApplicationException {
|
|||||||
* The error that occurred.
|
* The error that occurred.
|
||||||
*/
|
*/
|
||||||
public APIException(APIError error) {
|
public APIException(APIError error) {
|
||||||
super(Response.status(error.getType().getStatus()).entity(error).build());
|
super(Response.status(error.getType().getStatus())
|
||||||
|
.type(MediaType.APPLICATION_JSON)
|
||||||
|
.entity(error)
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,277 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole.rest;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
|
||||||
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
|
||||||
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
|
||||||
import org.apache.guacamole.net.auth.ConnectionGroup;
|
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
|
||||||
import org.apache.guacamole.net.auth.User;
|
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
|
||||||
import org.apache.guacamole.rest.connectiongroup.APIConnectionGroup;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides easy access and automatic error handling for retrieval of objects,
|
|
||||||
* such as users, connections, or connection groups. REST API semantics, such
|
|
||||||
* as the special root connection group identifier, are also handled
|
|
||||||
* automatically.
|
|
||||||
*/
|
|
||||||
public class ObjectRetrievalService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a single UserContext from the given GuacamoleSession, which
|
|
||||||
* may contain multiple UserContexts.
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* The GuacamoleSession to retrieve the UserContext from.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider that created the
|
|
||||||
* UserContext being retrieved. Only one UserContext per User per
|
|
||||||
* AuthenticationProvider can exist.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The UserContext that was created by the AuthenticationProvider
|
|
||||||
* having the given identifier.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving the UserContext, or if the
|
|
||||||
* UserContext does not exist.
|
|
||||||
*/
|
|
||||||
public UserContext retrieveUserContext(GuacamoleSession session,
|
|
||||||
String authProviderIdentifier) throws GuacamoleException {
|
|
||||||
|
|
||||||
// Get list of UserContexts
|
|
||||||
List<UserContext> userContexts = session.getUserContexts();
|
|
||||||
|
|
||||||
// Locate and return the UserContext associated with the
|
|
||||||
// AuthenticationProvider having the given identifier, if any
|
|
||||||
for (UserContext userContext : userContexts) {
|
|
||||||
|
|
||||||
// Get AuthenticationProvider associated with current UserContext
|
|
||||||
AuthenticationProvider authProvider = userContext.getAuthenticationProvider();
|
|
||||||
|
|
||||||
// If AuthenticationProvider identifier matches, done
|
|
||||||
if (authProvider.getIdentifier().equals(authProviderIdentifier))
|
|
||||||
return userContext;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new GuacamoleResourceNotFoundException("Session not associated with authentication provider \"" + authProviderIdentifier + "\".");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a single user from the given user context.
|
|
||||||
*
|
|
||||||
* @param userContext
|
|
||||||
* The user context to retrieve the user from.
|
|
||||||
*
|
|
||||||
* @param identifier
|
|
||||||
* The identifier of the user to retrieve.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The user having the given identifier.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving the user, or if the
|
|
||||||
* user does not exist.
|
|
||||||
*/
|
|
||||||
public User retrieveUser(UserContext userContext,
|
|
||||||
String identifier) throws GuacamoleException {
|
|
||||||
|
|
||||||
// Get user directory
|
|
||||||
Directory<User> directory = userContext.getUserDirectory();
|
|
||||||
|
|
||||||
// Pull specified user
|
|
||||||
User user = directory.get(identifier);
|
|
||||||
if (user == null)
|
|
||||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + identifier + "\"");
|
|
||||||
|
|
||||||
return user;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a single user from the given GuacamoleSession.
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* The GuacamoleSession to retrieve the user from.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider that created the
|
|
||||||
* UserContext from which the user should be retrieved. Only one
|
|
||||||
* UserContext per User per AuthenticationProvider can exist.
|
|
||||||
*
|
|
||||||
* @param identifier
|
|
||||||
* The identifier of the user to retrieve.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The user having the given identifier.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving the user, or if the
|
|
||||||
* user does not exist.
|
|
||||||
*/
|
|
||||||
public User retrieveUser(GuacamoleSession session, String authProviderIdentifier,
|
|
||||||
String identifier) throws GuacamoleException {
|
|
||||||
|
|
||||||
UserContext userContext = retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
return retrieveUser(userContext, identifier);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a single connection from the given user context.
|
|
||||||
*
|
|
||||||
* @param userContext
|
|
||||||
* The user context to retrieve the connection from.
|
|
||||||
*
|
|
||||||
* @param identifier
|
|
||||||
* The identifier of the connection to retrieve.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The connection having the given identifier.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving the connection, or if the
|
|
||||||
* connection does not exist.
|
|
||||||
*/
|
|
||||||
public Connection retrieveConnection(UserContext userContext,
|
|
||||||
String identifier) throws GuacamoleException {
|
|
||||||
|
|
||||||
// Get connection directory
|
|
||||||
Directory<Connection> directory = userContext.getConnectionDirectory();
|
|
||||||
|
|
||||||
// Pull specified connection
|
|
||||||
Connection connection = directory.get(identifier);
|
|
||||||
if (connection == null)
|
|
||||||
throw new GuacamoleResourceNotFoundException("No such connection: \"" + identifier + "\"");
|
|
||||||
|
|
||||||
return connection;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a single connection from the given GuacamoleSession.
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* The GuacamoleSession to retrieve the connection from.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider that created the
|
|
||||||
* UserContext from which the connection should be retrieved. Only one
|
|
||||||
* UserContext per User per AuthenticationProvider can exist.
|
|
||||||
*
|
|
||||||
* @param identifier
|
|
||||||
* The identifier of the connection to retrieve.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The connection having the given identifier.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving the connection, or if the
|
|
||||||
* connection does not exist.
|
|
||||||
*/
|
|
||||||
public Connection retrieveConnection(GuacamoleSession session,
|
|
||||||
String authProviderIdentifier, String identifier)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
UserContext userContext = retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
return retrieveConnection(userContext, identifier);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a single connection group from the given user context. If
|
|
||||||
* the given identifier the REST API root identifier, the root connection
|
|
||||||
* group will be returned. The underlying authentication provider may
|
|
||||||
* additionally use a different identifier for root.
|
|
||||||
*
|
|
||||||
* @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 the root identifier.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving the connection group, or if the
|
|
||||||
* connection group does not exist.
|
|
||||||
*/
|
|
||||||
public ConnectionGroup retrieveConnectionGroup(UserContext userContext,
|
|
||||||
String identifier) throws GuacamoleException {
|
|
||||||
|
|
||||||
// Use root group if identifier is the standard root identifier
|
|
||||||
if (identifier != null && identifier.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
|
||||||
return userContext.getRootConnectionGroup();
|
|
||||||
|
|
||||||
// Pull specified connection group otherwise
|
|
||||||
Directory<ConnectionGroup> directory = userContext.getConnectionGroupDirectory();
|
|
||||||
ConnectionGroup connectionGroup = directory.get(identifier);
|
|
||||||
|
|
||||||
if (connectionGroup == null)
|
|
||||||
throw new GuacamoleResourceNotFoundException("No such connection group: \"" + identifier + "\"");
|
|
||||||
|
|
||||||
return connectionGroup;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a single connection group from the given GuacamoleSession. If
|
|
||||||
* the given identifier is the REST API root identifier, the root
|
|
||||||
* connection group will be returned. The underlying authentication
|
|
||||||
* provider may additionally use a different identifier for root.
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* The GuacamoleSession to retrieve the connection group from.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider that created the
|
|
||||||
* UserContext from which the connection group should be retrieved.
|
|
||||||
* Only one UserContext per User per AuthenticationProvider can exist.
|
|
||||||
*
|
|
||||||
* @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 the root identifier.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving the connection group, or if the
|
|
||||||
* connection group does not exist.
|
|
||||||
*/
|
|
||||||
public ConnectionGroup retrieveConnectionGroup(GuacamoleSession session,
|
|
||||||
String authProviderIdentifier, String identifier) throws GuacamoleException {
|
|
||||||
|
|
||||||
UserContext userContext = retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
return retrieveConnectionGroup(userContext, identifier);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -23,6 +23,7 @@ import com.google.inject.matcher.AbstractMatcher;
|
|||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import javax.ws.rs.HttpMethod;
|
import javax.ws.rs.HttpMethod;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +68,7 @@ public class RESTMethodMatcher extends AbstractMatcher<Method> {
|
|||||||
/**
|
/**
|
||||||
* Returns whether the given method is annotated as a REST method. A REST
|
* Returns whether the given method is annotated as a REST method. A REST
|
||||||
* method is annotated with an annotation which is annotated with
|
* method is annotated with an annotation which is annotated with
|
||||||
* <code>@HttpMethod</code>.
|
* <code>@HttpMethod</code> or <code>@Path</code>.
|
||||||
*
|
*
|
||||||
* @param method
|
* @param method
|
||||||
* The method to test.
|
* The method to test.
|
||||||
@@ -86,9 +87,32 @@ public class RESTMethodMatcher extends AbstractMatcher<Method> {
|
|||||||
if (annotationType.isAnnotationPresent(HttpMethod.class))
|
if (annotationType.isAnnotationPresent(HttpMethod.class))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// A method is a REST method if it is annotated with @Path
|
||||||
|
if (Path.class.isAssignableFrom(annotationType))
|
||||||
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The method is not an HTTP method
|
// A method is also REST method if it overrides a REST method within
|
||||||
|
// the superclass
|
||||||
|
Class<?> superclass = method.getDeclaringClass().getSuperclass();
|
||||||
|
if (superclass != null) {
|
||||||
|
|
||||||
|
// Recheck against identical method within superclass
|
||||||
|
try {
|
||||||
|
return isRESTMethod(superclass.getMethod(method.getName(),
|
||||||
|
method.getParameterTypes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no such method, then this method cannot possibly be
|
||||||
|
// a REST method
|
||||||
|
catch (NoSuchMethodException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lacking a superclass, the search stops here - it's not a REST method
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -19,26 +19,27 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.rest;
|
package org.apache.guacamole.rest;
|
||||||
|
|
||||||
|
import org.apache.guacamole.rest.session.UserContextResourceFactory;
|
||||||
|
import org.apache.guacamole.rest.session.SessionRESTService;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
import com.google.inject.matcher.Matchers;
|
import com.google.inject.matcher.Matchers;
|
||||||
import com.google.inject.servlet.ServletModule;
|
import com.google.inject.servlet.ServletModule;
|
||||||
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
|
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
|
import org.apache.guacamole.rest.activeconnection.ActiveConnectionModule;
|
||||||
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
|
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
|
||||||
import org.apache.guacamole.rest.auth.TokenRESTService;
|
import org.apache.guacamole.rest.auth.TokenRESTService;
|
||||||
import org.apache.guacamole.rest.connection.ConnectionRESTService;
|
|
||||||
import org.apache.guacamole.rest.connectiongroup.ConnectionGroupRESTService;
|
|
||||||
import org.apache.guacamole.rest.activeconnection.ActiveConnectionRESTService;
|
|
||||||
import org.apache.guacamole.rest.auth.AuthTokenGenerator;
|
import org.apache.guacamole.rest.auth.AuthTokenGenerator;
|
||||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
import org.apache.guacamole.rest.auth.AuthenticationService;
|
||||||
import org.apache.guacamole.rest.auth.SecureRandomAuthTokenGenerator;
|
import org.apache.guacamole.rest.auth.SecureRandomAuthTokenGenerator;
|
||||||
import org.apache.guacamole.rest.auth.TokenSessionMap;
|
import org.apache.guacamole.rest.auth.TokenSessionMap;
|
||||||
import org.apache.guacamole.rest.history.HistoryRESTService;
|
import org.apache.guacamole.rest.connection.ConnectionModule;
|
||||||
|
import org.apache.guacamole.rest.connectiongroup.ConnectionGroupModule;
|
||||||
import org.apache.guacamole.rest.language.LanguageRESTService;
|
import org.apache.guacamole.rest.language.LanguageRESTService;
|
||||||
import org.apache.guacamole.rest.patch.PatchRESTService;
|
import org.apache.guacamole.rest.patch.PatchRESTService;
|
||||||
import org.apache.guacamole.rest.schema.SchemaRESTService;
|
import org.apache.guacamole.rest.session.SessionResourceFactory;
|
||||||
import org.apache.guacamole.rest.tunnel.TunnelRESTService;
|
import org.apache.guacamole.rest.user.UserModule;
|
||||||
import org.apache.guacamole.rest.user.UserRESTService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Guice Module to set up the servlet mappings and authentication-specific
|
* A Guice Module to set up the servlet mappings and authentication-specific
|
||||||
@@ -81,20 +82,21 @@ public class RESTServiceModule extends ServletModule {
|
|||||||
requestInjection(interceptor);
|
requestInjection(interceptor);
|
||||||
bindInterceptor(Matchers.any(), new RESTMethodMatcher(), interceptor);
|
bindInterceptor(Matchers.any(), new RESTMethodMatcher(), interceptor);
|
||||||
|
|
||||||
// Bind convenience services used by the REST API
|
|
||||||
bind(ObjectRetrievalService.class);
|
|
||||||
|
|
||||||
// Set up the API endpoints
|
// Set up the API endpoints
|
||||||
bind(ActiveConnectionRESTService.class);
|
|
||||||
bind(ConnectionGroupRESTService.class);
|
|
||||||
bind(ConnectionRESTService.class);
|
|
||||||
bind(HistoryRESTService.class);
|
|
||||||
bind(LanguageRESTService.class);
|
bind(LanguageRESTService.class);
|
||||||
bind(PatchRESTService.class);
|
bind(PatchRESTService.class);
|
||||||
bind(SchemaRESTService.class);
|
|
||||||
bind(TokenRESTService.class);
|
bind(TokenRESTService.class);
|
||||||
bind(TunnelRESTService.class);
|
|
||||||
bind(UserRESTService.class);
|
// Root-level resources
|
||||||
|
bind(SessionRESTService.class);
|
||||||
|
install(new FactoryModuleBuilder().build(SessionResourceFactory.class));
|
||||||
|
install(new FactoryModuleBuilder().build(UserContextResourceFactory.class));
|
||||||
|
|
||||||
|
// Resources below root
|
||||||
|
install(new ActiveConnectionModule());
|
||||||
|
install(new ConnectionModule());
|
||||||
|
install(new ConnectionGroupModule());
|
||||||
|
install(new UserModule());
|
||||||
|
|
||||||
// Set up the servlet and JSON mappings
|
// Set up the servlet and JSON mappings
|
||||||
bind(GuiceContainer.class);
|
bind(GuiceContainer.class);
|
||||||
|
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.activeconnection;
|
||||||
|
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryResourceFactory;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
import org.apache.guacamole.net.auth.ActiveConnection;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guice Module which configures injections required for handling
|
||||||
|
* ActiveConnection resources via the REST API.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class ActiveConnectionModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
|
||||||
|
// Create the required DirectoryResourceFactory implementation
|
||||||
|
install(new FactoryModuleBuilder()
|
||||||
|
.build(new TypeLiteral<DirectoryResourceFactory<ActiveConnection, APIActiveConnection>>() {}));
|
||||||
|
|
||||||
|
// Create the required DirectoryObjectResourceFactory implementation
|
||||||
|
install(new FactoryModuleBuilder()
|
||||||
|
.implement(
|
||||||
|
new TypeLiteral<DirectoryObjectResource<ActiveConnection, APIActiveConnection>>() {},
|
||||||
|
ActiveConnectionResource.class
|
||||||
|
)
|
||||||
|
.build(new TypeLiteral<DirectoryObjectResourceFactory<ActiveConnection, APIActiveConnection>>() {}));
|
||||||
|
|
||||||
|
// Bind translator for converting between ActiveConnection and APIActiveConnection
|
||||||
|
bind(new TypeLiteral<DirectoryObjectTranslator<ActiveConnection, APIActiveConnection>>() {})
|
||||||
|
.to(ActiveConnectionObjectTranslator.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.activeconnection;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleUnsupportedException;
|
||||||
|
import org.apache.guacamole.net.auth.ActiveConnection;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translator which converts between ActiveConnection objects and
|
||||||
|
* APIActiveConnection objects. As ActiveConnection objects are read-only, only
|
||||||
|
* toExternalObject() is implemented here.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class ActiveConnectionObjectTranslator
|
||||||
|
implements DirectoryObjectTranslator<ActiveConnection, APIActiveConnection> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public APIActiveConnection toExternalObject(ActiveConnection object)
|
||||||
|
throws GuacamoleException {
|
||||||
|
return new APIActiveConnection(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActiveConnection toInternalObject(APIActiveConnection object)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// ActiveConnection objects are read-only
|
||||||
|
throw new GuacamoleUnsupportedException("Active connection records are read-only.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyExternalChanges(ActiveConnection existingObject,
|
||||||
|
APIActiveConnection object) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Modification not supported for ActiveConnection
|
||||||
|
throw new GuacamoleUnsupportedException("Active connection records are read-only.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,193 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole.rest.activeconnection;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import java.util.Collection;
|
|
||||||
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.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.QueryParam;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import org.apache.guacamole.GuacamoleClientException;
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
|
||||||
import org.apache.guacamole.GuacamoleUnsupportedException;
|
|
||||||
import org.apache.guacamole.net.auth.ActiveConnection;
|
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
|
||||||
import org.apache.guacamole.net.auth.User;
|
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
|
||||||
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
|
||||||
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
|
|
||||||
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
|
||||||
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
|
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
|
||||||
import org.apache.guacamole.rest.APIPatch;
|
|
||||||
import org.apache.guacamole.rest.ObjectRetrievalService;
|
|
||||||
import org.apache.guacamole.rest.PATCH;
|
|
||||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A REST Service for retrieving and managing the tunnels of active connections.
|
|
||||||
*
|
|
||||||
* @author Michael Jumper
|
|
||||||
*/
|
|
||||||
@Path("/data/{dataSource}/activeConnections")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public class ActiveConnectionRESTService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger for this class.
|
|
||||||
*/
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ActiveConnectionRESTService.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A service for authenticating users from auth tokens.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service for convenient retrieval of objects.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private ObjectRetrievalService retrievalService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a list of active connections in the system, filtering the returned
|
|
||||||
* list by the given permissions, if specified.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the active connections to be retrieved.
|
|
||||||
*
|
|
||||||
* @param permissions
|
|
||||||
* The set of permissions to filter with. A user must have one or more
|
|
||||||
* of these permissions for a user to appear in the result.
|
|
||||||
* If null, no filtering will be performed.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* A list of all active connections. If a permission was specified,
|
|
||||||
* this list will contain only those active connections for which the
|
|
||||||
* current user has that permission.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error is encountered while retrieving active connections.
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
public Map<String, APIActiveConnection> getActiveConnections(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@QueryParam("permission") List<ObjectPermission.Type> permissions)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
User self = userContext.self();
|
|
||||||
|
|
||||||
// Do not filter on permissions if no permissions are specified
|
|
||||||
if (permissions != null && permissions.isEmpty())
|
|
||||||
permissions = null;
|
|
||||||
|
|
||||||
// An admin user has access to any connection
|
|
||||||
SystemPermissionSet systemPermissions = self.getSystemPermissions();
|
|
||||||
boolean isAdmin = systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER);
|
|
||||||
|
|
||||||
// Get the directory
|
|
||||||
Directory<ActiveConnection> activeConnectionDirectory = userContext.getActiveConnectionDirectory();
|
|
||||||
|
|
||||||
// Filter connections, if requested
|
|
||||||
Collection<String> activeConnectionIdentifiers = activeConnectionDirectory.getIdentifiers();
|
|
||||||
if (!isAdmin && permissions != null) {
|
|
||||||
ObjectPermissionSet activeConnectionPermissions = self.getActiveConnectionPermissions();
|
|
||||||
activeConnectionIdentifiers = activeConnectionPermissions.getAccessibleObjects(permissions, activeConnectionIdentifiers);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve all active connections , converting to API active connections
|
|
||||||
Map<String, APIActiveConnection> apiActiveConnections = new HashMap<String, APIActiveConnection>();
|
|
||||||
for (ActiveConnection activeConnection : activeConnectionDirectory.getAll(activeConnectionIdentifiers))
|
|
||||||
apiActiveConnections.put(activeConnection.getIdentifier(), new APIActiveConnection(activeConnection));
|
|
||||||
|
|
||||||
return apiActiveConnections;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies the given active connection patches. This operation currently
|
|
||||||
* only supports deletion of active connections through the "remove" patch
|
|
||||||
* operation. Deleting an active connection effectively kills the
|
|
||||||
* connection. The path of each patch operation is of the form "/ID"
|
|
||||||
* where ID is the identifier of the active connection being modified.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the active connections to be deleted.
|
|
||||||
*
|
|
||||||
* @param patches
|
|
||||||
* The active connection patches to apply for this request.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while deleting the active connections.
|
|
||||||
*/
|
|
||||||
@PATCH
|
|
||||||
public void patchTunnels(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
List<APIPatch<String>> patches) throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Get the directory
|
|
||||||
Directory<ActiveConnection> activeConnectionDirectory = userContext.getActiveConnectionDirectory();
|
|
||||||
|
|
||||||
// Close each connection listed for removal
|
|
||||||
for (APIPatch<String> patch : patches) {
|
|
||||||
|
|
||||||
// Only remove is supported
|
|
||||||
if (patch.getOp() != APIPatch.Operation.remove)
|
|
||||||
throw new GuacamoleUnsupportedException("Only the \"remove\" operation is supported when patching active connections.");
|
|
||||||
|
|
||||||
// Retrieve and validate path
|
|
||||||
String path = patch.getPath();
|
|
||||||
if (!path.startsWith("/"))
|
|
||||||
throw new GuacamoleClientException("Patch paths must start with \"/\".");
|
|
||||||
|
|
||||||
// Close connection
|
|
||||||
activeConnectionDirectory.remove(path.substring(1));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.activeconnection;
|
||||||
|
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.net.auth.ActiveConnection;
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which abstracts the operations available on an existing
|
||||||
|
* ActiveConnection.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class ActiveConnectionResource
|
||||||
|
extends DirectoryObjectResource<ActiveConnection, APIActiveConnection> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ActiveConnectionResource which exposes the operations and
|
||||||
|
* subresources available for the given ActiveConnection.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext associated with the given Directory.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The Directory which contains the given ActiveConnection.
|
||||||
|
*
|
||||||
|
* @param connection
|
||||||
|
* The ActiveConnection that this ActiveConnectionResource should
|
||||||
|
* represent.
|
||||||
|
*
|
||||||
|
* @param translator
|
||||||
|
* A DirectoryObjectTranslator implementation which handles
|
||||||
|
* ActiveConnections.
|
||||||
|
*/
|
||||||
|
@AssistedInject
|
||||||
|
public ActiveConnectionResource(@Assisted UserContext userContext,
|
||||||
|
@Assisted Directory<ActiveConnection> directory,
|
||||||
|
@Assisted ActiveConnection connection,
|
||||||
|
DirectoryObjectTranslator<ActiveConnection, APIActiveConnection> translator) {
|
||||||
|
super(directory, connection, translator);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classes related to the manipulation of active connections via the Guacamole
|
||||||
|
* REST API.
|
||||||
|
*/
|
||||||
|
package org.apache.guacamole.rest.activeconnection;
|
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.connection;
|
||||||
|
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryResourceFactory;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guice Module which configures injections required for handling Connection
|
||||||
|
* resources via the REST API.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class ConnectionModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
|
||||||
|
// Create the required DirectoryResourceFactory implementation
|
||||||
|
install(new FactoryModuleBuilder()
|
||||||
|
.build(new TypeLiteral<DirectoryResourceFactory<Connection, APIConnection>>() {}));
|
||||||
|
|
||||||
|
// Create the required DirectoryObjectResourceFactory implementation
|
||||||
|
install(new FactoryModuleBuilder()
|
||||||
|
.implement(
|
||||||
|
new TypeLiteral<DirectoryObjectResource<Connection, APIConnection>>() {},
|
||||||
|
ConnectionResource.class
|
||||||
|
)
|
||||||
|
.build(new TypeLiteral<DirectoryObjectResourceFactory<Connection, APIConnection>>() {}));
|
||||||
|
|
||||||
|
// Bind translator for converting between Connection and APIConnection
|
||||||
|
bind(new TypeLiteral<DirectoryObjectTranslator<Connection, APIConnection>>() {})
|
||||||
|
.to(ConnectionObjectTranslator.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.connection;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
|
import org.apache.guacamole.protocol.GuacamoleConfiguration;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translator which converts between Connection objects and APIConnection
|
||||||
|
* objects.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class ConnectionObjectTranslator
|
||||||
|
implements DirectoryObjectTranslator<Connection, APIConnection> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public APIConnection toExternalObject(Connection object)
|
||||||
|
throws GuacamoleException {
|
||||||
|
return new APIConnection(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Connection toInternalObject(APIConnection object) {
|
||||||
|
return new APIConnectionWrapper(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyExternalChanges(Connection existingObject,
|
||||||
|
APIConnection object) {
|
||||||
|
|
||||||
|
// Build updated configuration
|
||||||
|
GuacamoleConfiguration config = new GuacamoleConfiguration();
|
||||||
|
config.setProtocol(object.getProtocol());
|
||||||
|
config.setParameters(object.getParameters());
|
||||||
|
|
||||||
|
// Update the connection
|
||||||
|
existingObject.setConfiguration(config);
|
||||||
|
existingObject.setParentIdentifier(object.getParentIdentifier());
|
||||||
|
existingObject.setName(object.getName());
|
||||||
|
existingObject.setAttributes(object.getAttributes());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,346 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole.rest.connection;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
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 org.apache.guacamole.GuacamoleClientException;
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
|
||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
|
||||||
import org.apache.guacamole.net.auth.ConnectionRecord;
|
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
|
||||||
import org.apache.guacamole.net.auth.User;
|
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
|
||||||
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
|
||||||
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
|
|
||||||
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
|
||||||
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
|
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
|
||||||
import org.apache.guacamole.rest.ObjectRetrievalService;
|
|
||||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
|
||||||
import org.apache.guacamole.rest.history.APIConnectionRecord;
|
|
||||||
import org.apache.guacamole.protocol.GuacamoleConfiguration;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A REST Service for handling connection CRUD operations.
|
|
||||||
*
|
|
||||||
* @author James Muehlner
|
|
||||||
*/
|
|
||||||
@Path("/data/{dataSource}/connections")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public class ConnectionRESTService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger for this class.
|
|
||||||
*/
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ConnectionRESTService.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A service for authenticating users from auth tokens.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service for convenient retrieval of objects.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private ObjectRetrievalService retrievalService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves an individual connection.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the connection to be retrieved.
|
|
||||||
*
|
|
||||||
* @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}")
|
|
||||||
public APIConnection getConnection(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("connectionID") String connectionID)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
|
|
||||||
// Retrieve the requested connection
|
|
||||||
return new APIConnection(retrievalService.retrieveConnection(session, authProviderIdentifier, connectionID));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the parameters associated with a single connection.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the connection whose parameters are to be
|
|
||||||
* retrieved.
|
|
||||||
*
|
|
||||||
* @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")
|
|
||||||
public Map<String, String> getConnectionParameters(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("connectionID") String connectionID)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
User self = userContext.self();
|
|
||||||
|
|
||||||
// Retrieve permission sets
|
|
||||||
SystemPermissionSet systemPermissions = self.getSystemPermissions();
|
|
||||||
ObjectPermissionSet connectionPermissions = self.getConnectionPermissions();
|
|
||||||
|
|
||||||
// Deny access if adminstrative or update permission is missing
|
|
||||||
if (!systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER)
|
|
||||||
&& !connectionPermissions.hasPermission(ObjectPermission.Type.UPDATE, connectionID))
|
|
||||||
throw new GuacamoleSecurityException("Permission to read connection parameters denied.");
|
|
||||||
|
|
||||||
// Retrieve the requested connection
|
|
||||||
Connection connection = retrievalService.retrieveConnection(userContext, 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 authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the connection whose history is to be
|
|
||||||
* retrieved.
|
|
||||||
*
|
|
||||||
* @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")
|
|
||||||
public List<APIConnectionRecord> getConnectionHistory(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("connectionID") String connectionID)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
|
|
||||||
// Retrieve the requested connection
|
|
||||||
Connection connection = retrievalService.retrieveConnection(session, authProviderIdentifier, connectionID);
|
|
||||||
|
|
||||||
// Retrieve the requested connection's history
|
|
||||||
List<APIConnectionRecord> apiRecords = new ArrayList<APIConnectionRecord>();
|
|
||||||
for (ConnectionRecord record : connection.getHistory())
|
|
||||||
apiRecords.add(new APIConnectionRecord(record));
|
|
||||||
|
|
||||||
// Return the converted history
|
|
||||||
return apiRecords;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes an individual connection.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the connection to be deleted.
|
|
||||||
*
|
|
||||||
* @param connectionID
|
|
||||||
* The identifier of the connection to delete.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while deleting the connection.
|
|
||||||
*/
|
|
||||||
@DELETE
|
|
||||||
@Path("/{connectionID}")
|
|
||||||
public void deleteConnection(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("connectionID") String connectionID)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Get the connection directory
|
|
||||||
Directory<Connection> connectionDirectory = userContext.getConnectionDirectory();
|
|
||||||
|
|
||||||
// Delete the specified connection
|
|
||||||
connectionDirectory.remove(connectionID);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new connection and returns the new connection, with identifier
|
|
||||||
* field populated.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext in which the connection is to be created.
|
|
||||||
*
|
|
||||||
* @param connection
|
|
||||||
* The connection to create.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The new connection.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while creating the connection.
|
|
||||||
*/
|
|
||||||
@POST
|
|
||||||
public APIConnection createConnection(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
APIConnection connection) throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Validate that connection data was provided
|
|
||||||
if (connection == null)
|
|
||||||
throw new GuacamoleClientException("Connection JSON must be submitted when creating connections.");
|
|
||||||
|
|
||||||
// Add the new connection
|
|
||||||
Directory<Connection> connectionDirectory = userContext.getConnectionDirectory();
|
|
||||||
connectionDirectory.add(new APIConnectionWrapper(connection));
|
|
||||||
|
|
||||||
// Return the new connection
|
|
||||||
return 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 authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the connection to be updated.
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*/
|
|
||||||
@PUT
|
|
||||||
@Path("/{connectionID}")
|
|
||||||
public void updateConnection(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("connectionID") String connectionID,
|
|
||||||
APIConnection connection) throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Validate that connection data was provided
|
|
||||||
if (connection == null)
|
|
||||||
throw new GuacamoleClientException("Connection JSON must be submitted when updating connections.");
|
|
||||||
|
|
||||||
// Get the connection directory
|
|
||||||
Directory<Connection> connectionDirectory = userContext.getConnectionDirectory();
|
|
||||||
|
|
||||||
// Retrieve connection to update
|
|
||||||
Connection existingConnection = retrievalService.retrieveConnection(userContext, connectionID);
|
|
||||||
|
|
||||||
// Build updated configuration
|
|
||||||
GuacamoleConfiguration config = new GuacamoleConfiguration();
|
|
||||||
config.setProtocol(connection.getProtocol());
|
|
||||||
config.setParameters(connection.getParameters());
|
|
||||||
|
|
||||||
// Update the connection
|
|
||||||
existingConnection.setConfiguration(config);
|
|
||||||
existingConnection.setParentIdentifier(connection.getParentIdentifier());
|
|
||||||
existingConnection.setName(connection.getName());
|
|
||||||
existingConnection.setAttributes(connection.getAttributes());
|
|
||||||
connectionDirectory.update(existingConnection);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.connection;
|
||||||
|
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
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.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
|
import org.apache.guacamole.net.auth.ConnectionRecord;
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.User;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
||||||
|
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||||
|
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
||||||
|
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
|
||||||
|
import org.apache.guacamole.rest.history.APIConnectionRecord;
|
||||||
|
import org.apache.guacamole.protocol.GuacamoleConfiguration;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which abstracts the operations available on an existing
|
||||||
|
* Connection.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class ConnectionResource extends DirectoryObjectResource<Connection, APIConnection> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UserContext associated with the Directory which contains the
|
||||||
|
* Connection exposed by this resource.
|
||||||
|
*/
|
||||||
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Connection object represented by this ConnectionResource.
|
||||||
|
*/
|
||||||
|
private final Connection connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ConnectionResource which exposes the operations and
|
||||||
|
* subresources available for the given Connection.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext associated with the given Directory.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The Directory which contains the given Connection.
|
||||||
|
*
|
||||||
|
* @param connection
|
||||||
|
* The Connection that this ConnectionResource should represent.
|
||||||
|
*
|
||||||
|
* @param translator
|
||||||
|
* A DirectoryObjectTranslator implementation which handles the type of
|
||||||
|
* object given.
|
||||||
|
*/
|
||||||
|
@AssistedInject
|
||||||
|
public ConnectionResource(@Assisted UserContext userContext,
|
||||||
|
@Assisted Directory<Connection> directory,
|
||||||
|
@Assisted Connection connection,
|
||||||
|
DirectoryObjectTranslator<Connection, APIConnection> translator) {
|
||||||
|
super(directory, connection, translator);
|
||||||
|
this.userContext = userContext;
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the parameters associated with a single connection.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A map of parameter name/value pairs.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving the connection parameters.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("parameters")
|
||||||
|
public Map<String, String> getConnectionParameters()
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
User self = userContext.self();
|
||||||
|
|
||||||
|
// Retrieve permission sets
|
||||||
|
SystemPermissionSet systemPermissions = self.getSystemPermissions();
|
||||||
|
ObjectPermissionSet connectionPermissions = self.getConnectionPermissions();
|
||||||
|
|
||||||
|
// Deny access if adminstrative or update permission is missing
|
||||||
|
String identifier = connection.getIdentifier();
|
||||||
|
if (!systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER)
|
||||||
|
&& !connectionPermissions.hasPermission(ObjectPermission.Type.UPDATE, identifier))
|
||||||
|
throw new GuacamoleSecurityException("Permission to read connection parameters denied.");
|
||||||
|
|
||||||
|
// Retrieve connection configuration
|
||||||
|
GuacamoleConfiguration config = connection.getConfiguration();
|
||||||
|
|
||||||
|
// Return parameter map
|
||||||
|
return config.getParameters();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the usage history of a single 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("history")
|
||||||
|
public List<APIConnectionRecord> getConnectionHistory()
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Retrieve the requested connection's history
|
||||||
|
List<APIConnectionRecord> apiRecords = new ArrayList<APIConnectionRecord>();
|
||||||
|
for (ConnectionRecord record : connection.getHistory())
|
||||||
|
apiRecords.add(new APIConnectionRecord(record));
|
||||||
|
|
||||||
|
// Return the converted history
|
||||||
|
return apiRecords;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.connectiongroup;
|
||||||
|
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which abstracts the operations available on a Directory of
|
||||||
|
* ConnectionGroups.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class ConnectionGroupDirectoryResource
|
||||||
|
extends DirectoryResource<ConnectionGroup, APIConnectionGroup> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UserContext associated with the Directory which contains the
|
||||||
|
* ConnectionGroup exposed by this resource.
|
||||||
|
*/
|
||||||
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Directory exposed by this resource.
|
||||||
|
*/
|
||||||
|
private final Directory<ConnectionGroup> directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory which can be used to create instances of resources representing
|
||||||
|
* ConnectionGroups.
|
||||||
|
*/
|
||||||
|
private final DirectoryObjectResourceFactory<ConnectionGroup, APIConnectionGroup> resourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ConnectionGroupDirectoryResource which exposes the
|
||||||
|
* operations and subresources available for the given ConnectionGroup
|
||||||
|
* Directory.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext associated with the given Directory.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The Directory being exposed.
|
||||||
|
*
|
||||||
|
* @param translator
|
||||||
|
* A DirectoryObjectTranslator implementation which handles
|
||||||
|
* ConnectionGroups.
|
||||||
|
*
|
||||||
|
* @param resourceFactory
|
||||||
|
* A factory which can be used to create instances of resources
|
||||||
|
* representing ConnectionGroups.
|
||||||
|
*/
|
||||||
|
@AssistedInject
|
||||||
|
public ConnectionGroupDirectoryResource(@Assisted UserContext userContext,
|
||||||
|
@Assisted Directory<ConnectionGroup> directory,
|
||||||
|
DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup> translator,
|
||||||
|
DirectoryObjectResourceFactory<ConnectionGroup, APIConnectionGroup> resourceFactory) {
|
||||||
|
super(userContext, directory, translator, resourceFactory);
|
||||||
|
this.userContext = userContext;
|
||||||
|
this.directory = directory;
|
||||||
|
this.resourceFactory = resourceFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DirectoryObjectResource<ConnectionGroup, APIConnectionGroup>
|
||||||
|
getObjectResource(String identifier) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Use root group if identifier is the standard root identifier
|
||||||
|
if (identifier != null && identifier.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||||
|
return resourceFactory.create(userContext, directory,
|
||||||
|
userContext.getRootConnectionGroup());
|
||||||
|
|
||||||
|
return super.getObjectResource(identifier);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.connectiongroup;
|
||||||
|
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryResourceFactory;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guice Module which configures injections required for handling
|
||||||
|
* ConnectionGroup resources via the REST API.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class ConnectionGroupModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
|
||||||
|
// Create the required DirectoryResourceFactory implementation
|
||||||
|
install(new FactoryModuleBuilder()
|
||||||
|
.implement(
|
||||||
|
new TypeLiteral<DirectoryResource<ConnectionGroup, APIConnectionGroup>>() {},
|
||||||
|
ConnectionGroupDirectoryResource.class
|
||||||
|
)
|
||||||
|
.build(new TypeLiteral<DirectoryResourceFactory<ConnectionGroup, APIConnectionGroup>>() {}));
|
||||||
|
|
||||||
|
// Create the required DirectoryObjectResourceFactory implementation
|
||||||
|
install(new FactoryModuleBuilder()
|
||||||
|
.implement(
|
||||||
|
new TypeLiteral<DirectoryObjectResource<ConnectionGroup, APIConnectionGroup>>() {},
|
||||||
|
ConnectionGroupResource.class
|
||||||
|
)
|
||||||
|
.build(new TypeLiteral<DirectoryObjectResourceFactory<ConnectionGroup, APIConnectionGroup>>() {}));
|
||||||
|
|
||||||
|
// Bind translator for converting between ConnectionGroup and APIConnectionGroup
|
||||||
|
bind(new TypeLiteral<DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup>>() {})
|
||||||
|
.to(ConnectionGroupObjectTranslator.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.connectiongroup;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translator which converts between ConnectionGroup objects and
|
||||||
|
* APIConnectionGroup objects.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class ConnectionGroupObjectTranslator
|
||||||
|
implements DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public APIConnectionGroup toExternalObject(ConnectionGroup object)
|
||||||
|
throws GuacamoleException {
|
||||||
|
return new APIConnectionGroup(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConnectionGroup toInternalObject(APIConnectionGroup object) {
|
||||||
|
return new APIConnectionGroupWrapper(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyExternalChanges(ConnectionGroup existingObject,
|
||||||
|
APIConnectionGroup object) {
|
||||||
|
|
||||||
|
// Update the connection group
|
||||||
|
existingObject.setName(object.getName());
|
||||||
|
existingObject.setParentIdentifier(object.getParentIdentifier());
|
||||||
|
existingObject.setType(object.getType());
|
||||||
|
existingObject.setAttributes(object.getAttributes());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,284 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole.rest.connectiongroup;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import java.util.List;
|
|
||||||
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 org.apache.guacamole.GuacamoleClientException;
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
|
||||||
import org.apache.guacamole.net.auth.ConnectionGroup;
|
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
|
||||||
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
|
||||||
import org.apache.guacamole.rest.ObjectRetrievalService;
|
|
||||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A REST Service for handling connection group CRUD operations.
|
|
||||||
*
|
|
||||||
* @author James Muehlner
|
|
||||||
*/
|
|
||||||
@Path("/data/{dataSource}/connectionGroups")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public class ConnectionGroupRESTService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger for this class.
|
|
||||||
*/
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ConnectionGroupRESTService.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A service for authenticating users from auth tokens.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service for convenient retrieval of objects.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private ObjectRetrievalService retrievalService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an individual connection group.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the connection group to be retrieved.
|
|
||||||
*
|
|
||||||
* @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}")
|
|
||||||
public APIConnectionGroup getConnectionGroup(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("connectionGroupID") String connectionGroupID)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
|
|
||||||
// Retrieve the requested connection group
|
|
||||||
return new APIConnectionGroup(retrievalService.retrieveConnectionGroup(session, authProviderIdentifier, connectionGroupID));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an individual connection group and all children.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the connection group to be retrieved.
|
|
||||||
*
|
|
||||||
* @param connectionGroupID
|
|
||||||
* The ID of the connection group to retrieve.
|
|
||||||
*
|
|
||||||
* @param permissions
|
|
||||||
* If specified and non-empty, limit the returned list to only those
|
|
||||||
* connections for which the current user has any of the given
|
|
||||||
* permissions. 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")
|
|
||||||
public APIConnectionGroup getConnectionGroupTree(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("connectionGroupID") String connectionGroupID,
|
|
||||||
@QueryParam("permission") List<ObjectPermission.Type> permissions)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Retrieve the requested tree, filtering by the given permissions
|
|
||||||
ConnectionGroup treeRoot = retrievalService.retrieveConnectionGroup(userContext, connectionGroupID);
|
|
||||||
ConnectionGroupTree tree = new ConnectionGroupTree(userContext, treeRoot, permissions);
|
|
||||||
|
|
||||||
// Return tree as a connection group
|
|
||||||
return tree.getRootAPIConnectionGroup();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes an individual connection group.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the connection group to be deleted.
|
|
||||||
*
|
|
||||||
* @param connectionGroupID
|
|
||||||
* The identifier of the connection group to delete.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while deleting the connection group.
|
|
||||||
*/
|
|
||||||
@DELETE
|
|
||||||
@Path("/{connectionGroupID}")
|
|
||||||
public void deleteConnectionGroup(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("connectionGroupID") String connectionGroupID)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Get the connection group directory
|
|
||||||
Directory<ConnectionGroup> connectionGroupDirectory = userContext.getConnectionGroupDirectory();
|
|
||||||
|
|
||||||
// Delete the connection group
|
|
||||||
connectionGroupDirectory.remove(connectionGroupID);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new connection group and returns the new connection group,
|
|
||||||
* with identifier field populated.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext in which the connection group is to be created.
|
|
||||||
*
|
|
||||||
* @param connectionGroup
|
|
||||||
* The connection group to create.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The new connection group.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while creating the connection group.
|
|
||||||
*/
|
|
||||||
@POST
|
|
||||||
public APIConnectionGroup createConnectionGroup(
|
|
||||||
@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
APIConnectionGroup connectionGroup) throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Validate that connection group data was provided
|
|
||||||
if (connectionGroup == null)
|
|
||||||
throw new GuacamoleClientException("Connection group JSON must be submitted when creating connections groups.");
|
|
||||||
|
|
||||||
// Add the new connection group
|
|
||||||
Directory<ConnectionGroup> connectionGroupDirectory = userContext.getConnectionGroupDirectory();
|
|
||||||
connectionGroupDirectory.add(new APIConnectionGroupWrapper(connectionGroup));
|
|
||||||
|
|
||||||
// Return the new connection group
|
|
||||||
return connectionGroup;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the connection group to be updated.
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*/
|
|
||||||
@PUT
|
|
||||||
@Path("/{connectionGroupID}")
|
|
||||||
public void updateConnectionGroup(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("connectionGroupID") String connectionGroupID,
|
|
||||||
APIConnectionGroup connectionGroup)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Validate that connection group data was provided
|
|
||||||
if (connectionGroup == null)
|
|
||||||
throw new GuacamoleClientException("Connection group JSON must be submitted when updating connection groups.");
|
|
||||||
|
|
||||||
// Get the connection group directory
|
|
||||||
Directory<ConnectionGroup> connectionGroupDirectory = userContext.getConnectionGroupDirectory();
|
|
||||||
|
|
||||||
// Retrieve connection group to update
|
|
||||||
ConnectionGroup existingConnectionGroup = retrievalService.retrieveConnectionGroup(userContext, connectionGroupID);
|
|
||||||
|
|
||||||
// Update the connection group
|
|
||||||
existingConnectionGroup.setName(connectionGroup.getName());
|
|
||||||
existingConnectionGroup.setParentIdentifier(connectionGroup.getParentIdentifier());
|
|
||||||
existingConnectionGroup.setType(connectionGroup.getType());
|
|
||||||
existingConnectionGroup.setAttributes(connectionGroup.getAttributes());
|
|
||||||
connectionGroupDirectory.update(existingConnectionGroup);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.connectiongroup;
|
||||||
|
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
import java.util.List;
|
||||||
|
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.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which abstracts the operations available on an existing
|
||||||
|
* ConnectionGroup.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class ConnectionGroupResource
|
||||||
|
extends DirectoryObjectResource<ConnectionGroup, APIConnectionGroup> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UserContext associated with the Directory which contains the
|
||||||
|
* ConnectionGroup exposed by this resource.
|
||||||
|
*/
|
||||||
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ConnectionGroup object represented by this ConnectionGroupResource.
|
||||||
|
*/
|
||||||
|
private final ConnectionGroup connectionGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ConnectionGroupResource which exposes the operations and
|
||||||
|
* subresources available for the given ConnectionGroup.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext associated with the given Directory.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The Directory which contains the given ConnectionGroup.
|
||||||
|
*
|
||||||
|
* @param connectionGroup
|
||||||
|
* The ConnectionGroup that this ConnectionGroupResource should
|
||||||
|
* represent.
|
||||||
|
*
|
||||||
|
* @param translator
|
||||||
|
* A DirectoryObjectTranslator implementation which handles the type of
|
||||||
|
* object given.
|
||||||
|
*/
|
||||||
|
@AssistedInject
|
||||||
|
public ConnectionGroupResource(@Assisted UserContext userContext,
|
||||||
|
@Assisted Directory<ConnectionGroup> directory,
|
||||||
|
@Assisted ConnectionGroup connectionGroup,
|
||||||
|
DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup> translator) {
|
||||||
|
super(directory, connectionGroup, translator);
|
||||||
|
this.userContext = userContext;
|
||||||
|
this.connectionGroup = connectionGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current connection group along with all descendants.
|
||||||
|
*
|
||||||
|
* @param permissions
|
||||||
|
* If specified and non-empty, limit the returned list to only those
|
||||||
|
* connections for which the current user has any of the given
|
||||||
|
* permissions. Otherwise, all visible connections are returned.
|
||||||
|
* ConnectionGroups are unaffected by this parameter.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The current connection group, including all descendants.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If a problem is encountered while retrieving the connection group or
|
||||||
|
* its descendants.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("tree")
|
||||||
|
public APIConnectionGroup getConnectionGroupTree(
|
||||||
|
@QueryParam("permission") List<ObjectPermission.Type> permissions)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Retrieve the requested tree, filtering by the given permissions
|
||||||
|
ConnectionGroupTree tree = new ConnectionGroupTree(userContext,
|
||||||
|
connectionGroup, permissions);
|
||||||
|
|
||||||
|
// Return tree as a connection group
|
||||||
|
return tree.getRootAPIConnectionGroup();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.directory;
|
||||||
|
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DELETE;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleClientException;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which abstracts the operations available on an existing
|
||||||
|
* Guacamole object that is contained within a Directory, such as modification,
|
||||||
|
* deletion, or individual retrieval.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
* @param <InternalType>
|
||||||
|
* The type of object that this DirectoryObjectResource represents. To
|
||||||
|
* avoid coupling the REST API too tightly to the extension API, these
|
||||||
|
* objects are not directly serialized or deserialized when handling REST
|
||||||
|
* requests.
|
||||||
|
*
|
||||||
|
* @param <ExternalType>
|
||||||
|
* The type of object used in interchange (ie: serialized/deserialized as
|
||||||
|
* JSON) between REST clients and this DirectoryObjectResource to
|
||||||
|
* represent the InternalType.
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class DirectoryObjectResource<InternalType extends Identifiable, ExternalType> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Directory which contains the object represented by this
|
||||||
|
* DirectoryObjectResource.
|
||||||
|
*/
|
||||||
|
private final Directory<InternalType> directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object represented by this DirectoryObjectResource.
|
||||||
|
*/
|
||||||
|
private final InternalType object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A DirectoryObjectTranslator implementation which handles the type of
|
||||||
|
* objects represented by this DirectoryObjectResource.
|
||||||
|
*/
|
||||||
|
private final DirectoryObjectTranslator<InternalType, ExternalType> translator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DirectoryObjectResource which exposes the operations
|
||||||
|
* available for the given object.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The Directory which contains the given object.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
* The object that this DirectoryObjectResource should represent.
|
||||||
|
*
|
||||||
|
* @param translator
|
||||||
|
* A DirectoryObjectTranslator implementation which handles the type of
|
||||||
|
* object given.
|
||||||
|
*/
|
||||||
|
@AssistedInject
|
||||||
|
public DirectoryObjectResource(@Assisted Directory<InternalType> directory,
|
||||||
|
@Assisted InternalType object,
|
||||||
|
DirectoryObjectTranslator<InternalType, ExternalType> translator) {
|
||||||
|
this.directory = directory;
|
||||||
|
this.object = object;
|
||||||
|
this.translator = translator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the object represented by this DirectoryObjectResource, in a
|
||||||
|
* format intended for interchange.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The object that this DirectoryObjectResource represents, in a format
|
||||||
|
* intended for interchange.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error is encountered while retrieving the object.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
public ExternalType getObject() throws GuacamoleException {
|
||||||
|
return translator.toExternalObject(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates an existing object. The changes to be made to the corresponding
|
||||||
|
* object within the directory indicated by the provided data.
|
||||||
|
*
|
||||||
|
* @param modifiedObject
|
||||||
|
* The data to update the corresponding object with.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while updating the object.
|
||||||
|
*/
|
||||||
|
@PUT
|
||||||
|
public void updateObject(ExternalType modifiedObject) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Validate that data was provided
|
||||||
|
if (modifiedObject == null)
|
||||||
|
throw new GuacamoleClientException("Data must be submitted when updating objects.");
|
||||||
|
|
||||||
|
// Perform update
|
||||||
|
translator.applyExternalChanges(object, modifiedObject);
|
||||||
|
directory.update(object);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes this object from the containing directory.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while removing the object.
|
||||||
|
*/
|
||||||
|
@DELETE
|
||||||
|
public void deleteObject() throws GuacamoleException {
|
||||||
|
directory.remove(object.getIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.directory;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory which creates DirectoryObjectResource instances exposing objects of
|
||||||
|
* a particular type.
|
||||||
|
*
|
||||||
|
* @param <InternalType>
|
||||||
|
* The type of object exposed by the DirectoryObjectResource instances
|
||||||
|
* created by this DirectoryResourceFactory.
|
||||||
|
*
|
||||||
|
* @param <ExternalType>
|
||||||
|
* The type of object used in interchange (ie: serialized or deserialized
|
||||||
|
* as JSON) between REST clients and resources when representing the
|
||||||
|
* InternalType.
|
||||||
|
*/
|
||||||
|
public interface DirectoryObjectResourceFactory<InternalType extends Identifiable, ExternalType> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DirectoryObjectResource which exposes the given object.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext which contains the given Directory.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The Directory which contains the object being exposed.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
* The object which should be exposed by the created
|
||||||
|
* DirectoryObjectResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new DirectoryObjectResource which exposes the given object.
|
||||||
|
*/
|
||||||
|
DirectoryObjectResource<InternalType, ExternalType>
|
||||||
|
create(UserContext userContext, Directory<InternalType> directory,
|
||||||
|
InternalType object);
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.directory;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides bidirectional conversion between REST-specific objects and the
|
||||||
|
* internal objects defined by the Guacamole extension API.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
* @param <InternalType>
|
||||||
|
* The type of object converted by this DirectoryObjectTranslator which is
|
||||||
|
* not necessarily intended for use in interchange.
|
||||||
|
*
|
||||||
|
* @param <ExternalType>
|
||||||
|
* The type of object used in interchange (ie: serialized or
|
||||||
|
* deserialized as JSON) between REST clients and resource implementations
|
||||||
|
* when representing the InternalType.
|
||||||
|
*/
|
||||||
|
public interface DirectoryObjectTranslator<InternalType extends Identifiable, ExternalType> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given object to an object which is intended to be used in
|
||||||
|
* interchange.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
* The object to convert for the sake of interchange.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new object containing the same data as the given internal object,
|
||||||
|
* but intended for use in interchange.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the provided object cannot be converted for any reason.
|
||||||
|
*/
|
||||||
|
ExternalType toExternalObject(InternalType object)
|
||||||
|
throws GuacamoleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given object to an object which is intended to be used
|
||||||
|
* within the Guacamole extension API.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
* An object of the type intended for use in interchange, such as that
|
||||||
|
* produced by toExternalObject() or received from a user via REST.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new object containing the same data as the given external object,
|
||||||
|
* but intended for use within the Guacamole extension API.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the provided object cannot be converted for any reason.
|
||||||
|
*/
|
||||||
|
InternalType toInternalObject(ExternalType object)
|
||||||
|
throws GuacamoleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overlays the changes indicated by the given external object, modifying
|
||||||
|
* the given existing object from the Guacamole extension API.
|
||||||
|
*
|
||||||
|
* @param existingObject
|
||||||
|
* The existing object from the Guacamole extension API which should be
|
||||||
|
* modified.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
* The external object representing the modifications to the existing
|
||||||
|
* internal object.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the provided modifications cannot be applied for any reason.
|
||||||
|
*/
|
||||||
|
void applyExternalChanges(InternalType existingObject, ExternalType object)
|
||||||
|
throws GuacamoleException;
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,266 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.directory;
|
||||||
|
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
import java.util.Collection;
|
||||||
|
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 org.apache.guacamole.GuacamoleClientException;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
||||||
|
import org.apache.guacamole.GuacamoleUnsupportedException;
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
|
import org.apache.guacamole.net.auth.User;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
||||||
|
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||||
|
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
||||||
|
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
|
||||||
|
import org.apache.guacamole.rest.APIPatch;
|
||||||
|
import org.apache.guacamole.rest.PATCH;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which abstracts the operations available on all Guacamole
|
||||||
|
* Directory implementations, such as the creation of new objects, or listing
|
||||||
|
* of existing objects. A DirectoryResource functions as the parent of any
|
||||||
|
* number of child DirectoryObjectResources, which are created with the factory
|
||||||
|
* provided at the time of this object's construction.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
* @param <InternalType>
|
||||||
|
* The type of object contained within the Directory that this
|
||||||
|
* DirectoryResource exposes. To avoid coupling the REST API too tightly to
|
||||||
|
* the extension API, these objects are not directly serialized or
|
||||||
|
* deserialized when handling REST requests.
|
||||||
|
*
|
||||||
|
* @param <ExternalType>
|
||||||
|
* The type of object used in interchange (ie: serialized/deserialized as
|
||||||
|
* JSON) between REST clients and this DirectoryResource when representing
|
||||||
|
* the InternalType.
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class DirectoryResource<InternalType extends Identifiable, ExternalType> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UserContext associated with the Directory being exposed by this
|
||||||
|
* DirectoryResource.
|
||||||
|
*/
|
||||||
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Directory being exposed by this DirectoryResource.
|
||||||
|
*/
|
||||||
|
private final Directory<InternalType> directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A DirectoryObjectTranslator implementation which handles the type of
|
||||||
|
* objects contained within the Directory exposed by this DirectoryResource.
|
||||||
|
*/
|
||||||
|
private final DirectoryObjectTranslator<InternalType, ExternalType> translator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory which can be used to create instances of resources representing
|
||||||
|
* individual objects contained within the Directory exposed by this
|
||||||
|
* DirectoryResource.
|
||||||
|
*/
|
||||||
|
private final DirectoryObjectResourceFactory<InternalType, ExternalType> resourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DirectoryResource which exposes the operations available
|
||||||
|
* for the given Directory.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext associated with the given Directory.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The Directory being exposed by this DirectoryResource.
|
||||||
|
*
|
||||||
|
* @param translator
|
||||||
|
* A DirectoryObjectTranslator implementation which handles the type of
|
||||||
|
* objects contained within the given Directory.
|
||||||
|
*
|
||||||
|
* @param resourceFactory
|
||||||
|
* A factory which can be used to create instances of resources
|
||||||
|
* representing individual objects contained within the given Directory.
|
||||||
|
*/
|
||||||
|
@AssistedInject
|
||||||
|
public DirectoryResource(@Assisted UserContext userContext,
|
||||||
|
@Assisted Directory<InternalType> directory,
|
||||||
|
DirectoryObjectTranslator<InternalType, ExternalType> translator,
|
||||||
|
DirectoryObjectResourceFactory<InternalType, ExternalType> resourceFactory) {
|
||||||
|
this.userContext = userContext;
|
||||||
|
this.directory = directory;
|
||||||
|
this.translator = translator;
|
||||||
|
this.resourceFactory = resourceFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a map of all objects available within this DirectoryResource,
|
||||||
|
* filtering the returned map by the given permission, if specified.
|
||||||
|
*
|
||||||
|
* @param permissions
|
||||||
|
* The set of permissions to filter with. A user must have one or more
|
||||||
|
* of these permissions for the affected objects to appear in the
|
||||||
|
* result. If null, no filtering will be performed.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A map of all visible objects. If a permission was specified, this
|
||||||
|
* map will contain only those objects for which the current user has
|
||||||
|
* that permission.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error is encountered while retrieving the objects.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
public Map<String, ExternalType> getObjects(
|
||||||
|
@QueryParam("permission") List<ObjectPermission.Type> permissions)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// An admin user has access to all objects
|
||||||
|
User self = userContext.self();
|
||||||
|
SystemPermissionSet systemPermissions = self.getSystemPermissions();
|
||||||
|
boolean isAdmin = systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER);
|
||||||
|
|
||||||
|
// Filter objects, if requested
|
||||||
|
Collection<String> identifiers = directory.getIdentifiers();
|
||||||
|
if (!isAdmin && permissions != null && !permissions.isEmpty()) {
|
||||||
|
ObjectPermissionSet objectPermissions = self.getUserPermissions();
|
||||||
|
identifiers = objectPermissions.getAccessibleObjects(permissions, identifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Translate each retrieved object into the corresponding external object
|
||||||
|
Map<String, ExternalType> apiObjects = new HashMap<String, ExternalType>();
|
||||||
|
for (InternalType object : directory.getAll(identifiers))
|
||||||
|
apiObjects.put(object.getIdentifier(), translator.toExternalObject(object));
|
||||||
|
|
||||||
|
return apiObjects;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the given object patches, updating the underlying directory
|
||||||
|
* accordingly. This operation currently only supports deletion of objects
|
||||||
|
* through the "remove" patch operation. The path of each patch operation is
|
||||||
|
* of the form "/ID" where ID is the identifier of the object being
|
||||||
|
* modified.
|
||||||
|
*
|
||||||
|
* @param patches
|
||||||
|
* The patches to apply for this request.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while deleting the objects.
|
||||||
|
*/
|
||||||
|
@PATCH
|
||||||
|
public void patchObjects(List<APIPatch<String>> patches)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Apply each operation specified within the patch
|
||||||
|
for (APIPatch<String> patch : patches) {
|
||||||
|
|
||||||
|
// Only remove is supported
|
||||||
|
if (patch.getOp() != APIPatch.Operation.remove)
|
||||||
|
throw new GuacamoleUnsupportedException("Only the \"remove\" "
|
||||||
|
+ "operation is supported.");
|
||||||
|
|
||||||
|
// Retrieve and validate path
|
||||||
|
String path = patch.getPath();
|
||||||
|
if (!path.startsWith("/"))
|
||||||
|
throw new GuacamoleClientException("Patch paths must start with \"/\".");
|
||||||
|
|
||||||
|
// Remove specified object
|
||||||
|
directory.remove(path.substring(1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new object within the underlying Directory, returning the
|
||||||
|
* object that was created. The identifier of the created object will be
|
||||||
|
* populated, if applicable.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
* The object to create.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The object that was created.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while adding the object to the underlying
|
||||||
|
* directory.
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
public ExternalType createObject(ExternalType object)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Validate that data was provided
|
||||||
|
if (object == null)
|
||||||
|
throw new GuacamoleClientException("Data must be submitted when creating objects.");
|
||||||
|
|
||||||
|
// Create the new object within the directory
|
||||||
|
directory.add(translator.toInternalObject(object));
|
||||||
|
|
||||||
|
return object;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an individual object, returning a DirectoryObjectResource
|
||||||
|
* implementation which exposes operations available on that object.
|
||||||
|
*
|
||||||
|
* @param identifier
|
||||||
|
* The identifier of the object to retrieve.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A DirectoryObjectResource exposing operations available on the
|
||||||
|
* object having the given identifier.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving the object.
|
||||||
|
*/
|
||||||
|
@Path("{identifier}")
|
||||||
|
public DirectoryObjectResource<InternalType, ExternalType>
|
||||||
|
getObjectResource(@PathParam("identifier") String identifier)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Retrieve the object having the given identifier
|
||||||
|
InternalType object = directory.get(identifier);
|
||||||
|
if (object == null)
|
||||||
|
throw new GuacamoleResourceNotFoundException("Not found: \"" + identifier + "\"");
|
||||||
|
|
||||||
|
// Return a resource which provides access to the retrieved object
|
||||||
|
return resourceFactory.create(userContext, directory, object);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.directory;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory which creates DirectoryResource instances exposing Directory
|
||||||
|
* objects of a particular type.
|
||||||
|
*
|
||||||
|
* @param <InternalType>
|
||||||
|
* The type of object contained within the Directory objects exposed by the
|
||||||
|
* DirectoryResource instances created by this DirectoryResourceFactory.
|
||||||
|
*
|
||||||
|
* @param <ExternalType>
|
||||||
|
* The type of object used in interchange (ie: serialized or deserialized
|
||||||
|
* as JSON) between REST clients and resources when representing the
|
||||||
|
* InternalType.
|
||||||
|
*/
|
||||||
|
public interface DirectoryResourceFactory<InternalType extends Identifiable, ExternalType> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new DirectoryResource which exposes the given Directory.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext from which the given Directory was obtained.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The Directory which should be exposed by the created
|
||||||
|
* DirectoryResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new DirectoryResource which exposes the given Directory.
|
||||||
|
*/
|
||||||
|
DirectoryResource<InternalType, ExternalType>
|
||||||
|
create(UserContext userContext, Directory<InternalType> directory);
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base classes providing support for exposing and manipulating Directory
|
||||||
|
* objects and their contents via the Guacamole REST API.
|
||||||
|
*/
|
||||||
|
package org.apache.guacamole.rest.directory;
|
@@ -19,13 +19,11 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.rest.history;
|
package org.apache.guacamole.rest.history;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
@@ -33,27 +31,16 @@ import org.apache.guacamole.GuacamoleException;
|
|||||||
import org.apache.guacamole.net.auth.ConnectionRecord;
|
import org.apache.guacamole.net.auth.ConnectionRecord;
|
||||||
import org.apache.guacamole.net.auth.ConnectionRecordSet;
|
import org.apache.guacamole.net.auth.ConnectionRecordSet;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
|
||||||
import org.apache.guacamole.rest.ObjectRetrievalService;
|
|
||||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A REST Service for retrieving and managing the history records of Guacamole
|
* A REST resource for retrieving and managing the history records of Guacamole
|
||||||
* objects.
|
* objects.
|
||||||
*
|
*
|
||||||
* @author Michael Jumper
|
* @author Michael Jumper
|
||||||
*/
|
*/
|
||||||
@Path("/data/{dataSource}/history")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public class HistoryRESTService {
|
public class HistoryResource {
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger for this class.
|
|
||||||
*/
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(HistoryRESTService.class);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of history records to return in any one response.
|
* The maximum number of history records to return in any one response.
|
||||||
@@ -61,30 +48,25 @@ public class HistoryRESTService {
|
|||||||
private static final int MAXIMUM_HISTORY_SIZE = 1000;
|
private static final int MAXIMUM_HISTORY_SIZE = 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service for authenticating users from auth tokens.
|
* The UserContext whose associated connection history is being exposed.
|
||||||
*/
|
*/
|
||||||
@Inject
|
private final UserContext userContext;
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for convenient retrieval of objects.
|
* Creates a new HistoryResource which exposes the connection history
|
||||||
|
* associated with the given UserContext.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext whose connection history should be exposed.
|
||||||
*/
|
*/
|
||||||
@Inject
|
public HistoryResource(UserContext userContext) {
|
||||||
private ObjectRetrievalService retrievalService;
|
this.userContext = userContext;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the usage history for all connections, restricted by optional
|
* Retrieves the usage history for all connections, restricted by optional
|
||||||
* filter parameters.
|
* filter parameters.
|
||||||
*
|
*
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext containing the connection whose history is to be
|
|
||||||
* retrieved.
|
|
||||||
*
|
|
||||||
* @param requiredContents
|
* @param requiredContents
|
||||||
* The set of strings that each must occur somewhere within the
|
* The set of strings that each must occur somewhere within the
|
||||||
* returned connection records, whether within the associated username,
|
* returned connection records, whether within the associated username,
|
||||||
@@ -105,16 +87,12 @@ public class HistoryRESTService {
|
|||||||
* If an error occurs while retrieving the connection history.
|
* If an error occurs while retrieving the connection history.
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("/connections")
|
@Path("connections")
|
||||||
public List<APIConnectionRecord> getConnectionHistory(@QueryParam("token") String authToken,
|
public List<APIConnectionRecord> getConnectionHistory(
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@QueryParam("contains") List<String> requiredContents,
|
@QueryParam("contains") List<String> requiredContents,
|
||||||
@QueryParam("order") List<APIConnectionRecordSortPredicate> sortPredicates)
|
@QueryParam("order") List<APIConnectionRecordSortPredicate> sortPredicates)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Retrieve overall connection history
|
// Retrieve overall connection history
|
||||||
ConnectionRecordSet history = userContext.getConnectionHistory();
|
ConnectionRecordSet history = userContext.getConnectionHistory();
|
||||||
|
|
@@ -17,7 +17,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.apache.guacamole.rest.user;
|
package org.apache.guacamole.rest.permission;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
@@ -0,0 +1,261 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.permission;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleClientException;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.User;
|
||||||
|
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
||||||
|
import org.apache.guacamole.net.auth.permission.Permission;
|
||||||
|
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
||||||
|
import org.apache.guacamole.rest.APIPatch;
|
||||||
|
import org.apache.guacamole.rest.PATCH;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which abstracts the operations available on the permissions
|
||||||
|
* granted to an existing User.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class PermissionSetResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 a specific active connection.
|
||||||
|
*/
|
||||||
|
private static final String ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX = "/activeConnectionPermissions/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The User object whose permissions are represented by this
|
||||||
|
* PermissionSetResource.
|
||||||
|
*/
|
||||||
|
private final User user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new PermissionSetResource which exposes the operations and
|
||||||
|
* subresources available for permissions of the given User.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* The User whose permissions should be represented by this
|
||||||
|
* PermissionSetResource.
|
||||||
|
*/
|
||||||
|
public PermissionSetResource(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of permissions for the user with the given username.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A list of all permissions granted to the specified user.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving permissions.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
public APIPermissionSet getPermissions() throws GuacamoleException {
|
||||||
|
return new APIPermissionSet(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the given permission set patch by queuing an add or remove
|
||||||
|
* operation for the given permission based on the given patch operation.
|
||||||
|
*
|
||||||
|
* @param <PermissionType>
|
||||||
|
* The type of permission stored within the permission set.
|
||||||
|
*
|
||||||
|
* @param operation
|
||||||
|
* The patch operation to perform.
|
||||||
|
*
|
||||||
|
* @param permissionSetPatch
|
||||||
|
* The permission set patch being modified.
|
||||||
|
*
|
||||||
|
* @param permission
|
||||||
|
* The permission being added or removed from the set.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the requested patch operation is not supported.
|
||||||
|
*/
|
||||||
|
private <PermissionType extends Permission> void updatePermissionSet(
|
||||||
|
APIPatch.Operation operation,
|
||||||
|
PermissionSetPatch<PermissionType> permissionSetPatch,
|
||||||
|
PermissionType permission) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Add or remove permission based on operation
|
||||||
|
switch (operation) {
|
||||||
|
|
||||||
|
// Add permission
|
||||||
|
case add:
|
||||||
|
permissionSetPatch.addPermission(permission);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Remove permission
|
||||||
|
case remove:
|
||||||
|
permissionSetPatch.removePermission(permission);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Unsupported patch operation
|
||||||
|
default:
|
||||||
|
throw new GuacamoleClientException("Unsupported patch operation: \"" + operation + "\"");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 patches
|
||||||
|
* The permission patches to apply for this request.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If a problem is encountered while modifying permissions.
|
||||||
|
*/
|
||||||
|
@PATCH
|
||||||
|
public void patchPermissions(List<APIPatch<String>> patches)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Permission patches for all types of permissions
|
||||||
|
PermissionSetPatch<ObjectPermission> connectionPermissionPatch = new PermissionSetPatch<ObjectPermission>();
|
||||||
|
PermissionSetPatch<ObjectPermission> connectionGroupPermissionPatch = new PermissionSetPatch<ObjectPermission>();
|
||||||
|
PermissionSetPatch<ObjectPermission> activeConnectionPermissionPatch = new PermissionSetPatch<ObjectPermission>();
|
||||||
|
PermissionSetPatch<ObjectPermission> userPermissionPatch = new PermissionSetPatch<ObjectPermission>();
|
||||||
|
PermissionSetPatch<SystemPermission> systemPermissionPatch = new PermissionSetPatch<SystemPermission>();
|
||||||
|
|
||||||
|
// Apply all patch operations individually
|
||||||
|
for (APIPatch<String> patch : patches) {
|
||||||
|
|
||||||
|
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 and update corresponding permission
|
||||||
|
ObjectPermission permission = new ObjectPermission(type, identifier);
|
||||||
|
updatePermissionSet(patch.getOp(), connectionPermissionPatch, permission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 and update corresponding permission
|
||||||
|
ObjectPermission permission = new ObjectPermission(type, identifier);
|
||||||
|
updatePermissionSet(patch.getOp(), connectionGroupPermissionPatch, permission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create active connection permission if path has active connection prefix
|
||||||
|
else if (path.startsWith(ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX)) {
|
||||||
|
|
||||||
|
// Get identifier and type from patch operation
|
||||||
|
String identifier = path.substring(ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length());
|
||||||
|
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
|
||||||
|
|
||||||
|
// Create and update corresponding permission
|
||||||
|
ObjectPermission permission = new ObjectPermission(type, identifier);
|
||||||
|
updatePermissionSet(patch.getOp(), activeConnectionPermissionPatch, permission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 and update corresponding permission
|
||||||
|
ObjectPermission permission = new ObjectPermission(type, identifier);
|
||||||
|
updatePermissionSet(patch.getOp(), userPermissionPatch, permission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create system permission if path is system path
|
||||||
|
else if (path.equals(SYSTEM_PERMISSION_PATCH_PATH)) {
|
||||||
|
|
||||||
|
// Get identifier and type from patch operation
|
||||||
|
SystemPermission.Type type = SystemPermission.Type.valueOf(patch.getValue());
|
||||||
|
|
||||||
|
// Create and update corresponding permission
|
||||||
|
SystemPermission permission = new SystemPermission(type);
|
||||||
|
updatePermissionSet(patch.getOp(), systemPermissionPatch, permission);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, the path is not supported
|
||||||
|
else
|
||||||
|
throw new GuacamoleClientException("Unsupported patch path: \"" + path + "\"");
|
||||||
|
|
||||||
|
} // end for each patch operation
|
||||||
|
|
||||||
|
// Save the permission changes
|
||||||
|
connectionPermissionPatch.apply(user.getConnectionPermissions());
|
||||||
|
connectionGroupPermissionPatch.apply(user.getConnectionGroupPermissions());
|
||||||
|
activeConnectionPermissionPatch.apply(user.getActiveConnectionPermissions());
|
||||||
|
userPermissionPatch.apply(user.getUserPermissions());
|
||||||
|
systemPermissionPatch.apply(user.getSystemPermissions());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,196 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole.rest.schema;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
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 org.apache.guacamole.GuacamoleException;
|
|
||||||
import org.apache.guacamole.environment.Environment;
|
|
||||||
import org.apache.guacamole.environment.LocalEnvironment;
|
|
||||||
import org.apache.guacamole.form.Form;
|
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
|
||||||
import org.apache.guacamole.rest.ObjectRetrievalService;
|
|
||||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
|
||||||
import org.apache.guacamole.protocols.ProtocolInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A REST service which provides access to descriptions of the properties,
|
|
||||||
* attributes, etc. of objects used within the Guacamole REST API.
|
|
||||||
*
|
|
||||||
* @author Michael Jumper
|
|
||||||
*/
|
|
||||||
@Path("/schema/{dataSource}")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public class SchemaRESTService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A service for authenticating users from auth tokens.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service for convenient retrieval of objects.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private ObjectRetrievalService retrievalService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the possible attributes of a user object.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext dictating the available user attributes.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* A collection of forms which describe the possible attributes of a
|
|
||||||
* user object.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving the possible attributes.
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
@Path("/users/attributes")
|
|
||||||
public Collection<Form> getUserAttributes(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
// Retrieve all possible user attributes
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
return userContext.getUserAttributes();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the possible attributes of a connection object.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext dictating the available connection attributes.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* A collection of forms which describe the possible attributes of a
|
|
||||||
* connection object.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving the possible attributes.
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
@Path("/connections/attributes")
|
|
||||||
public Collection<Form> getConnectionAttributes(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
// Retrieve all possible connection attributes
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
return userContext.getConnectionAttributes();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the possible attributes of a connection group object.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext dictating the available connection group
|
|
||||||
* attributes.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* A collection of forms which describe the possible attributes of a
|
|
||||||
* connection group object.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while retrieving the possible attributes.
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
@Path("/connectionGroups/attributes")
|
|
||||||
public Collection<Form> getConnectionGroupAttributes(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
// Retrieve all possible connection group attributes
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
return userContext.getConnectionGroupAttributes();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a map of protocols defined in the system - protocol name to protocol.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext dictating the protocols available. Currently, the
|
|
||||||
* UserContext actually does not dictate this, the the same set of
|
|
||||||
* protocols will be retrieved for all users, though the identifier
|
|
||||||
* given here will be validated.
|
|
||||||
*
|
|
||||||
* @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
|
|
||||||
@Path("/protocols")
|
|
||||||
public Map<String, ProtocolInfo> getProtocols(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
// Verify the given auth token and auth provider identifier are valid
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Get and return a map of all protocols.
|
|
||||||
Environment env = new LocalEnvironment();
|
|
||||||
return env.getProtocols();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.schema;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
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.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
import org.apache.guacamole.environment.LocalEnvironment;
|
||||||
|
import org.apache.guacamole.form.Form;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.protocols.ProtocolInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which provides access to descriptions of the properties,
|
||||||
|
* attributes, etc. of objects within a particular UserContext.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class SchemaResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UserContext whose schema is exposed by this SchemaResource.
|
||||||
|
*/
|
||||||
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new SchemaResource which exposes meta information describing
|
||||||
|
* the kind of data within the given UserContext.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext whose schema should be exposed by this
|
||||||
|
* SchemaResource.
|
||||||
|
*/
|
||||||
|
public SchemaResource(UserContext userContext) {
|
||||||
|
this.userContext = userContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the possible attributes of a user object.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A collection of forms which describe the possible attributes of a
|
||||||
|
* user object.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving the possible attributes.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("userAttributes")
|
||||||
|
public Collection<Form> getUserAttributes() throws GuacamoleException {
|
||||||
|
|
||||||
|
// Retrieve all possible user attributes
|
||||||
|
return userContext.getUserAttributes();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the possible attributes of a connection object.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A collection of forms which describe the possible attributes of a
|
||||||
|
* connection object.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving the possible attributes.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("connectionAttributes")
|
||||||
|
public Collection<Form> getConnectionAttributes()
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Retrieve all possible connection attributes
|
||||||
|
return userContext.getConnectionAttributes();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the possible attributes of a connection group object.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A collection of forms which describe the possible attributes of a
|
||||||
|
* connection group object.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving the possible attributes.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
@Path("connectionGroupAttributes")
|
||||||
|
public Collection<Form> getConnectionGroupAttributes()
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Retrieve all possible connection group attributes
|
||||||
|
return userContext.getConnectionGroupAttributes();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a map of protocols defined in the system - protocol name to protocol.
|
||||||
|
*
|
||||||
|
* @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
|
||||||
|
@Path("protocols")
|
||||||
|
public Map<String, ProtocolInfo> getProtocols() throws GuacamoleException {
|
||||||
|
|
||||||
|
// Get and return a map of all protocols.
|
||||||
|
Environment env = new LocalEnvironment();
|
||||||
|
return env.getProtocols();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.session;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleSession;
|
||||||
|
import org.apache.guacamole.rest.auth.AuthenticationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST service which exposes all data associated with Guacamole users'
|
||||||
|
* sessions.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Path("/session")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class SessionRESTService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A service for authenticating users from auth tokens.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private AuthenticationService authenticationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for creating SessionResources which expose a given
|
||||||
|
* GuacamoleSession.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private SessionResourceFactory sessionResourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a resource representing the GuacamoleSession associated with
|
||||||
|
* the given authentication token.
|
||||||
|
*
|
||||||
|
* @param authToken
|
||||||
|
* The authentication token that is used to authenticate the user
|
||||||
|
* having the session being exposed.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A resource representing the GuacamoleSession associated with the
|
||||||
|
* given authentication token.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the authentication token is invalid.
|
||||||
|
*/
|
||||||
|
@Path("/")
|
||||||
|
public SessionResource getSessionResource(@QueryParam("token") String authToken)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Return a resource exposing the retrieved session
|
||||||
|
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
||||||
|
return sessionResourceFactory.create(session);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.session;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleSession;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.rest.tunnel.TunnelCollectionResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which exposes all data associated with a Guacamole user's
|
||||||
|
* session via the underlying UserContexts.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class SessionResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GuacamoleSession being exposed by this SessionResource.
|
||||||
|
*/
|
||||||
|
private final GuacamoleSession session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for creating UserContextResources which expose a given
|
||||||
|
* UserContext.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private UserContextResourceFactory userContextResourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new SessionResource which exposes the data within the given
|
||||||
|
* GuacamoleSession.
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* The GuacamoleSession which should be exposed through this
|
||||||
|
* SessionResource.
|
||||||
|
*/
|
||||||
|
@AssistedInject
|
||||||
|
public SessionResource(@Assisted GuacamoleSession session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a resource representing the UserContext associated with the
|
||||||
|
* AuthenticationProvider having the given identifier.
|
||||||
|
*
|
||||||
|
* @param authProviderIdentifier
|
||||||
|
* The unique identifier of the AuthenticationProvider associated with
|
||||||
|
* the UserContext being retrieved.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A resource representing the UserContext associated with the
|
||||||
|
* AuthenticationProvider having the given identifier.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the AuthenticationProvider identifier is invalid.
|
||||||
|
*/
|
||||||
|
@Path("data/{dataSource}")
|
||||||
|
public UserContextResource getUserContextResource(
|
||||||
|
@PathParam("dataSource") String authProviderIdentifier)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
// Pull UserContext defined by the given auth provider identifier
|
||||||
|
UserContext userContext = session.getUserContext(authProviderIdentifier);
|
||||||
|
|
||||||
|
// Return a resource exposing the retrieved UserContext
|
||||||
|
return userContextResourceFactory.create(userContext);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a resource representing all tunnels associated with session
|
||||||
|
* exposed by this SessionResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A resource representing all tunnels associated with the
|
||||||
|
* AuthenticationProvider having the given identifier.
|
||||||
|
*/
|
||||||
|
@Path("tunnels")
|
||||||
|
public TunnelCollectionResource getTunnelCollectionResource() {
|
||||||
|
return new TunnelCollectionResource(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.session;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory which creates resources that expose the contents of a given
|
||||||
|
* GuacamoleSession.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public interface SessionResourceFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new SessionResource which exposes the contents of the
|
||||||
|
* given GuacamoleSession.
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* The GuacamoleSession whose contents should be exposed.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new SessionResource which exposes the contents of the given
|
||||||
|
* GuacamoleSession.
|
||||||
|
*/
|
||||||
|
SessionResource create(GuacamoleSession session);
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.session;
|
||||||
|
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryResourceFactory;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.ActiveConnection;
|
||||||
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
|
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||||
|
import org.apache.guacamole.net.auth.User;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.rest.activeconnection.APIActiveConnection;
|
||||||
|
import org.apache.guacamole.rest.connection.APIConnection;
|
||||||
|
import org.apache.guacamole.rest.connectiongroup.APIConnectionGroup;
|
||||||
|
import org.apache.guacamole.rest.history.HistoryResource;
|
||||||
|
import org.apache.guacamole.rest.schema.SchemaResource;
|
||||||
|
import org.apache.guacamole.rest.user.APIUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which exposes the contents of a particular UserContext.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class UserContextResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UserContext being exposed through this resource.
|
||||||
|
*/
|
||||||
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for creating DirectoryResources which expose a given
|
||||||
|
* ActiveConnection Directory.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private DirectoryResourceFactory<ActiveConnection, APIActiveConnection>
|
||||||
|
activeConnectionDirectoryResourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for creating DirectoryResources which expose a given
|
||||||
|
* Connection Directory.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private DirectoryResourceFactory<Connection, APIConnection>
|
||||||
|
connectionDirectoryResourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for creating DirectoryResources which expose a given
|
||||||
|
* ConnectionGroup Directory.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private DirectoryResourceFactory<ConnectionGroup, APIConnectionGroup>
|
||||||
|
connectionGroupDirectoryResourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for creating DirectoryResources which expose a given
|
||||||
|
* User Directory.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private DirectoryResourceFactory<User, APIUser> userDirectoryResourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new UserContextResource which exposes the data within the
|
||||||
|
* given UserContext.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext which should be exposed through this
|
||||||
|
* UserContextResource.
|
||||||
|
*/
|
||||||
|
@AssistedInject
|
||||||
|
public UserContextResource(@Assisted UserContext userContext) {
|
||||||
|
this.userContext = userContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new resource which represents the ActiveConnection Directory
|
||||||
|
* contained within the UserContext exposed by this UserContextResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new resource which represents the ActiveConnection Directory
|
||||||
|
* contained within the UserContext exposed by this UserContextResource.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving the ActiveConnection Directory.
|
||||||
|
*/
|
||||||
|
@Path("activeConnections")
|
||||||
|
public DirectoryResource<ActiveConnection, APIActiveConnection>
|
||||||
|
getActiveConnectionDirectoryResource() throws GuacamoleException {
|
||||||
|
return activeConnectionDirectoryResourceFactory.create(userContext,
|
||||||
|
userContext.getActiveConnectionDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new resource which represents the Connection Directory
|
||||||
|
* contained within the UserContext exposed by this UserContextResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new resource which represents the Connection Directory contained
|
||||||
|
* within the UserContext exposed by this UserContextResource.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving the Connection Directory.
|
||||||
|
*/
|
||||||
|
@Path("connections")
|
||||||
|
public DirectoryResource<Connection, APIConnection> getConnectionDirectoryResource()
|
||||||
|
throws GuacamoleException {
|
||||||
|
return connectionDirectoryResourceFactory.create(userContext,
|
||||||
|
userContext.getConnectionDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new resource which represents the ConnectionGroup Directory
|
||||||
|
* contained within the UserContext exposed by this UserContextResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new resource which represents the ConnectionGroup Directory
|
||||||
|
* contained within the UserContext exposed by this UserContextResource.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving the ConnectionGroup Directory.
|
||||||
|
*/
|
||||||
|
@Path("connectionGroups")
|
||||||
|
public DirectoryResource<ConnectionGroup, APIConnectionGroup> getConnectionGroupDirectoryResource()
|
||||||
|
throws GuacamoleException {
|
||||||
|
return connectionGroupDirectoryResourceFactory.create(userContext,
|
||||||
|
userContext.getConnectionGroupDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new resource which represents the User Directory contained
|
||||||
|
* within the UserContext exposed by this UserContextResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new resource which represents the User Directory contained within
|
||||||
|
* the UserContext exposed by this UserContextResource.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while retrieving the User Directory.
|
||||||
|
*/
|
||||||
|
@Path("users")
|
||||||
|
public DirectoryResource<User, APIUser> getUserDirectoryResource()
|
||||||
|
throws GuacamoleException {
|
||||||
|
return userDirectoryResourceFactory.create(userContext,
|
||||||
|
userContext.getUserDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new resource which represents historical data contained
|
||||||
|
* within the UserContext exposed by this UserContextResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new resource which represents the historical data contained within
|
||||||
|
* the UserContext exposed by this UserContextResource.
|
||||||
|
*/
|
||||||
|
@Path("history")
|
||||||
|
public HistoryResource getHistoryResource() {
|
||||||
|
return new HistoryResource(userContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new resource which represents meta information describing the
|
||||||
|
* kind of data which within the UserContext exposed by this
|
||||||
|
* UserContextResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new resource which represents the meta information describing the
|
||||||
|
* kind of data within the UserContext exposed by this
|
||||||
|
* UserContextResource.
|
||||||
|
*/
|
||||||
|
@Path("schema")
|
||||||
|
public SchemaResource getSchemaResource() {
|
||||||
|
return new SchemaResource(userContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.session;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory which creates resources that expose the contents of a given
|
||||||
|
* UserContext.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public interface UserContextResourceFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new UserContextResource which exposes the contents of the
|
||||||
|
* given UserContext.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext whose contents should be exposed.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A new UserContextResource which exposes the contents of the given
|
||||||
|
* UserContext.
|
||||||
|
*/
|
||||||
|
UserContextResource create(UserContext userContext);
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classes which expose the absolute root of the data available to a Guacamole
|
||||||
|
* user's session.
|
||||||
|
*/
|
||||||
|
package org.apache.guacamole.rest.session;
|
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.tunnel;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.StreamingOutput;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.tunnel.StreamInterceptingTunnel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource providing access to a Guacamole protocol-level stream
|
||||||
|
* within a tunnel.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class StreamResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tunnel whose stream is exposed through this StreamResource.
|
||||||
|
*/
|
||||||
|
private final StreamInterceptingTunnel tunnel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index of the stream being exposed.
|
||||||
|
*/
|
||||||
|
private final int streamIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The media type of the data within the stream being exposed.
|
||||||
|
*/
|
||||||
|
private final String mediaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new StreamResource which provides access to the given
|
||||||
|
* stream.
|
||||||
|
*
|
||||||
|
* @param tunnel
|
||||||
|
* The tunnel whose stream is being exposed.
|
||||||
|
*
|
||||||
|
* @param streamIndex
|
||||||
|
* The index of the stream to expose via this StreamResource.
|
||||||
|
*
|
||||||
|
* @param mediaType
|
||||||
|
* The media type of the data within the stream.
|
||||||
|
*/
|
||||||
|
public StreamResource(StreamInterceptingTunnel tunnel, int streamIndex,
|
||||||
|
String mediaType) {
|
||||||
|
this.tunnel = tunnel;
|
||||||
|
this.streamIndex = streamIndex;
|
||||||
|
this.mediaType = mediaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercepts and returns the entire contents the stream represented by
|
||||||
|
* this StreamResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A response through which the entire contents of the intercepted
|
||||||
|
* stream will be sent.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
public Response getStreamContents() {
|
||||||
|
|
||||||
|
// Intercept all output
|
||||||
|
StreamingOutput stream = new StreamingOutput() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(OutputStream output) throws IOException {
|
||||||
|
try {
|
||||||
|
tunnel.interceptStream(streamIndex, output);
|
||||||
|
}
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
throw new IOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return Response.ok(stream, mediaType).build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercepts the stream represented by this StreamResource, sending the
|
||||||
|
* contents of the given InputStream over that stream as "blob"
|
||||||
|
* instructions.
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* An InputStream containing the data to be sent over the intercepted
|
||||||
|
* stream.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the intercepted stream closes with an error.
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
@Consumes(MediaType.WILDCARD)
|
||||||
|
public void setStreamContents(InputStream data) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Send input over stream
|
||||||
|
tunnel.interceptStream(streamIndex, data);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.tunnel;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.PathParam;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
||||||
|
import org.apache.guacamole.GuacamoleSession;
|
||||||
|
import org.apache.guacamole.tunnel.StreamInterceptingTunnel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which exposes the active tunnels of a Guacamole session.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Path("/tunnels")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class TunnelCollectionResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GuacamoleSession containing the tunnels exposed by this resource.
|
||||||
|
*/
|
||||||
|
private final GuacamoleSession session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new TunnelCollectionResource which exposes the active tunnels
|
||||||
|
* of the given GuacamoleSession.
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* The GuacamoleSession whose tunnels should be exposed by this
|
||||||
|
* resource.
|
||||||
|
*/
|
||||||
|
public TunnelCollectionResource(GuacamoleSession session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the UUIDs of all tunnels exposed by this
|
||||||
|
* TunnelCollectionResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A set containing the UUIDs of all tunnels exposed by this
|
||||||
|
* TunnelCollectionResource.
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
public Set<String> getTunnelUUIDs() {
|
||||||
|
return session.getTunnels().keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the tunnel having the given UUID, returning a TunnelResource
|
||||||
|
* representing that tunnel. If no such tunnel exists, an exception will be
|
||||||
|
* thrown.
|
||||||
|
*
|
||||||
|
* @param tunnelUUID
|
||||||
|
* The UUID of the tunnel to return via a TunnelResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A TunnelResource which represents the tunnel having the given UUID.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If no such tunnel exists.
|
||||||
|
*/
|
||||||
|
@Path("{tunnel}")
|
||||||
|
public TunnelResource getTunnel(@PathParam("tunnel") String tunnelUUID)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
Map<String, StreamInterceptingTunnel> tunnels = session.getTunnels();
|
||||||
|
|
||||||
|
// Pull tunnel with given UUID
|
||||||
|
final StreamInterceptingTunnel tunnel = tunnels.get(tunnelUUID);
|
||||||
|
if (tunnel == null)
|
||||||
|
throw new GuacamoleResourceNotFoundException("No such tunnel.");
|
||||||
|
|
||||||
|
// Return corresponding tunnel resource
|
||||||
|
return new TunnelResource(tunnel);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,202 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole.rest.tunnel;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.DefaultValue;
|
|
||||||
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;
|
|
||||||
import javax.ws.rs.core.StreamingOutput;
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
|
||||||
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
|
||||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
|
||||||
import org.apache.guacamole.tunnel.StreamInterceptingTunnel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A REST Service for retrieving and managing the tunnels of active
|
|
||||||
* connections, including any associated objects.
|
|
||||||
*
|
|
||||||
* @author Michael Jumper
|
|
||||||
*/
|
|
||||||
@Path("/tunnels")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
public class TunnelRESTService {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The media type to send as the content type of stream contents if no
|
|
||||||
* other media type is specified.
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_MEDIA_TYPE = "application/octet-stream";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A service for authenticating users from auth tokens.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the UUIDs of all currently-active tunnels associated with the
|
|
||||||
* session identified by the given auth token.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* A set containing the UUIDs of all currently-active tunnels.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If the session associated with the given auth token cannot be
|
|
||||||
* retrieved.
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
public Set<String> getTunnelUUIDs(@QueryParam("token") String authToken)
|
|
||||||
throws GuacamoleException {
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
return session.getTunnels().keySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intercepts and returns the entire contents of a specific stream.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param tunnelUUID
|
|
||||||
* The UUID of the tunnel containing the stream being intercepted.
|
|
||||||
*
|
|
||||||
* @param streamIndex
|
|
||||||
* The index of the stream to intercept.
|
|
||||||
*
|
|
||||||
* @param mediaType
|
|
||||||
* The media type (mimetype) of the data within the stream.
|
|
||||||
*
|
|
||||||
* @param filename
|
|
||||||
* The filename to use for the sake of identifying the data returned.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* A response through which the entire contents of the intercepted
|
|
||||||
* stream will be sent.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If the session associated with the given auth token cannot be
|
|
||||||
* retrieved, or if no such tunnel exists.
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
@Path("/{tunnel}/streams/{index}/{filename}")
|
|
||||||
public Response getStreamContents(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("tunnel") String tunnelUUID,
|
|
||||||
@PathParam("index") final int streamIndex,
|
|
||||||
@QueryParam("type") @DefaultValue(DEFAULT_MEDIA_TYPE) String mediaType,
|
|
||||||
@PathParam("filename") String filename)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
Map<String, StreamInterceptingTunnel> tunnels = session.getTunnels();
|
|
||||||
|
|
||||||
// Pull tunnel with given UUID
|
|
||||||
final StreamInterceptingTunnel tunnel = tunnels.get(tunnelUUID);
|
|
||||||
if (tunnel == null)
|
|
||||||
throw new GuacamoleResourceNotFoundException("No such tunnel.");
|
|
||||||
|
|
||||||
// Intercept all output
|
|
||||||
StreamingOutput stream = new StreamingOutput() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(OutputStream output) throws IOException {
|
|
||||||
try {
|
|
||||||
tunnel.interceptStream(streamIndex, output);
|
|
||||||
}
|
|
||||||
catch (GuacamoleException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
return Response.ok(stream, mediaType).build();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intercepts a specific stream, sending the contents of the given
|
|
||||||
* InputStream over that stream as "blob" instructions.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param tunnelUUID
|
|
||||||
* The UUID of the tunnel containing the stream being intercepted.
|
|
||||||
*
|
|
||||||
* @param streamIndex
|
|
||||||
* The index of the stream to intercept.
|
|
||||||
*
|
|
||||||
* @param filename
|
|
||||||
* The filename to use for the sake of identifying the data being sent.
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* An InputStream containing the data to be sent over the intercepted
|
|
||||||
* stream.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If the session associated with the given auth token cannot be
|
|
||||||
* retrieved, if no such tunnel exists, or if the intercepted stream
|
|
||||||
* itself closes with an error.
|
|
||||||
*/
|
|
||||||
@POST
|
|
||||||
@Consumes(MediaType.WILDCARD)
|
|
||||||
@Path("/{tunnel}/streams/{index}/{filename}")
|
|
||||||
public void setStreamContents(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("tunnel") String tunnelUUID,
|
|
||||||
@PathParam("index") final int streamIndex,
|
|
||||||
@PathParam("filename") String filename,
|
|
||||||
InputStream data)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
Map<String, StreamInterceptingTunnel> tunnels = session.getTunnels();
|
|
||||||
|
|
||||||
// Pull tunnel with given UUID
|
|
||||||
final StreamInterceptingTunnel tunnel = tunnels.get(tunnelUUID);
|
|
||||||
if (tunnel == null)
|
|
||||||
throw new GuacamoleResourceNotFoundException("No such tunnel.");
|
|
||||||
|
|
||||||
// Send input over stream
|
|
||||||
tunnel.interceptStream(streamIndex, data);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.tunnel;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.DefaultValue;
|
||||||
|
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 org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.tunnel.StreamInterceptingTunnel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which abstracts the operations available for an individual
|
||||||
|
* tunnel.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class TunnelResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The media type to send as the content type of stream contents if no
|
||||||
|
* other media type is specified.
|
||||||
|
*/
|
||||||
|
private static final String DEFAULT_MEDIA_TYPE = "application/octet-stream";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tunnel that this TunnelResource represents.
|
||||||
|
*/
|
||||||
|
private final StreamInterceptingTunnel tunnel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new TunnelResource which exposes the operations and
|
||||||
|
* subresources available for the given tunnel.
|
||||||
|
*
|
||||||
|
* @param tunnel
|
||||||
|
* The tunnel that this TunnelResource should represent.
|
||||||
|
*/
|
||||||
|
public TunnelResource(StreamInterceptingTunnel tunnel) {
|
||||||
|
this.tunnel = tunnel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercepts and returns the entire contents of a specific stream.
|
||||||
|
*
|
||||||
|
* @param streamIndex
|
||||||
|
* The index of the stream to intercept.
|
||||||
|
*
|
||||||
|
* @param mediaType
|
||||||
|
* The media type (mimetype) of the data within the stream.
|
||||||
|
*
|
||||||
|
* @param filename
|
||||||
|
* The filename to use for the sake of identifying the data returned.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A response through which the entire contents of the intercepted
|
||||||
|
* stream will be sent.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If the session associated with the given auth token cannot be
|
||||||
|
* retrieved, or if no such tunnel exists.
|
||||||
|
*/
|
||||||
|
@Path("streams/{index}/{filename}")
|
||||||
|
public StreamResource getStream(@PathParam("index") final int streamIndex,
|
||||||
|
@QueryParam("type") @DefaultValue(DEFAULT_MEDIA_TYPE) String mediaType,
|
||||||
|
@PathParam("filename") String filename)
|
||||||
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
return new StreamResource(tunnel, streamIndex, mediaType);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classes related to the manipulation of Guacamole tunnels and underlying
|
||||||
|
* streams.
|
||||||
|
*/
|
||||||
|
package org.apache.guacamole.rest.tunnel;
|
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.user;
|
||||||
|
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
import java.util.UUID;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.User;
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which abstracts the operations available on a Directory of
|
||||||
|
* Users.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class UserDirectoryResource extends DirectoryResource<User, APIUser> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UserContext associated with the Directory which contains the
|
||||||
|
* User exposed by this resource.
|
||||||
|
*/
|
||||||
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Directory exposed by this resource.
|
||||||
|
*/
|
||||||
|
private final Directory<User> directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory which can be used to create instances of resources representing
|
||||||
|
* Users.
|
||||||
|
*/
|
||||||
|
private final DirectoryObjectResourceFactory<User, APIUser> resourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new UserDirectoryResource which exposes the operations and
|
||||||
|
* subresources available for the given User Directory.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext associated with the given Directory.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The Directory being exposed.
|
||||||
|
*
|
||||||
|
* @param translator
|
||||||
|
* A DirectoryObjectTranslator implementation which handles
|
||||||
|
* Users.
|
||||||
|
*
|
||||||
|
* @param resourceFactory
|
||||||
|
* A factory which can be used to create instances of resources
|
||||||
|
* representing Users.
|
||||||
|
*/
|
||||||
|
@AssistedInject
|
||||||
|
public UserDirectoryResource(@Assisted UserContext userContext,
|
||||||
|
@Assisted Directory<User> directory,
|
||||||
|
DirectoryObjectTranslator<User, APIUser> translator,
|
||||||
|
DirectoryObjectResourceFactory<User, APIUser> resourceFactory) {
|
||||||
|
super(userContext, directory, translator, resourceFactory);
|
||||||
|
this.userContext = userContext;
|
||||||
|
this.directory = directory;
|
||||||
|
this.resourceFactory = resourceFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public APIUser createObject(APIUser object) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Randomly set the password if it wasn't provided
|
||||||
|
if (object.getPassword() == null)
|
||||||
|
object.setPassword(UUID.randomUUID().toString());
|
||||||
|
|
||||||
|
return super.createObject(object);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DirectoryObjectResource<User, APIUser>
|
||||||
|
getObjectResource(String identifier) throws GuacamoleException {
|
||||||
|
|
||||||
|
// If username is own username, just use self - might not have query permissions
|
||||||
|
if (userContext.self().getIdentifier().equals(identifier))
|
||||||
|
return resourceFactory.create(userContext, directory, userContext.self());
|
||||||
|
|
||||||
|
return super.getObjectResource(identifier);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.user;
|
||||||
|
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResourceFactory;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryResourceFactory;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||||
|
import org.apache.guacamole.net.auth.User;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guice Module which configures injections required for handling User resources
|
||||||
|
* via the REST API.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class UserModule extends AbstractModule {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
|
||||||
|
// Create the required DirectoryResourceFactory implementation
|
||||||
|
install(new FactoryModuleBuilder()
|
||||||
|
.implement(
|
||||||
|
new TypeLiteral<DirectoryResource<User, APIUser>>() {},
|
||||||
|
UserDirectoryResource.class
|
||||||
|
)
|
||||||
|
.build(new TypeLiteral<DirectoryResourceFactory<User, APIUser>>() {}));
|
||||||
|
|
||||||
|
// Create the required DirectoryObjectResourceFactory implementation
|
||||||
|
install(new FactoryModuleBuilder()
|
||||||
|
.implement(
|
||||||
|
new TypeLiteral<DirectoryObjectResource<User, APIUser>>() {},
|
||||||
|
UserResource.class
|
||||||
|
)
|
||||||
|
.build(new TypeLiteral<DirectoryObjectResourceFactory<User, APIUser>>() {}));
|
||||||
|
|
||||||
|
// Bind translator for converting between User and APIUser
|
||||||
|
bind(new TypeLiteral<DirectoryObjectTranslator<User, APIUser>>() {})
|
||||||
|
.to(UserObjectTranslator.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.user;
|
||||||
|
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.User;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translator which converts between User objects and APIUser objects.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
public class UserObjectTranslator
|
||||||
|
implements DirectoryObjectTranslator<User, APIUser> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public APIUser toExternalObject(User object)
|
||||||
|
throws GuacamoleException {
|
||||||
|
return new APIUser(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User toInternalObject(APIUser object)
|
||||||
|
throws GuacamoleException {
|
||||||
|
return new APIUserWrapper(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyExternalChanges(User existingObject,
|
||||||
|
APIUser object) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Do not update the user password if no password was provided
|
||||||
|
if (object.getPassword() != null)
|
||||||
|
existingObject.setPassword(object.getPassword());
|
||||||
|
|
||||||
|
// Update user attributes
|
||||||
|
existingObject.setAttributes(object.getAttributes());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,644 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.apache.guacamole.rest.user;
|
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
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.Context;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import org.apache.guacamole.GuacamoleClientException;
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
|
||||||
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
|
||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
|
||||||
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
|
||||||
import org.apache.guacamole.net.auth.Credentials;
|
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
|
||||||
import org.apache.guacamole.net.auth.User;
|
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
|
||||||
import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException;
|
|
||||||
import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
|
||||||
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
|
|
||||||
import org.apache.guacamole.net.auth.permission.Permission;
|
|
||||||
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
|
||||||
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
|
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
|
||||||
import org.apache.guacamole.rest.APIPatch;
|
|
||||||
import static org.apache.guacamole.rest.APIPatch.Operation.add;
|
|
||||||
import static org.apache.guacamole.rest.APIPatch.Operation.remove;
|
|
||||||
import org.apache.guacamole.rest.ObjectRetrievalService;
|
|
||||||
import org.apache.guacamole.rest.PATCH;
|
|
||||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
|
||||||
import org.apache.guacamole.rest.permission.APIPermissionSet;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A REST Service for handling user CRUD operations.
|
|
||||||
*
|
|
||||||
* @author James Muehlner
|
|
||||||
* @author Michael Jumper
|
|
||||||
*/
|
|
||||||
@Path("/data/{dataSource}/users")
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
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 a specific active connection.
|
|
||||||
*/
|
|
||||||
private static final String ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX = "/activeConnectionPermissions/";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Service for convenient retrieval of objects.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private ObjectRetrievalService retrievalService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a list of users in the given data source (UserContext), 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 authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext from which the users are to be retrieved.
|
|
||||||
*
|
|
||||||
* @param permissions
|
|
||||||
* The set of permissions to filter with. A user must have one or more
|
|
||||||
* of these permissions for a user to appear in the result.
|
|
||||||
* If null, no filtering will be performed.
|
|
||||||
*
|
|
||||||
* @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
|
|
||||||
public List<APIUser> getUsers(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@QueryParam("permission") List<ObjectPermission.Type> permissions)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// An admin user has access to any user
|
|
||||||
User self = userContext.self();
|
|
||||||
SystemPermissionSet systemPermissions = self.getSystemPermissions();
|
|
||||||
boolean isAdmin = systemPermissions.hasPermission(SystemPermission.Type.ADMINISTER);
|
|
||||||
|
|
||||||
// Get the directory
|
|
||||||
Directory<User> userDirectory = userContext.getUserDirectory();
|
|
||||||
|
|
||||||
// Filter users, if requested
|
|
||||||
Collection<String> userIdentifiers = userDirectory.getIdentifiers();
|
|
||||||
if (!isAdmin && permissions != null && !permissions.isEmpty()) {
|
|
||||||
ObjectPermissionSet userPermissions = self.getUserPermissions();
|
|
||||||
userIdentifiers = userPermissions.getAccessibleObjects(permissions, userIdentifiers);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve all users, converting to API users
|
|
||||||
List<APIUser> apiUsers = new ArrayList<APIUser>();
|
|
||||||
for (User user : userDirectory.getAll(userIdentifiers))
|
|
||||||
apiUsers.add(new APIUser(user));
|
|
||||||
|
|
||||||
return apiUsers;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves an individual user.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext from which the requested user is to be retrieved.
|
|
||||||
*
|
|
||||||
* @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("/{username}")
|
|
||||||
public APIUser getUser(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("username") String username)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
|
|
||||||
// Retrieve the requested user
|
|
||||||
User user = retrievalService.retrieveUser(session, authProviderIdentifier, username);
|
|
||||||
return new APIUser(user);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new user and returns the user that was created.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext in which the requested user is to be created.
|
|
||||||
*
|
|
||||||
* @param user
|
|
||||||
* The new user to create.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If a problem is encountered while creating the user.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The newly created user.
|
|
||||||
*/
|
|
||||||
@POST
|
|
||||||
public APIUser createUser(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier, APIUser user)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Get the directory
|
|
||||||
Directory<User> userDirectory = userContext.getUserDirectory();
|
|
||||||
|
|
||||||
// Randomly set the password if it wasn't provided
|
|
||||||
if (user.getPassword() == null)
|
|
||||||
user.setPassword(UUID.randomUUID().toString());
|
|
||||||
|
|
||||||
// Create the user
|
|
||||||
userDirectory.add(new APIUserWrapper(user));
|
|
||||||
|
|
||||||
return user;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates an individual existing user.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext in which the requested user is to be updated.
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*/
|
|
||||||
@PUT
|
|
||||||
@Path("/{username}")
|
|
||||||
public void updateUser(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("username") String username, APIUser user)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Get the directory
|
|
||||||
Directory<User> userDirectory = userContext.getUserDirectory();
|
|
||||||
|
|
||||||
// Validate data and path are sane
|
|
||||||
if (!user.getUsername().equals(username))
|
|
||||||
throw new GuacamoleClientException("Username in path does not match username provided JSON data.");
|
|
||||||
|
|
||||||
// A user may not use this endpoint to modify himself
|
|
||||||
if (userContext.self().getIdentifier().equals(user.getUsername()))
|
|
||||||
throw new GuacamoleSecurityException("Permission denied.");
|
|
||||||
|
|
||||||
// Get the user
|
|
||||||
User existingUser = retrievalService.retrieveUser(userContext, username);
|
|
||||||
|
|
||||||
// Do not update the user password if no password was provided
|
|
||||||
if (user.getPassword() != null)
|
|
||||||
existingUser.setPassword(user.getPassword());
|
|
||||||
|
|
||||||
// Update user attributes
|
|
||||||
existingUser.setAttributes(user.getAttributes());
|
|
||||||
|
|
||||||
// Update the user
|
|
||||||
userDirectory.update(existingUser);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the password for an individual existing user.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext in which the requested user is to be updated.
|
|
||||||
*
|
|
||||||
* @param username
|
|
||||||
* The username of the user to update.
|
|
||||||
*
|
|
||||||
* @param userPasswordUpdate
|
|
||||||
* The object containing the old password for the user, as well as the
|
|
||||||
* new password to set for that user.
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* The HttpServletRequest associated with the password update attempt.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while updating the user's password.
|
|
||||||
*/
|
|
||||||
@PUT
|
|
||||||
@Path("/{username}/password")
|
|
||||||
public void updatePassword(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("username") String username,
|
|
||||||
APIUserPasswordUpdate userPasswordUpdate,
|
|
||||||
@Context HttpServletRequest request) throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Build credentials
|
|
||||||
Credentials credentials = new Credentials();
|
|
||||||
credentials.setUsername(username);
|
|
||||||
credentials.setPassword(userPasswordUpdate.getOldPassword());
|
|
||||||
credentials.setRequest(request);
|
|
||||||
credentials.setSession(request.getSession(true));
|
|
||||||
|
|
||||||
// Verify that the old password was correct
|
|
||||||
try {
|
|
||||||
AuthenticationProvider authProvider = userContext.getAuthenticationProvider();
|
|
||||||
if (authProvider.authenticateUser(credentials) == null)
|
|
||||||
throw new GuacamoleSecurityException("Permission denied.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass through any credentials exceptions as simple permission denied
|
|
||||||
catch (GuacamoleCredentialsException e) {
|
|
||||||
throw new GuacamoleSecurityException("Permission denied.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the user directory
|
|
||||||
Directory<User> userDirectory = userContext.getUserDirectory();
|
|
||||||
|
|
||||||
// Get the user that we want to updates
|
|
||||||
User user = retrievalService.retrieveUser(userContext, username);
|
|
||||||
|
|
||||||
// Set password to the newly provided one
|
|
||||||
user.setPassword(userPasswordUpdate.getNewPassword());
|
|
||||||
|
|
||||||
// Update the user
|
|
||||||
userDirectory.update(user);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes an individual existing user.
|
|
||||||
*
|
|
||||||
* @param authToken
|
|
||||||
* The authentication token that is used to authenticate the user
|
|
||||||
* performing the operation.
|
|
||||||
*
|
|
||||||
* @param authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext from which the requested user is to be deleted.
|
|
||||||
*
|
|
||||||
* @param username
|
|
||||||
* The username of the user to delete.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If an error occurs while deleting the user.
|
|
||||||
*/
|
|
||||||
@DELETE
|
|
||||||
@Path("/{username}")
|
|
||||||
public void deleteUser(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("username") String username)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Get the directory
|
|
||||||
Directory<User> userDirectory = userContext.getUserDirectory();
|
|
||||||
|
|
||||||
// Get the user
|
|
||||||
User existingUser = userDirectory.get(username);
|
|
||||||
if (existingUser == null)
|
|
||||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
|
|
||||||
|
|
||||||
// Delete the user
|
|
||||||
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 authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext in which the requested user is to be found.
|
|
||||||
*
|
|
||||||
* @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")
|
|
||||||
public APIPermissionSet getPermissions(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("username") String username)
|
|
||||||
throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
User user;
|
|
||||||
|
|
||||||
// If username is own username, just use self - might not have query permissions
|
|
||||||
if (userContext.self().getIdentifier().equals(username))
|
|
||||||
user = userContext.self();
|
|
||||||
|
|
||||||
// If not self, query corresponding user from directory
|
|
||||||
else {
|
|
||||||
user = userContext.getUserDirectory().get(username);
|
|
||||||
if (user == null)
|
|
||||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new APIPermissionSet(user);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the given permission set patch by queuing an add or remove
|
|
||||||
* operation for the given permission based on the given patch operation.
|
|
||||||
*
|
|
||||||
* @param <PermissionType>
|
|
||||||
* The type of permission stored within the permission set.
|
|
||||||
*
|
|
||||||
* @param operation
|
|
||||||
* The patch operation to perform.
|
|
||||||
*
|
|
||||||
* @param permissionSetPatch
|
|
||||||
* The permission set patch being modified.
|
|
||||||
*
|
|
||||||
* @param permission
|
|
||||||
* The permission being added or removed from the set.
|
|
||||||
*
|
|
||||||
* @throws GuacamoleException
|
|
||||||
* If the requested patch operation is not supported.
|
|
||||||
*/
|
|
||||||
private <PermissionType extends Permission> void updatePermissionSet(
|
|
||||||
APIPatch.Operation operation,
|
|
||||||
PermissionSetPatch<PermissionType> permissionSetPatch,
|
|
||||||
PermissionType permission) throws GuacamoleException {
|
|
||||||
|
|
||||||
// Add or remove permission based on operation
|
|
||||||
switch (operation) {
|
|
||||||
|
|
||||||
// Add permission
|
|
||||||
case add:
|
|
||||||
permissionSetPatch.addPermission(permission);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Remove permission
|
|
||||||
case remove:
|
|
||||||
permissionSetPatch.removePermission(permission);
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Unsupported patch operation
|
|
||||||
default:
|
|
||||||
throw new GuacamoleClientException("Unsupported patch operation: \"" + operation + "\"");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 authProviderIdentifier
|
|
||||||
* The unique identifier of the AuthenticationProvider associated with
|
|
||||||
* the UserContext in which the requested user is to be found.
|
|
||||||
*
|
|
||||||
* @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")
|
|
||||||
public void patchPermissions(@QueryParam("token") String authToken,
|
|
||||||
@PathParam("dataSource") String authProviderIdentifier,
|
|
||||||
@PathParam("username") String username,
|
|
||||||
List<APIPatch<String>> patches) throws GuacamoleException {
|
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
|
||||||
|
|
||||||
// Get the user
|
|
||||||
User user = userContext.getUserDirectory().get(username);
|
|
||||||
if (user == null)
|
|
||||||
throw new GuacamoleResourceNotFoundException("No such user: \"" + username + "\"");
|
|
||||||
|
|
||||||
// Permission patches for all types of permissions
|
|
||||||
PermissionSetPatch<ObjectPermission> connectionPermissionPatch = new PermissionSetPatch<ObjectPermission>();
|
|
||||||
PermissionSetPatch<ObjectPermission> connectionGroupPermissionPatch = new PermissionSetPatch<ObjectPermission>();
|
|
||||||
PermissionSetPatch<ObjectPermission> activeConnectionPermissionPatch = new PermissionSetPatch<ObjectPermission>();
|
|
||||||
PermissionSetPatch<ObjectPermission> userPermissionPatch = new PermissionSetPatch<ObjectPermission>();
|
|
||||||
PermissionSetPatch<SystemPermission> systemPermissionPatch = new PermissionSetPatch<SystemPermission>();
|
|
||||||
|
|
||||||
// Apply all patch operations individually
|
|
||||||
for (APIPatch<String> patch : patches) {
|
|
||||||
|
|
||||||
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 and update corresponding permission
|
|
||||||
ObjectPermission permission = new ObjectPermission(type, identifier);
|
|
||||||
updatePermissionSet(patch.getOp(), connectionPermissionPatch, permission);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 and update corresponding permission
|
|
||||||
ObjectPermission permission = new ObjectPermission(type, identifier);
|
|
||||||
updatePermissionSet(patch.getOp(), connectionGroupPermissionPatch, permission);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create active connection permission if path has active connection prefix
|
|
||||||
else if (path.startsWith(ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX)) {
|
|
||||||
|
|
||||||
// Get identifier and type from patch operation
|
|
||||||
String identifier = path.substring(ACTIVE_CONNECTION_PERMISSION_PATCH_PATH_PREFIX.length());
|
|
||||||
ObjectPermission.Type type = ObjectPermission.Type.valueOf(patch.getValue());
|
|
||||||
|
|
||||||
// Create and update corresponding permission
|
|
||||||
ObjectPermission permission = new ObjectPermission(type, identifier);
|
|
||||||
updatePermissionSet(patch.getOp(), activeConnectionPermissionPatch, permission);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 and update corresponding permission
|
|
||||||
ObjectPermission permission = new ObjectPermission(type, identifier);
|
|
||||||
updatePermissionSet(patch.getOp(), userPermissionPatch, permission);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create system permission if path is system path
|
|
||||||
else if (path.equals(SYSTEM_PERMISSION_PATCH_PATH)) {
|
|
||||||
|
|
||||||
// Get identifier and type from patch operation
|
|
||||||
SystemPermission.Type type = SystemPermission.Type.valueOf(patch.getValue());
|
|
||||||
|
|
||||||
// Create and update corresponding permission
|
|
||||||
SystemPermission permission = new SystemPermission(type);
|
|
||||||
updatePermissionSet(patch.getOp(), systemPermissionPatch, permission);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, the path is not supported
|
|
||||||
else
|
|
||||||
throw new GuacamoleClientException("Unsupported patch path: \"" + path + "\"");
|
|
||||||
|
|
||||||
} // end for each patch operation
|
|
||||||
|
|
||||||
// Save the permission changes
|
|
||||||
connectionPermissionPatch.apply(user.getConnectionPermissions());
|
|
||||||
connectionGroupPermissionPatch.apply(user.getConnectionGroupPermissions());
|
|
||||||
activeConnectionPermissionPatch.apply(user.getActiveConnectionPermissions());
|
|
||||||
userPermissionPatch.apply(user.getUserPermissions());
|
|
||||||
systemPermissionPatch.apply(user.getSystemPermissions());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.rest.user;
|
||||||
|
|
||||||
|
import com.google.inject.assistedinject.Assisted;
|
||||||
|
import com.google.inject.assistedinject.AssistedInject;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.PUT;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
|
import org.apache.guacamole.net.auth.User;
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
|
import org.apache.guacamole.rest.permission.PermissionSetResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A REST resource which abstracts the operations available on an existing
|
||||||
|
* User.
|
||||||
|
*
|
||||||
|
* @author Michael Jumper
|
||||||
|
*/
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
|
public class UserResource
|
||||||
|
extends DirectoryObjectResource<User, APIUser> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UserContext associated with the Directory which contains the User
|
||||||
|
* exposed by this resource.
|
||||||
|
*/
|
||||||
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Directory which contains the User object represented by this
|
||||||
|
* UserResource.
|
||||||
|
*/
|
||||||
|
private final Directory<User> directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The User object represented by this UserResource.
|
||||||
|
*/
|
||||||
|
private final User user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new UserResource which exposes the operations and subresources
|
||||||
|
* available for the given User.
|
||||||
|
*
|
||||||
|
* @param userContext
|
||||||
|
* The UserContext associated with the given Directory.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The Directory which contains the given User.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* The User that this UserResource should represent.
|
||||||
|
*
|
||||||
|
* @param translator
|
||||||
|
* A DirectoryObjectTranslator implementation which handles Users.
|
||||||
|
*/
|
||||||
|
@AssistedInject
|
||||||
|
public UserResource(@Assisted UserContext userContext,
|
||||||
|
@Assisted Directory<User> directory,
|
||||||
|
@Assisted User user,
|
||||||
|
DirectoryObjectTranslator<User, APIUser> translator) {
|
||||||
|
super(directory, user, translator);
|
||||||
|
this.userContext = userContext;
|
||||||
|
this.directory = directory;
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateObject(APIUser modifiedObject) throws GuacamoleException {
|
||||||
|
|
||||||
|
// A user may not use this endpoint to modify himself
|
||||||
|
if (userContext.self().getIdentifier().equals(modifiedObject.getUsername()))
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
|
||||||
|
super.updateObject(modifiedObject);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the password for an individual existing user.
|
||||||
|
*
|
||||||
|
* @param userPasswordUpdate
|
||||||
|
* The object containing the old password for the user, as well as the
|
||||||
|
* new password to set for that user.
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* The HttpServletRequest associated with the password update attempt.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If an error occurs while updating the user's password.
|
||||||
|
*/
|
||||||
|
@PUT
|
||||||
|
@Path("password")
|
||||||
|
public void updatePassword(APIUserPasswordUpdate userPasswordUpdate,
|
||||||
|
@Context HttpServletRequest request) throws GuacamoleException {
|
||||||
|
|
||||||
|
// Build credentials
|
||||||
|
Credentials credentials = new Credentials();
|
||||||
|
credentials.setUsername(user.getIdentifier());
|
||||||
|
credentials.setPassword(userPasswordUpdate.getOldPassword());
|
||||||
|
credentials.setRequest(request);
|
||||||
|
credentials.setSession(request.getSession(true));
|
||||||
|
|
||||||
|
// Verify that the old password was correct
|
||||||
|
try {
|
||||||
|
AuthenticationProvider authProvider = userContext.getAuthenticationProvider();
|
||||||
|
if (authProvider.authenticateUser(credentials) == null)
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass through any credentials exceptions as simple permission denied
|
||||||
|
catch (GuacamoleCredentialsException e) {
|
||||||
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set password to the newly provided one
|
||||||
|
user.setPassword(userPasswordUpdate.getNewPassword());
|
||||||
|
directory.update(user);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a resource which abstracts operations available on the overall
|
||||||
|
* permissions granted to the User represented by this UserResource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A resource which representing the permissions granted to the User
|
||||||
|
* represented by this UserResource.
|
||||||
|
*/
|
||||||
|
@Path("permissions")
|
||||||
|
public PermissionSetResource getPermissions() {
|
||||||
|
return new PermissionSetResource(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -31,7 +31,6 @@ import org.apache.guacamole.net.auth.Connection;
|
|||||||
import org.apache.guacamole.net.auth.ConnectionGroup;
|
import org.apache.guacamole.net.auth.ConnectionGroup;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
import org.apache.guacamole.rest.ObjectRetrievalService;
|
|
||||||
import org.apache.guacamole.rest.auth.AuthenticationService;
|
import org.apache.guacamole.rest.auth.AuthenticationService;
|
||||||
import org.apache.guacamole.protocol.GuacamoleClientInformation;
|
import org.apache.guacamole.protocol.GuacamoleClientInformation;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -61,12 +60,6 @@ public class TunnelRequestService {
|
|||||||
@Inject
|
@Inject
|
||||||
private AuthenticationService authenticationService;
|
private AuthenticationService authenticationService;
|
||||||
|
|
||||||
/**
|
|
||||||
* Service for convenient retrieval of objects.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private ObjectRetrievalService retrievalService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads and returns the client information provided within the given
|
* Reads and returns the client information provided within the given
|
||||||
* request.
|
* request.
|
||||||
@@ -327,7 +320,7 @@ public class TunnelRequestService {
|
|||||||
GuacamoleClientInformation info = getClientInformation(request);
|
GuacamoleClientInformation info = getClientInformation(request);
|
||||||
|
|
||||||
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
GuacamoleSession session = authenticationService.getGuacamoleSession(authToken);
|
||||||
UserContext userContext = retrievalService.retrieveUserContext(session, authProviderIdentifier);
|
UserContext userContext = session.getUserContext(authProviderIdentifier);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@@ -60,7 +60,7 @@ angular.module('rest').factory('activeConnectionService', ['$injector',
|
|||||||
// Retrieve tunnels
|
// Retrieve tunnels
|
||||||
return $http({
|
return $http({
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/activeConnections',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/activeConnections',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ angular.module('rest').factory('activeConnectionService', ['$injector',
|
|||||||
// Perform active connection deletion via PATCH
|
// Perform active connection deletion via PATCH
|
||||||
return $http({
|
return $http({
|
||||||
method : 'PATCH',
|
method : 'PATCH',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/activeConnections',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/activeConnections',
|
||||||
params : httpParameters,
|
params : httpParameters,
|
||||||
data : activeConnectionPatch
|
data : activeConnectionPatch
|
||||||
});
|
});
|
||||||
|
@@ -73,7 +73,7 @@ angular.module('rest').factory('connectionGroupService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.connections,
|
cache : cacheService.connections,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connectionGroups/' + encodeURIComponent(connectionGroupID) + '/tree',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connectionGroups/' + encodeURIComponent(connectionGroupID) + '/tree',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ angular.module('rest').factory('connectionGroupService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.connections,
|
cache : cacheService.connections,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connectionGroups/' + encodeURIComponent(connectionGroupID),
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connectionGroups/' + encodeURIComponent(connectionGroupID),
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ angular.module('rest').factory('connectionGroupService', ['$injector',
|
|||||||
if (!connectionGroup.identifier) {
|
if (!connectionGroup.identifier) {
|
||||||
return $http({
|
return $http({
|
||||||
method : 'POST',
|
method : 'POST',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connectionGroups',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connectionGroups',
|
||||||
params : httpParameters,
|
params : httpParameters,
|
||||||
data : connectionGroup
|
data : connectionGroup
|
||||||
})
|
})
|
||||||
@@ -152,7 +152,7 @@ angular.module('rest').factory('connectionGroupService', ['$injector',
|
|||||||
else {
|
else {
|
||||||
return $http({
|
return $http({
|
||||||
method : 'PUT',
|
method : 'PUT',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connectionGroups/' + encodeURIComponent(connectionGroup.identifier),
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connectionGroups/' + encodeURIComponent(connectionGroup.identifier),
|
||||||
params : httpParameters,
|
params : httpParameters,
|
||||||
data : connectionGroup
|
data : connectionGroup
|
||||||
})
|
})
|
||||||
@@ -185,7 +185,7 @@ angular.module('rest').factory('connectionGroupService', ['$injector',
|
|||||||
// Delete connection group
|
// Delete connection group
|
||||||
return $http({
|
return $http({
|
||||||
method : 'DELETE',
|
method : 'DELETE',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connectionGroups/' + encodeURIComponent(connectionGroup.identifier),
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connectionGroups/' + encodeURIComponent(connectionGroup.identifier),
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -56,7 +56,7 @@ angular.module('rest').factory('connectionService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.connections,
|
cache : cacheService.connections,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connections/' + encodeURIComponent(id),
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connections/' + encodeURIComponent(id),
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ angular.module('rest').factory('connectionService', ['$injector',
|
|||||||
// Retrieve connection history
|
// Retrieve connection history
|
||||||
return $http({
|
return $http({
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connections/' + encodeURIComponent(id) + '/history',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connections/' + encodeURIComponent(id) + '/history',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ angular.module('rest').factory('connectionService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.connections,
|
cache : cacheService.connections,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connections/' + encodeURIComponent(id) + '/parameters',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connections/' + encodeURIComponent(id) + '/parameters',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ angular.module('rest').factory('connectionService', ['$injector',
|
|||||||
if (!connection.identifier) {
|
if (!connection.identifier) {
|
||||||
return $http({
|
return $http({
|
||||||
method : 'POST',
|
method : 'POST',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connections',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connections',
|
||||||
params : httpParameters,
|
params : httpParameters,
|
||||||
data : connection
|
data : connection
|
||||||
})
|
})
|
||||||
@@ -159,7 +159,7 @@ angular.module('rest').factory('connectionService', ['$injector',
|
|||||||
else {
|
else {
|
||||||
return $http({
|
return $http({
|
||||||
method : 'PUT',
|
method : 'PUT',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connections/' + encodeURIComponent(connection.identifier),
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connections/' + encodeURIComponent(connection.identifier),
|
||||||
params : httpParameters,
|
params : httpParameters,
|
||||||
data : connection
|
data : connection
|
||||||
})
|
})
|
||||||
@@ -192,7 +192,7 @@ angular.module('rest').factory('connectionService', ['$injector',
|
|||||||
// Delete connection
|
// Delete connection
|
||||||
return $http({
|
return $http({
|
||||||
method : 'DELETE',
|
method : 'DELETE',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/connections/' + encodeURIComponent(connection.identifier),
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/connections/' + encodeURIComponent(connection.identifier),
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@@ -76,7 +76,7 @@ angular.module('rest').factory('historyService', ['$injector',
|
|||||||
// Retrieve connection history
|
// Retrieve connection history
|
||||||
return $http({
|
return $http({
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/history/connections',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/history/connections',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -62,7 +62,7 @@ angular.module('rest').factory('permissionService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.users,
|
cache : cacheService.users,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(userID) + '/permissions',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(userID) + '/permissions',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ angular.module('rest').factory('permissionService', ['$injector',
|
|||||||
// Patch user permissions
|
// Patch user permissions
|
||||||
return $http({
|
return $http({
|
||||||
method : 'PATCH',
|
method : 'PATCH',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(userID) + '/permissions',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(userID) + '/permissions',
|
||||||
params : httpParameters,
|
params : httpParameters,
|
||||||
data : permissionPatch
|
data : permissionPatch
|
||||||
})
|
})
|
||||||
|
@@ -58,7 +58,7 @@ angular.module('rest').factory('schemaService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.schema,
|
cache : cacheService.schema,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/schema/' + encodeURIComponent(dataSource) + '/users/attributes',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/schema/userAttributes',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ angular.module('rest').factory('schemaService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.schema,
|
cache : cacheService.schema,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/schema/' + encodeURIComponent(dataSource) + '/connections/attributes',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/schema/connectionAttributes',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ angular.module('rest').factory('schemaService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.schema,
|
cache : cacheService.schema,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/schema/' + encodeURIComponent(dataSource) + '/connectionGroups/attributes',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/schema/connectionGroupAttributes',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ angular.module('rest').factory('schemaService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.schema,
|
cache : cacheService.schema,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/schema/' + encodeURIComponent(dataSource) + '/protocols',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/schema/protocols',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -62,7 +62,7 @@ angular.module('rest').factory('tunnelService', ['$injector',
|
|||||||
// Retrieve tunnels
|
// Retrieve tunnels
|
||||||
return $http({
|
return $http({
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/tunnels',
|
url : 'api/session/tunnels',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ angular.module('rest').factory('tunnelService', ['$injector',
|
|||||||
// Build download URL
|
// Build download URL
|
||||||
var url = $window.location.origin
|
var url = $window.location.origin
|
||||||
+ $window.location.pathname
|
+ $window.location.pathname
|
||||||
+ 'api/tunnels/' + encodeURIComponent(tunnel)
|
+ 'api/session/tunnels/' + encodeURIComponent(tunnel)
|
||||||
+ '/streams/' + encodeURIComponent(stream.index)
|
+ '/streams/' + encodeURIComponent(stream.index)
|
||||||
+ '/' + encodeURIComponent(filename)
|
+ '/' + encodeURIComponent(filename)
|
||||||
+ '?token=' + encodeURIComponent(authenticationService.getCurrentToken());
|
+ '?token=' + encodeURIComponent(authenticationService.getCurrentToken());
|
||||||
@@ -163,7 +163,7 @@ angular.module('rest').factory('tunnelService', ['$injector',
|
|||||||
// Build upload URL
|
// Build upload URL
|
||||||
var url = $window.location.origin
|
var url = $window.location.origin
|
||||||
+ $window.location.pathname
|
+ $window.location.pathname
|
||||||
+ 'api/tunnels/' + encodeURIComponent(tunnel)
|
+ 'api/session/tunnels/' + encodeURIComponent(tunnel)
|
||||||
+ '/streams/' + encodeURIComponent(stream.index)
|
+ '/streams/' + encodeURIComponent(stream.index)
|
||||||
+ '/' + encodeURIComponent(file.name)
|
+ '/' + encodeURIComponent(file.name)
|
||||||
+ '?token=' + encodeURIComponent(authenticationService.getCurrentToken());
|
+ '?token=' + encodeURIComponent(authenticationService.getCurrentToken());
|
||||||
|
@@ -50,9 +50,10 @@ angular.module('rest').factory('userService', ['$injector',
|
|||||||
* If null, no filtering will be performed. Valid values are listed
|
* If null, no filtering will be performed. Valid values are listed
|
||||||
* within PermissionSet.ObjectType.
|
* within PermissionSet.ObjectType.
|
||||||
*
|
*
|
||||||
* @returns {Promise.<User[]>}
|
* @returns {Promise.<Object.<String, User>>}
|
||||||
* A promise which will resolve with an array of @link{User} objects
|
* A promise which will resolve with a map of @link{User} objects
|
||||||
* upon success.
|
* where each key is the identifier (username) of the corresponding
|
||||||
|
* user.
|
||||||
*/
|
*/
|
||||||
service.getUsers = function getUsers(dataSource, permissionTypes) {
|
service.getUsers = function getUsers(dataSource, permissionTypes) {
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ angular.module('rest').factory('userService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.users,
|
cache : cacheService.users,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/users',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users',
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -102,7 +103,7 @@ angular.module('rest').factory('userService', ['$injector',
|
|||||||
return $http({
|
return $http({
|
||||||
cache : cacheService.users,
|
cache : cacheService.users,
|
||||||
method : 'GET',
|
method : 'GET',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(username),
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(username),
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -134,7 +135,7 @@ angular.module('rest').factory('userService', ['$injector',
|
|||||||
// Delete user
|
// Delete user
|
||||||
return $http({
|
return $http({
|
||||||
method : 'DELETE',
|
method : 'DELETE',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(user.username),
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(user.username),
|
||||||
params : httpParameters
|
params : httpParameters
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -172,7 +173,7 @@ angular.module('rest').factory('userService', ['$injector',
|
|||||||
// Create user
|
// Create user
|
||||||
return $http({
|
return $http({
|
||||||
method : 'POST',
|
method : 'POST',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/users',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users',
|
||||||
params : httpParameters,
|
params : httpParameters,
|
||||||
data : user
|
data : user
|
||||||
})
|
})
|
||||||
@@ -210,7 +211,7 @@ angular.module('rest').factory('userService', ['$injector',
|
|||||||
// Update user
|
// Update user
|
||||||
return $http({
|
return $http({
|
||||||
method : 'PUT',
|
method : 'PUT',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(user.username),
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(user.username),
|
||||||
params : httpParameters,
|
params : httpParameters,
|
||||||
data : user
|
data : user
|
||||||
})
|
})
|
||||||
@@ -255,7 +256,7 @@ angular.module('rest').factory('userService', ['$injector',
|
|||||||
// Update user password
|
// Update user password
|
||||||
return $http({
|
return $http({
|
||||||
method : 'PUT',
|
method : 'PUT',
|
||||||
url : 'api/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(username) + '/password',
|
url : 'api/session/data/' + encodeURIComponent(dataSource) + '/users/' + encodeURIComponent(username) + '/password',
|
||||||
params : httpParameters,
|
params : httpParameters,
|
||||||
data : new UserPasswordUpdate({
|
data : new UserPasswordUpdate({
|
||||||
oldPassword : oldPassword,
|
oldPassword : oldPassword,
|
||||||
|
@@ -227,14 +227,14 @@ angular.module('settings').directive('guacSettingsUsers', [function guacSettings
|
|||||||
PermissionSet.ObjectPermissionType.DELETE
|
PermissionSet.ObjectPermissionType.DELETE
|
||||||
]);
|
]);
|
||||||
|
|
||||||
userPromise.then(function usersReceived(userArrays) {
|
userPromise.then(function usersReceived(allUsers) {
|
||||||
|
|
||||||
var addedUsers = {};
|
var addedUsers = {};
|
||||||
$scope.manageableUsers = [];
|
$scope.manageableUsers = [];
|
||||||
|
|
||||||
// For each user in each data source
|
// For each user in each data source
|
||||||
angular.forEach(dataSources, function addUserList(dataSource) {
|
angular.forEach(dataSources, function addUserList(dataSource) {
|
||||||
angular.forEach(userArrays[dataSource], function addUser(user) {
|
angular.forEach(allUsers[dataSource], function addUser(user) {
|
||||||
|
|
||||||
// Do not add the same user twice
|
// Do not add the same user twice
|
||||||
if (addedUsers[user.username])
|
if (addedUsers[user.username])
|
||||||
|
Reference in New Issue
Block a user