mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-06 05:07:41 +00:00
GUACAMOLE-1224: Merge updated event handling and global logging improvements.
This commit is contained in:
@@ -21,7 +21,6 @@ package org.apache.guacamole.auth.ban.status;
|
|||||||
|
|
||||||
import com.github.benmanes.caffeine.cache.Cache;
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleServerException;
|
import org.apache.guacamole.GuacamoleServerException;
|
||||||
import org.apache.guacamole.language.TranslatableGuacamoleClientTooManyException;
|
import org.apache.guacamole.language.TranslatableGuacamoleClientTooManyException;
|
||||||
@@ -88,40 +87,6 @@ public class InMemoryAuthenticationFailureTracker implements AuthenticationFailu
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the given Credentials do not contain any specific
|
|
||||||
* authentication parameters, including HTTP parameters. An authentication
|
|
||||||
* request that contains no parameters whatsoever will tend to be the
|
|
||||||
* first, anonymous, credential-less authentication attempt that results in
|
|
||||||
* the initial login screen rendering.
|
|
||||||
*
|
|
||||||
* @param credentials
|
|
||||||
* The Credentials object to test.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* true if the given Credentials contain no authentication parameters
|
|
||||||
* whatsoever, false otherwise.
|
|
||||||
*/
|
|
||||||
private boolean isEmpty(Credentials credentials) {
|
|
||||||
|
|
||||||
// An authentication request that contains an explicit username or
|
|
||||||
// password (even if blank) is non-empty, regardless of how the values
|
|
||||||
// were passed
|
|
||||||
if (credentials.getUsername() != null || credentials.getPassword() != null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// All further tests depend on HTTP request details
|
|
||||||
HttpServletRequest request = credentials.getRequest();
|
|
||||||
if (request == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// An authentication request is non-empty if it contains any HTTP
|
|
||||||
// parameters at all or contains an authentication token
|
|
||||||
return !request.getParameterNames().hasMoreElements()
|
|
||||||
&& request.getHeader("Guacamole-Token") == null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reports that the given address has just failed to authenticate and
|
* Reports that the given address has just failed to authenticate and
|
||||||
* returns the AuthenticationFailureStatus that represents that failure. If
|
* returns the AuthenticationFailureStatus that represents that failure. If
|
||||||
@@ -168,7 +133,7 @@ public class InMemoryAuthenticationFailureTracker implements AuthenticationFailu
|
|||||||
boolean failed) throws GuacamoleException {
|
boolean failed) throws GuacamoleException {
|
||||||
|
|
||||||
// Ignore requests that do not contain explicit parameters of any kind
|
// Ignore requests that do not contain explicit parameters of any kind
|
||||||
if (isEmpty(credentials))
|
if (credentials.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Determine originating address of the authentication request
|
// Determine originating address of the authentication request
|
||||||
|
@@ -34,20 +34,7 @@ import org.apache.guacamole.protocol.GuacamoleConfiguration;
|
|||||||
* backing GuacamoleConfiguration may be intentionally obfuscated or tokenized
|
* backing GuacamoleConfiguration may be intentionally obfuscated or tokenized
|
||||||
* to protect sensitive configuration information.
|
* to protect sensitive configuration information.
|
||||||
*/
|
*/
|
||||||
public interface Connection extends Identifiable, Connectable, Attributes {
|
public interface Connection extends Identifiable, Connectable, Attributes, Nameable {
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name assigned to this Connection.
|
|
||||||
* @return The name assigned to this Connection.
|
|
||||||
*/
|
|
||||||
public String getName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the name assigned to this Connection.
|
|
||||||
*
|
|
||||||
* @param name The name to assign.
|
|
||||||
*/
|
|
||||||
public void setName(String name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the unique identifier of the parent ConnectionGroup for
|
* Returns the unique identifier of the parent ConnectionGroup for
|
||||||
|
@@ -26,7 +26,7 @@ import org.apache.guacamole.GuacamoleException;
|
|||||||
* Represents a connection group, which can contain both other connection groups
|
* Represents a connection group, which can contain both other connection groups
|
||||||
* as well as connections.
|
* as well as connections.
|
||||||
*/
|
*/
|
||||||
public interface ConnectionGroup extends Identifiable, Connectable, Attributes {
|
public interface ConnectionGroup extends Identifiable, Connectable, Attributes, Nameable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All legal types of connection group.
|
* All legal types of connection group.
|
||||||
@@ -51,19 +51,6 @@ public interface ConnectionGroup extends Identifiable, Connectable, Attributes {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the name assigned to this ConnectionGroup.
|
|
||||||
* @return The name assigned to this ConnectionGroup.
|
|
||||||
*/
|
|
||||||
public String getName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the name assigned to this ConnectionGroup.
|
|
||||||
*
|
|
||||||
* @param name The name to assign.
|
|
||||||
*/
|
|
||||||
public void setName(String name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the unique identifier of the parent ConnectionGroup for
|
* Returns the unique identifier of the parent ConnectionGroup for
|
||||||
* this ConnectionGroup.
|
* this ConnectionGroup.
|
||||||
|
@@ -236,4 +236,36 @@ public class Credentials implements Serializable {
|
|||||||
this.remoteHostname = remoteHostname;
|
this.remoteHostname = remoteHostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this Credentials object does not contain any specific
|
||||||
|
* authentication parameters, including HTTP parameters and the HTTP header
|
||||||
|
* used for the authentication token. An authentication request that
|
||||||
|
* contains no parameters whatsoever will tend to be the first, anonymous,
|
||||||
|
* credential-less authentication attempt that results in the initial login
|
||||||
|
* screen rendering.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* true if this Credentials object contains no authentication
|
||||||
|
* parameters whatsoever, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
|
||||||
|
// An authentication request that contains an explicit username or
|
||||||
|
// password (even if blank) is non-empty, regardless of how the values
|
||||||
|
// were passed
|
||||||
|
if (getUsername() != null || getPassword() != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// All further tests depend on HTTP request details
|
||||||
|
HttpServletRequest httpRequest = getRequest();
|
||||||
|
if (httpRequest == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// An authentication request is non-empty if it contains any HTTP
|
||||||
|
// parameters at all or contains an authentication token
|
||||||
|
return !httpRequest.getParameterNames().hasMoreElements()
|
||||||
|
&& httpRequest.getHeader("Guacamole-Token") == null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,104 @@ import org.apache.guacamole.GuacamoleException;
|
|||||||
*/
|
*/
|
||||||
public interface Directory<ObjectType extends Identifiable> {
|
public interface Directory<ObjectType extends Identifiable> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All Directory types that may be found on the {@link UserContext}
|
||||||
|
* interface.
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of a Directory that contains {@link ActiveConnection}
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
ACTIVE_CONNECTION(ActiveConnection.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of a Directory that contains {@link Connection}
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
CONNECTION(Connection.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of a Directory that contains {@link ConnectionGroup}
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
CONNECTION_GROUP(ConnectionGroup.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of a Directory that contains {@link SharingProfile}
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
SHARING_PROFILE(SharingProfile.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of a Directory that contains {@link User} objects.
|
||||||
|
*/
|
||||||
|
USER(User.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of a Directory that contains {@link UserGroup}
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
USER_GROUP(UserGroup.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base class of the type of object stored within the type of
|
||||||
|
* Directory represented by this Directory.Type.
|
||||||
|
*/
|
||||||
|
private final Class<? extends Identifiable> objectType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Directory.Type representing the type of a Directory
|
||||||
|
* that contains only subclasses of the given class.
|
||||||
|
*
|
||||||
|
* @param objectType
|
||||||
|
* The base class of the type of object stored within the type of
|
||||||
|
* Directory represented by this Directory.Type.
|
||||||
|
*/
|
||||||
|
private Type(Class<? extends Identifiable> objectType) {
|
||||||
|
this.objectType = objectType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the base class of the type of object stored within a
|
||||||
|
* {@link Directory} of this type.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The base class of the type of object stored within a
|
||||||
|
* {@link Directory} of this type.
|
||||||
|
*/
|
||||||
|
public Class<? extends Identifiable> getObjectType() {
|
||||||
|
return objectType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Directory.Type representing the type of a Directory that
|
||||||
|
* could contain an object having the given class. The class may be a
|
||||||
|
* subclass of the overall base class of the objects stored within the
|
||||||
|
* Directory.
|
||||||
|
*
|
||||||
|
* @param objectType
|
||||||
|
* The class to determine the Directory.Type of.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The Directory.Type representing the type of a Directory that
|
||||||
|
* could contain an object having the given class, or null if there
|
||||||
|
* is no such Directory available via the UserContext interface.
|
||||||
|
*/
|
||||||
|
public static Type of(Class<? extends Identifiable> objectType) {
|
||||||
|
|
||||||
|
for (Type type : Type.values()) {
|
||||||
|
if (type.getObjectType().isAssignableFrom(objectType))
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the object having the given identifier. Note that changes to
|
* Returns the object having the given identifier. Note that changes to
|
||||||
* the object returned will not necessarily affect the object stored within
|
* the object returned will not necessarily affect the object stored within
|
||||||
|
@@ -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.net.auth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object which has a human-readable, arbitrary name. No requirement is
|
||||||
|
* imposed by this interface regarding whether this name must be unique,
|
||||||
|
* however implementations are free to impose such restrictions.
|
||||||
|
*/
|
||||||
|
public interface Nameable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the human-readable name assigned to this object.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The name assigned to this object.
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the human-readable name assigned to this object.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* The name to assign.
|
||||||
|
*/
|
||||||
|
void setName(String name);
|
||||||
|
|
||||||
|
}
|
@@ -25,23 +25,7 @@ import java.util.Map;
|
|||||||
* Represents the semantics which apply to an existing connection when shared,
|
* Represents the semantics which apply to an existing connection when shared,
|
||||||
* along with a human-readable name and unique identifier.
|
* along with a human-readable name and unique identifier.
|
||||||
*/
|
*/
|
||||||
public interface SharingProfile extends Identifiable, Attributes {
|
public interface SharingProfile extends Identifiable, Attributes, Nameable {
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the human-readable name assigned to this SharingProfile.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The name assigned to this SharingProfile.
|
|
||||||
*/
|
|
||||||
public String getName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the human-readable name assigned to this SharingProfile.
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* The name to assign.
|
|
||||||
*/
|
|
||||||
public void setName(String name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the identifier of the primary connection associated with this
|
* Returns the identifier of the primary connection associated with this
|
||||||
|
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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.net.event;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.net.event.listener.Listener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event that is dispatched when the web application has nearly completely shut
|
||||||
|
* down, including the authentication/authorization portion of extensions. Any
|
||||||
|
* installed extensions are still loaded (such that they may receive this event
|
||||||
|
* via {@link Listener#handleEvent(java.lang.Object)}, but their authentication
|
||||||
|
* providers will have been shut down via {@link AuthenticationProvider#shutdown()},
|
||||||
|
* and resources from user sessions will have been closed and released via
|
||||||
|
* {@link UserContext#invalidate()}.
|
||||||
|
*/
|
||||||
|
public interface ApplicationShutdownEvent {
|
||||||
|
}
|
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.net.event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event that is dispatched when the web application has finished starting up,
|
||||||
|
* including all extensions. This event indicates only that the web application
|
||||||
|
* startup process has completed and all extensions have been loaded. It does
|
||||||
|
* not indicate whether all extensions have started successfully.
|
||||||
|
*/
|
||||||
|
public interface ApplicationStartedEvent {
|
||||||
|
}
|
@@ -42,17 +42,47 @@ public class AuthenticationSuccessEvent implements UserEvent, CredentialEvent,
|
|||||||
*/
|
*/
|
||||||
private final AuthenticatedUser authenticatedUser;
|
private final AuthenticatedUser authenticatedUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the successful authentication attempt represented by this event
|
||||||
|
* is related to an established Guacamole session.
|
||||||
|
*/
|
||||||
|
private final boolean existingSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new AuthenticationSuccessEvent which represents a successful
|
* Creates a new AuthenticationSuccessEvent which represents a successful
|
||||||
* authentication attempt by the user identified by the given
|
* authentication attempt by the user identified by the given
|
||||||
* AuthenticatedUser object.
|
* AuthenticatedUser object. The authentication attempt is presumed to be
|
||||||
|
* a fresh authentication attempt unrelated to an established session (a
|
||||||
|
* login attempt).
|
||||||
*
|
*
|
||||||
* @param authenticatedUser
|
* @param authenticatedUser
|
||||||
* The AuthenticatedUser identifying the user that successfully
|
* The AuthenticatedUser identifying the user that successfully
|
||||||
* authenticated.
|
* authenticated.
|
||||||
*/
|
*/
|
||||||
public AuthenticationSuccessEvent(AuthenticatedUser authenticatedUser) {
|
public AuthenticationSuccessEvent(AuthenticatedUser authenticatedUser) {
|
||||||
|
this(authenticatedUser, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new AuthenticationSuccessEvent which represents a successful
|
||||||
|
* authentication attempt by the user identified by the given
|
||||||
|
* AuthenticatedUser object. Whether the authentication attempt is
|
||||||
|
* related to an established session (a periodic re-authentication attempt
|
||||||
|
* that updates session status) or not (a fresh login attempt) is
|
||||||
|
* determined by the value of the provided flag.
|
||||||
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The AuthenticatedUser identifying the user that successfully
|
||||||
|
* authenticated.
|
||||||
|
*
|
||||||
|
* @param existingSession
|
||||||
|
* Whether this AuthenticationSuccessEvent represents an
|
||||||
|
* re-authentication attempt that updates the status of an established
|
||||||
|
* Guacamole session.
|
||||||
|
*/
|
||||||
|
public AuthenticationSuccessEvent(AuthenticatedUser authenticatedUser, boolean existingSession) {
|
||||||
this.authenticatedUser = authenticatedUser;
|
this.authenticatedUser = authenticatedUser;
|
||||||
|
this.existingSession = existingSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -70,4 +100,21 @@ public class AuthenticationSuccessEvent implements UserEvent, CredentialEvent,
|
|||||||
return getAuthenticatedUser().getAuthenticationProvider();
|
return getAuthenticatedUser().getAuthenticationProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the successful authentication attempt represented by
|
||||||
|
* this event is related to an established Guacamole session. During normal
|
||||||
|
* operation, the Guacamole web application will periodically
|
||||||
|
* re-authenticate with the server to verify its authentication token and
|
||||||
|
* update the session state, in which case the value returned by this
|
||||||
|
* function will be true. If the user was not already authenticated and has
|
||||||
|
* just initially logged in, false is returned.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* true if this AuthenticationSuccessEvent is related to a Guacamole
|
||||||
|
* session that was already established, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isExistingSession() {
|
||||||
|
return existingSession;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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.net.event;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract basis for events which involve a modification made to the objects
|
||||||
|
* within a {@link Directory} through the operations exposed by the Directory
|
||||||
|
* interface.
|
||||||
|
*
|
||||||
|
* @param <ObjectType>
|
||||||
|
* The type of object stored within the {@link Directory}.
|
||||||
|
*/
|
||||||
|
public interface DirectoryEvent<ObjectType extends Identifiable>
|
||||||
|
extends IdentifiableObjectEvent<ObjectType> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of directory operations that may be represented by a
|
||||||
|
* DirectoryEvent.
|
||||||
|
*/
|
||||||
|
public enum Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object was added to the {@link Directory}. The object added can
|
||||||
|
* be accessed with {@link #getObject()}, and its identifier may be
|
||||||
|
* obtained from {@link #getObjectIdentifier()}.
|
||||||
|
*/
|
||||||
|
ADD,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object was retrieved from a {@link Directory}. The object
|
||||||
|
* retrieved can be accessed with {@link #getObject()}, and its
|
||||||
|
* identifier may be obtained from {@link #getObjectIdentifier()}.
|
||||||
|
*/
|
||||||
|
GET,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An existing object within a {@link Directory} was modified. The
|
||||||
|
* modified object can be accessed with {@link #getObject()}, and its
|
||||||
|
* identifier may be obtained from {@link #getObjectIdentifier()}.
|
||||||
|
*/
|
||||||
|
UPDATE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An existing object within a {@link Directory} was deleted/removed.
|
||||||
|
* The identifier of the object that was deleted may be obtained from
|
||||||
|
* {@link #getObjectIdentifier()}. The full object that was deleted
|
||||||
|
* will be made available via {@link #getObject()} if possible, but
|
||||||
|
* this is not guaranteed for deletions.
|
||||||
|
*/
|
||||||
|
REMOVE
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the operation that was performed/attempted.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The operation that was performed or attempted.
|
||||||
|
*/
|
||||||
|
Operation getOperation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* If the object was just created, this will be the identifier of the new
|
||||||
|
* object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
String getObjectIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* Currently, for object creation ({@link Operation#ADD ADD}), retrieval
|
||||||
|
* ({@link Operation#GET GET}), and modification ({@link Operation#UPDATE UPDATE}),
|
||||||
|
* it can be expected that the affected object will be available, however
|
||||||
|
* the caller should verify this regardless. For deletions
|
||||||
|
* ({@link Operation#REMOVE REMOVE}), the object can only be made available for
|
||||||
|
* single deletions, and cannot be made available for batch deletions.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
ObjectType getObject();
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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.net.event;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event that is dispatched whenever a REST API request to create/modify/delete
|
||||||
|
* an object within a {@link Directory} fails. The specific failure is made
|
||||||
|
* available via {@link #getFailure()}.
|
||||||
|
*
|
||||||
|
* @param <ObjectType>
|
||||||
|
* The type of object stored within the {@link Directory}.
|
||||||
|
*/
|
||||||
|
public interface DirectoryFailureEvent<ObjectType extends Identifiable>
|
||||||
|
extends DirectoryEvent<ObjectType>, FailureEvent {
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.net.event;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event that is dispatched whenever a REST API request to create/modify/delete
|
||||||
|
* an object within a {@link Directory} succeeds.
|
||||||
|
*
|
||||||
|
* @param <ObjectType>
|
||||||
|
* The type of object stored within the {@link Directory}.
|
||||||
|
*/
|
||||||
|
public interface DirectorySuccessEvent<ObjectType extends Identifiable>
|
||||||
|
extends DirectoryEvent<ObjectType> {
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.guacamole.net.event;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract basis for events which affect or directly relate to objects that
|
||||||
|
* are {@link Identifiable} and may be stored within a {@link Directory}.
|
||||||
|
*
|
||||||
|
* @param <ObjectType>
|
||||||
|
* The type of object affected or related to the event.
|
||||||
|
*/
|
||||||
|
public interface IdentifiableObjectEvent<ObjectType extends Identifiable>
|
||||||
|
extends AuthenticationProviderEvent, UserEvent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* NOTE: For subclasses of {@link IdentifiableObjectEvent}, this will be the
|
||||||
|
* AuthenticationProvider associated with the affected, {@link Identifiable}
|
||||||
|
* object. This is not necessarily the same as the AuthenticationProvider
|
||||||
|
* that authenticated the user performing the operation, which can be
|
||||||
|
* retrieved via {@link #getAuthenticatedUser()} and
|
||||||
|
* {@link AuthenticatedUser#getAuthenticationProvider()}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
AuthenticationProvider getAuthenticationProvider();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type of {@link Directory} that may contains the object
|
||||||
|
* affected by the operation.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The type of objects stored within the {@link Directory}.
|
||||||
|
*/
|
||||||
|
Directory.Type getDirectoryType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the identifier of the object affected by the operation.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The identifier of the object affected by the operation.
|
||||||
|
*/
|
||||||
|
String getObjectIdentifier();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the object affected by the operation, if available. Whether the
|
||||||
|
* affected object is available is context- and implementation-dependent.
|
||||||
|
* There is no general guarantee across all implementations of this event
|
||||||
|
* that the affected object will be available. If the object is not
|
||||||
|
* available, null is returned.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The object affected by the operation performed, or null if that
|
||||||
|
* object is not available in the context of this event.
|
||||||
|
*/
|
||||||
|
ObjectType getObject();
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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.net.event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event that is dispatched when a user has logged out or their session has
|
||||||
|
* expired.
|
||||||
|
*/
|
||||||
|
public interface UserSessionInvalidatedEvent extends UserEvent {
|
||||||
|
}
|
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* 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.net.auth;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that verifies the functionality provided by the Directory interface.
|
||||||
|
*/
|
||||||
|
public class DirectoryTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Collection of all classes that have associated Directories
|
||||||
|
* available via the UserContext interface. The classes are retrieved
|
||||||
|
* using reflection by enumerating the type parameters of the return types
|
||||||
|
* of all functions that return a Directory.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A Collection of all classes that have associated Directories
|
||||||
|
* available via the UserContext interface.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked") // Verified via calls to isAssignableFrom()
|
||||||
|
private Collection<Class<? extends Identifiable>> getDirectoryTypes() {
|
||||||
|
|
||||||
|
Set<Class<? extends Identifiable>> types = new HashSet<>();
|
||||||
|
|
||||||
|
Method[] methods = UserContext.class.getMethods();
|
||||||
|
for (Method method : methods) {
|
||||||
|
|
||||||
|
if (!Directory.class.isAssignableFrom(method.getReturnType()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Type retType = method.getGenericReturnType();
|
||||||
|
Assert.assertTrue("UserContext functions that return directories "
|
||||||
|
+ "must have proper type parameters for the returned "
|
||||||
|
+ "directory.", retType instanceof ParameterizedType);
|
||||||
|
|
||||||
|
Type[] typeArgs = ((ParameterizedType) retType).getActualTypeArguments();
|
||||||
|
Assert.assertEquals("UserContext functions that return directories "
|
||||||
|
+ "must properly declare exactly one type argument for "
|
||||||
|
+ "those directories.", 1, typeArgs.length);
|
||||||
|
|
||||||
|
Class<?> directoryType = (Class<?>) typeArgs[0];
|
||||||
|
Assert.assertTrue("Directories returned by UserContext functions "
|
||||||
|
+ "must contain subclasses of Identifiable.",
|
||||||
|
Identifiable.class.isAssignableFrom(directoryType));
|
||||||
|
|
||||||
|
types.add((Class<? extends Identifiable>) directoryType);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableSet(types);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that Directory.Type covers the types of all directories exposed
|
||||||
|
* by the UserContext interface.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testTypeCoverage() {
|
||||||
|
|
||||||
|
Collection<Class<? extends Identifiable>> types = getDirectoryTypes();
|
||||||
|
|
||||||
|
Assert.assertEquals("Directory.Type must provide exactly one value "
|
||||||
|
+ "for each type of directory provideed by the UserContext "
|
||||||
|
+ "interface.", types.size(), Directory.Type.values().length);
|
||||||
|
|
||||||
|
for (Class<? extends Identifiable> type : types) {
|
||||||
|
|
||||||
|
Directory.Type dirType = Directory.Type.of(type);
|
||||||
|
Assert.assertNotNull("of() must provide mappings for all directory "
|
||||||
|
+ "types defined on the UserContext interface.", dirType);
|
||||||
|
|
||||||
|
Assert.assertEquals("getObjectType() must return the same base "
|
||||||
|
+ "superclass used by UserContext for all directory "
|
||||||
|
+ "types defined on the UserContext interface.", type,
|
||||||
|
dirType.getObjectType());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that each type declared by Directory.Type exposes an
|
||||||
|
* associated class via getObjectType() which then maps back to the same
|
||||||
|
* type via Directory.Type.of().
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testTypeIdentity() {
|
||||||
|
for (Directory.Type dirType : Directory.Type.values()) {
|
||||||
|
Assert.assertEquals("For all defined directory types, "
|
||||||
|
+ "Directory.Type.of(theType.getObjectType()) must "
|
||||||
|
+ "correctly map back to theType.", dirType,
|
||||||
|
Directory.Type.of(dirType.getObjectType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -35,11 +35,14 @@ import org.apache.guacamole.environment.LocalEnvironment;
|
|||||||
import org.apache.guacamole.extension.ExtensionModule;
|
import org.apache.guacamole.extension.ExtensionModule;
|
||||||
import org.apache.guacamole.log.LogModule;
|
import org.apache.guacamole.log.LogModule;
|
||||||
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
|
import org.apache.guacamole.net.event.ApplicationShutdownEvent;
|
||||||
|
import org.apache.guacamole.net.event.ApplicationStartedEvent;
|
||||||
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
|
import org.apache.guacamole.properties.BooleanGuacamoleProperty;
|
||||||
import org.apache.guacamole.properties.FileGuacamoleProperties;
|
import org.apache.guacamole.properties.FileGuacamoleProperties;
|
||||||
import org.apache.guacamole.rest.RESTServiceModule;
|
import org.apache.guacamole.rest.RESTServiceModule;
|
||||||
import org.apache.guacamole.rest.auth.HashTokenSessionMap;
|
import org.apache.guacamole.rest.auth.HashTokenSessionMap;
|
||||||
import org.apache.guacamole.rest.auth.TokenSessionMap;
|
import org.apache.guacamole.rest.auth.TokenSessionMap;
|
||||||
|
import org.apache.guacamole.rest.event.ListenerService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -125,7 +128,13 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener
|
|||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
private List<File> temporaryFiles;
|
private List<File> temporaryFiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for dispatching events to registered listeners.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ListenerService listenerService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal reference to the Guice injector that was lazily created when
|
* Internal reference to the Guice injector that was lazily created when
|
||||||
* getInjector() was first invoked.
|
* getInjector() was first invoked.
|
||||||
@@ -179,6 +188,17 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener
|
|||||||
// Store reference to injector for use by Jersey and HK2 bridge
|
// Store reference to injector for use by Jersey and HK2 bridge
|
||||||
servletContextEvent.getServletContext().setAttribute(GUICE_INJECTOR, injector);
|
servletContextEvent.getServletContext().setAttribute(GUICE_INJECTOR, injector);
|
||||||
|
|
||||||
|
// Inform any listeners that application startup has completed
|
||||||
|
try {
|
||||||
|
listenerService.handleEvent(new ApplicationStartedEvent() {
|
||||||
|
// The application startup event currently has no content
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
logger.error("An extension listening for application startup failed: {}", e.getMessage());
|
||||||
|
logger.debug("Extension failed internally while handling the application startup event.", e);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -228,19 +248,36 @@ public class GuacamoleServletContextListener extends GuiceServletContextListener
|
|||||||
// Clean up reference to Guice injector
|
// Clean up reference to Guice injector
|
||||||
servletContextEvent.getServletContext().removeAttribute(GUICE_INJECTOR);
|
servletContextEvent.getServletContext().removeAttribute(GUICE_INJECTOR);
|
||||||
|
|
||||||
// Shutdown TokenSessionMap
|
// Shutdown TokenSessionMap, invalidating all sessions (logging all
|
||||||
|
// users out)
|
||||||
if (sessionMap != null)
|
if (sessionMap != null)
|
||||||
sessionMap.shutdown();
|
sessionMap.shutdown();
|
||||||
|
|
||||||
// Unload all extensions
|
// Unload authentication for all extensions
|
||||||
if (authProviders != null) {
|
if (authProviders != null) {
|
||||||
for (AuthenticationProvider authProvider : authProviders)
|
for (AuthenticationProvider authProvider : authProviders)
|
||||||
authProvider.shutdown();
|
authProvider.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inform any listeners that application shutdown has completed
|
||||||
|
try {
|
||||||
|
listenerService.handleEvent(new ApplicationShutdownEvent() {
|
||||||
|
// The application shutdown event currently has no content
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
logger.error("An extension listening for application shutdown failed: {}", e.getMessage());
|
||||||
|
logger.debug("Extension failed internally while handling the application shutdown event.", e);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
|
||||||
|
// NOTE: This temporary file cleanup must happen AFTER firing the
|
||||||
|
// ApplicationShutdownEvent, or an extension that relies on a .jar
|
||||||
|
// file among those temporary files might fail internally when
|
||||||
|
// attempting to process the event.
|
||||||
|
|
||||||
// Regardless of what may succeed/fail here, always attempt to
|
// Regardless of what may succeed/fail here, always attempt to
|
||||||
// clean up ALL temporary files
|
// clean up ALL temporary files
|
||||||
if (temporaryFiles != null)
|
if (temporaryFiles != null)
|
||||||
|
@@ -23,12 +23,13 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
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.AuthenticationProvider;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.net.event.UserSessionInvalidatedEvent;
|
||||||
import org.apache.guacamole.rest.auth.DecoratedUserContext;
|
import org.apache.guacamole.rest.auth.DecoratedUserContext;
|
||||||
|
import org.apache.guacamole.rest.event.ListenerService;
|
||||||
import org.apache.guacamole.tunnel.UserTunnel;
|
import org.apache.guacamole.tunnel.UserTunnel;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -58,8 +59,12 @@ public class GuacamoleSession {
|
|||||||
/**
|
/**
|
||||||
* All currently-active tunnels, indexed by tunnel UUID.
|
* All currently-active tunnels, indexed by tunnel UUID.
|
||||||
*/
|
*/
|
||||||
private final Map<String, UserTunnel> tunnels =
|
private final Map<String, UserTunnel> tunnels = new ConcurrentHashMap<>();
|
||||||
new ConcurrentHashMap<String, UserTunnel>();
|
|
||||||
|
/**
|
||||||
|
* Service for dispatching events to registered event listeners.
|
||||||
|
*/
|
||||||
|
private final ListenerService listenerService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last time this session was accessed.
|
* The last time this session was accessed.
|
||||||
@@ -70,9 +75,9 @@ public class GuacamoleSession {
|
|||||||
* Creates a new Guacamole session associated with the given
|
* Creates a new Guacamole session associated with the given
|
||||||
* AuthenticatedUser and UserContexts.
|
* AuthenticatedUser and UserContexts.
|
||||||
*
|
*
|
||||||
* @param environment
|
* @param listenerService
|
||||||
* The environment of the Guacamole server associated with this new
|
* The service to use to notify registered event listeners when this
|
||||||
* session.
|
* session is invalidated.
|
||||||
*
|
*
|
||||||
* @param authenticatedUser
|
* @param authenticatedUser
|
||||||
* The authenticated user to associate this session with.
|
* The authenticated user to associate this session with.
|
||||||
@@ -83,11 +88,12 @@ public class GuacamoleSession {
|
|||||||
* @throws GuacamoleException
|
* @throws GuacamoleException
|
||||||
* If an error prevents the session from being created.
|
* If an error prevents the session from being created.
|
||||||
*/
|
*/
|
||||||
public GuacamoleSession(Environment environment,
|
public GuacamoleSession(ListenerService listenerService,
|
||||||
AuthenticatedUser authenticatedUser,
|
AuthenticatedUser authenticatedUser,
|
||||||
List<DecoratedUserContext> userContexts)
|
List<DecoratedUserContext> userContexts)
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
this.lastAccessedTime = System.currentTimeMillis();
|
this.lastAccessedTime = System.currentTimeMillis();
|
||||||
|
this.listenerService = listenerService;
|
||||||
this.authenticatedUser = authenticatedUser;
|
this.authenticatedUser = authenticatedUser;
|
||||||
this.userContexts = userContexts;
|
this.userContexts = userContexts;
|
||||||
}
|
}
|
||||||
@@ -260,6 +266,23 @@ public class GuacamoleSession {
|
|||||||
// Invalidate the authenticated user object
|
// Invalidate the authenticated user object
|
||||||
authenticatedUser.invalidate();
|
authenticatedUser.invalidate();
|
||||||
|
|
||||||
|
// Advise any registered listeners that the user's session is now
|
||||||
|
// invalidated
|
||||||
|
try {
|
||||||
|
listenerService.handleEvent(new UserSessionInvalidatedEvent() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatedUser getAuthenticatedUser() {
|
||||||
|
return authenticatedUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (GuacamoleException e) {
|
||||||
|
logger.error("An extension listening for session invalidation failed: {}", e.getMessage());
|
||||||
|
logger.debug("Extension failed internally while handling the session invalidation event.", e);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* 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.event;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.Nameable;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.apache.guacamole.net.event.IdentifiableObjectEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loggable representation of the object affected by an operation.
|
||||||
|
*/
|
||||||
|
public class AffectedObject implements LoggableDetail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger for this class.
|
||||||
|
*/
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AffectedObject.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The event representing the requested operation.
|
||||||
|
*/
|
||||||
|
private final IdentifiableObjectEvent<?> event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new AffectedObject representing the object affected by the
|
||||||
|
* operation described by the given event.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* The event representing the operation.
|
||||||
|
*/
|
||||||
|
public AffectedObject(IdentifiableObjectEvent<?> event) {
|
||||||
|
this.event = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
|
||||||
|
Object object = event.getObject();
|
||||||
|
String identifier = event.getObjectIdentifier();
|
||||||
|
String dataSource = event.getAuthenticationProvider().getIdentifier();
|
||||||
|
|
||||||
|
String objectType;
|
||||||
|
String name = null; // Not all objects have names
|
||||||
|
|
||||||
|
// Obtain name of object (if applicable and available)
|
||||||
|
if (object instanceof Nameable) {
|
||||||
|
try {
|
||||||
|
name = ((Nameable) object).getName();
|
||||||
|
}
|
||||||
|
catch (RuntimeException | Error e) {
|
||||||
|
logger.debug("Name of object \"{}\" could not be retrieved.", identifier, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine type of object
|
||||||
|
switch (event.getDirectoryType()) {
|
||||||
|
|
||||||
|
// Active connections
|
||||||
|
case ACTIVE_CONNECTION:
|
||||||
|
objectType = "active connection";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Connections
|
||||||
|
case CONNECTION:
|
||||||
|
objectType = "connection";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Connection groups
|
||||||
|
case CONNECTION_GROUP:
|
||||||
|
objectType = "connection group";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Sharing profiles
|
||||||
|
case SHARING_PROFILE:
|
||||||
|
objectType = "sharing profile";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Users
|
||||||
|
case USER:
|
||||||
|
|
||||||
|
if (identifier != null && identifier.equals(event.getAuthenticatedUser().getIdentifier()))
|
||||||
|
return "their own user account within \"" + dataSource + "\"";
|
||||||
|
|
||||||
|
objectType = "user";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// User groups
|
||||||
|
case USER_GROUP:
|
||||||
|
objectType = "user group";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Unknown
|
||||||
|
default:
|
||||||
|
objectType = (object != null) ? object.getClass().toString() : "an unknown object";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Describe at least the type of the object and its identifier,
|
||||||
|
// including the name of the object, as well, if available
|
||||||
|
if (identifier != null) {
|
||||||
|
if (name != null)
|
||||||
|
return objectType + " \"" + identifier + "\" within \"" + dataSource + "\" (currently named \"" + name + "\")";
|
||||||
|
else
|
||||||
|
return objectType + " \"" + identifier + "\" within \"" + dataSource + "\"";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return objectType + " within \"" + dataSource + "\"";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* 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.event;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
|
import org.apache.guacamole.net.auth.User;
|
||||||
|
import org.apache.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
|
||||||
|
import org.apache.guacamole.net.event.ApplicationShutdownEvent;
|
||||||
|
import org.apache.guacamole.net.event.ApplicationStartedEvent;
|
||||||
|
import org.apache.guacamole.net.event.AuthenticationFailureEvent;
|
||||||
|
import org.apache.guacamole.net.event.AuthenticationRequestReceivedEvent;
|
||||||
|
import org.apache.guacamole.net.event.AuthenticationSuccessEvent;
|
||||||
|
import org.apache.guacamole.net.event.DirectoryEvent;
|
||||||
|
import org.apache.guacamole.net.event.DirectoryFailureEvent;
|
||||||
|
import org.apache.guacamole.net.event.DirectorySuccessEvent;
|
||||||
|
import org.apache.guacamole.net.event.IdentifiableObjectEvent;
|
||||||
|
import org.apache.guacamole.net.event.UserSessionInvalidatedEvent;
|
||||||
|
import org.apache.guacamole.net.event.listener.Listener;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener that records each event that occurs in the logs, such as changes
|
||||||
|
* made to objects via the REST API.
|
||||||
|
*/
|
||||||
|
public class EventLoggingListener implements Listener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger for this class.
|
||||||
|
*/
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(EventLoggingListener.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given event affects the password of a User object.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* The event to check.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* true if a user's password is specifically set or modified by the
|
||||||
|
* given event, false otherwise.
|
||||||
|
*/
|
||||||
|
private boolean isPasswordAffected(IdentifiableObjectEvent<?> event) {
|
||||||
|
|
||||||
|
Identifiable object = event.getObject();
|
||||||
|
if (!(object instanceof User))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ((User) object).getPassword() != null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs that an operation was performed on an object within a Directory
|
||||||
|
* successfully.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* The event describing the operation successfully performed on the
|
||||||
|
* object.
|
||||||
|
*/
|
||||||
|
private void logSuccess(DirectorySuccessEvent<?> event) {
|
||||||
|
DirectoryEvent.Operation op = event.getOperation();
|
||||||
|
switch (op) {
|
||||||
|
|
||||||
|
case GET:
|
||||||
|
logger.debug("{} successfully accessed/retrieved {}", new RequestingUser(event), new AffectedObject(event));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADD:
|
||||||
|
if (isPasswordAffected(event))
|
||||||
|
logger.info("{} successfully created {}, setting their password", new RequestingUser(event), new AffectedObject(event));
|
||||||
|
else
|
||||||
|
logger.info("{} successfully created {}", new RequestingUser(event), new AffectedObject(event));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UPDATE:
|
||||||
|
if (isPasswordAffected(event))
|
||||||
|
logger.info("{} successfully updated {}, changing their password", new RequestingUser(event), new AffectedObject(event));
|
||||||
|
else
|
||||||
|
logger.info("{} successfully updated {}", new RequestingUser(event), new AffectedObject(event));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOVE:
|
||||||
|
logger.info("{} successfully deleted {}", new RequestingUser(event), new AffectedObject(event));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logger.warn("DirectoryEvent operation type has no corresponding log message implemented: {}", op);
|
||||||
|
logger.info("{} successfully performed an unknown action on {} {}", new RequestingUser(event), new AffectedObject(event));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs that an operation failed to be performed on an object within a
|
||||||
|
* Directory.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* The event describing the operation that failed.
|
||||||
|
*/
|
||||||
|
private void logFailure(DirectoryFailureEvent<?> event) {
|
||||||
|
DirectoryEvent.Operation op = event.getOperation();
|
||||||
|
switch (op) {
|
||||||
|
|
||||||
|
case GET:
|
||||||
|
if (event.getFailure() instanceof GuacamoleResourceNotFoundException)
|
||||||
|
logger.debug("{} failed to access/retrieve {}: {}", new RequestingUser(event), new AffectedObject(event), new Failure(event));
|
||||||
|
else
|
||||||
|
logger.info("{} failed to access/retrieve {}: {}", new RequestingUser(event), new AffectedObject(event), new Failure(event));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ADD:
|
||||||
|
logger.info("{} failed to create {}: {}", new RequestingUser(event), new AffectedObject(event), new Failure(event));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UPDATE:
|
||||||
|
logger.info("{} failed to update {}: {}", new RequestingUser(event), new AffectedObject(event), new Failure(event));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REMOVE:
|
||||||
|
logger.info("{} failed to delete {}: {}", new RequestingUser(event), new AffectedObject(event), new Failure(event));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logger.warn("DirectoryEvent operation type has no corresponding log message implemented: {}", op);
|
||||||
|
logger.info("{} failed to perform an unknown action on {}: {}", new RequestingUser(event), new AffectedObject(event), new Failure(event));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs that authentication succeeded for a user.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* The event describing the authentication attempt that succeeded.
|
||||||
|
*/
|
||||||
|
private void logSuccess(AuthenticationSuccessEvent event) {
|
||||||
|
if (!event.isExistingSession())
|
||||||
|
logger.info("{} successfully authenticated from {}",
|
||||||
|
new RequestingUser(event),
|
||||||
|
new RemoteAddress(event.getCredentials()));
|
||||||
|
else
|
||||||
|
logger.debug("{} successfully re-authenticated their existing "
|
||||||
|
+ "session from {}", new RequestingUser(event),
|
||||||
|
new RemoteAddress(event.getCredentials()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs that authentication failed for a user.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* The event describing the authentication attempt that failed.
|
||||||
|
*/
|
||||||
|
private void logFailure(AuthenticationFailureEvent event) {
|
||||||
|
|
||||||
|
AuthenticationProvider authProvider = event.getAuthenticationProvider();
|
||||||
|
|
||||||
|
Credentials creds = event.getCredentials();
|
||||||
|
String username = creds.getUsername();
|
||||||
|
|
||||||
|
if (creds.isEmpty())
|
||||||
|
logger.debug("Empty authentication attempt (login screen "
|
||||||
|
+ "initialization) from {} failed: {}",
|
||||||
|
new RemoteAddress(creds), new Failure(event));
|
||||||
|
else if (username == null || username.isEmpty())
|
||||||
|
logger.debug("Anonymous authentication attempt from {} failed: {}",
|
||||||
|
new RemoteAddress(creds), new Failure(event));
|
||||||
|
else if (event.getFailure() instanceof GuacamoleInsufficientCredentialsException) {
|
||||||
|
if (authProvider != null)
|
||||||
|
logger.debug("Authentication attempt from {} for user \"{}\" "
|
||||||
|
+ "requires additional credentials to continue: {} "
|
||||||
|
+ "(requested by \"{}\")", new RemoteAddress(creds),
|
||||||
|
username, new Failure(event), authProvider.getIdentifier());
|
||||||
|
else
|
||||||
|
logger.debug("Authentication attempt from {} for user \"{}\" "
|
||||||
|
+ "requires additional credentials to continue: {}",
|
||||||
|
new RemoteAddress(creds), username, new Failure(event));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (authProvider != null)
|
||||||
|
logger.warn("Authentication attempt from {} for user \"{}\" "
|
||||||
|
+ "failed: {} (rejected by \"{}\")", new RemoteAddress(creds),
|
||||||
|
username, new Failure(event), authProvider.getIdentifier());
|
||||||
|
else
|
||||||
|
logger.warn("Authentication attempt from {} for user \"{}\" "
|
||||||
|
+ "failed: {}", new RemoteAddress(creds), username,
|
||||||
|
new Failure(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleEvent(@Nonnull Object event) throws GuacamoleException {
|
||||||
|
|
||||||
|
// General object creation/modification/deletion
|
||||||
|
if (event instanceof DirectorySuccessEvent)
|
||||||
|
logSuccess((DirectorySuccessEvent<?>) event);
|
||||||
|
else if (event instanceof DirectoryFailureEvent)
|
||||||
|
logFailure((DirectoryFailureEvent<?>) event);
|
||||||
|
|
||||||
|
// Login / logout / session expiration
|
||||||
|
else if (event instanceof AuthenticationSuccessEvent)
|
||||||
|
logSuccess((AuthenticationSuccessEvent) event);
|
||||||
|
else if (event instanceof AuthenticationFailureEvent)
|
||||||
|
logFailure((AuthenticationFailureEvent) event);
|
||||||
|
else if (event instanceof UserSessionInvalidatedEvent)
|
||||||
|
logger.info("{} has logged out, or their session has expired or "
|
||||||
|
+ "been terminated.", new RequestingUser((UserSessionInvalidatedEvent) event));
|
||||||
|
else if (event instanceof AuthenticationRequestReceivedEvent)
|
||||||
|
logger.trace("Authentication request received from {}",
|
||||||
|
new RemoteAddress(((AuthenticationRequestReceivedEvent) event).getCredentials()));
|
||||||
|
|
||||||
|
// Application startup/shutdown
|
||||||
|
else if (event instanceof ApplicationStartedEvent)
|
||||||
|
logger.info("The Apache Guacamole web application has started.");
|
||||||
|
else if (event instanceof ApplicationShutdownEvent)
|
||||||
|
logger.info("The Apache Guacamole web application has shut down.");
|
||||||
|
|
||||||
|
// Unknown events
|
||||||
|
else
|
||||||
|
logger.debug("Ignoring unknown/unimplemented event type: {}",
|
||||||
|
event.getClass());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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.event;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.event.FailureEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loggable representation of a failure that occurred.
|
||||||
|
*/
|
||||||
|
public class Failure implements LoggableDetail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The event representing the failure.
|
||||||
|
*/
|
||||||
|
private final FailureEvent event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Failure representing the failure described by the given
|
||||||
|
* event.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* The event representing the failure.
|
||||||
|
*/
|
||||||
|
public Failure(FailureEvent event) {
|
||||||
|
this.event = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
|
||||||
|
Throwable failure = event.getFailure();
|
||||||
|
if (failure == null)
|
||||||
|
return "unknown error (no specific failure recorded)";
|
||||||
|
|
||||||
|
return failure.getMessage();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a {@link #toString()} implementation that returns a human-readable
|
||||||
|
* string that is intended to be logged and which describes a particular detail
|
||||||
|
* of an event.
|
||||||
|
*/
|
||||||
|
public interface LoggableDetail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* <p>
|
||||||
|
* A LoggableDetail implementation of toString() is required to return a
|
||||||
|
* string that is human-readable, describes a detail of a provided event,
|
||||||
|
* and that is intended to be logged.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
String toString();
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* 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.event;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loggable representation of the remote address of a user, including any
|
||||||
|
* intervening proxies noted by "X-Forwarded-For". This representation takes
|
||||||
|
* into account the fact that "X-Forwarded-For" may come from an untrusted
|
||||||
|
* source, logging such addresses within square brackets alongside the trusted
|
||||||
|
* source IP.
|
||||||
|
*/
|
||||||
|
public class RemoteAddress implements LoggableDetail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular expression which matches any IPv4 address.
|
||||||
|
*/
|
||||||
|
private static final String IPV4_ADDRESS_REGEX = "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular expression which matches any IPv6 address.
|
||||||
|
*/
|
||||||
|
private static final String IPV6_ADDRESS_REGEX = "([0-9a-fA-F]*(:[0-9a-fA-F]*){0,7})";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular expression which matches any IP address, regardless of version.
|
||||||
|
*/
|
||||||
|
private static final String IP_ADDRESS_REGEX = "(" + IPV4_ADDRESS_REGEX + "|" + IPV6_ADDRESS_REGEX + ")";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular expression which matches any Port Number.
|
||||||
|
*/
|
||||||
|
private static final String PORT_NUMBER_REGEX = "(:[0-9]{1,5})?";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pattern which matches valid values of the de-facto standard
|
||||||
|
* "X-Forwarded-For" header.
|
||||||
|
*/
|
||||||
|
private static final Pattern X_FORWARDED_FOR = Pattern.compile("^" + IP_ADDRESS_REGEX + PORT_NUMBER_REGEX + "(, " + IP_ADDRESS_REGEX + PORT_NUMBER_REGEX + ")*$");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The credentials supplied by the user when they authenticated.
|
||||||
|
*/
|
||||||
|
private final Credentials creds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new RemoteAddress representing the source address of the HTTP
|
||||||
|
* request that provided the given Credentials.
|
||||||
|
*
|
||||||
|
* @param creds
|
||||||
|
* The Credentials associated with the request whose source address
|
||||||
|
* should be represented by this RemoteAddress.
|
||||||
|
*/
|
||||||
|
public RemoteAddress(Credentials creds) {
|
||||||
|
this.creds = creds;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
|
||||||
|
HttpServletRequest request = creds.getRequest();
|
||||||
|
if (request == null)
|
||||||
|
return creds.getRemoteAddress();
|
||||||
|
|
||||||
|
// Log X-Forwarded-For, if present and valid
|
||||||
|
String header = request.getHeader("X-Forwarded-For");
|
||||||
|
if (header != null && X_FORWARDED_FOR.matcher(header).matches())
|
||||||
|
return "[" + header + ", " + request.getRemoteAddr() + "]";
|
||||||
|
|
||||||
|
// If header absent or invalid, just use source IP
|
||||||
|
return request.getRemoteAddr();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -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.event;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
|
import org.apache.guacamole.net.event.UserEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loggable representation of the user that requested an operation.
|
||||||
|
*/
|
||||||
|
public class RequestingUser implements LoggableDetail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The event representing the requested operation.
|
||||||
|
*/
|
||||||
|
private final UserEvent event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new RequestingUser that represents the user that requested the
|
||||||
|
* operation described by the given event.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
* The event representing the requested operation.
|
||||||
|
*/
|
||||||
|
public RequestingUser(UserEvent event) {
|
||||||
|
this.event = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
|
||||||
|
AuthenticatedUser user = event.getAuthenticatedUser();
|
||||||
|
String identifier = user.getIdentifier();
|
||||||
|
|
||||||
|
if (AuthenticatedUser.ANONYMOUS_IDENTIFIER.equals(identifier))
|
||||||
|
return "Anonymous user (authenticated by \"" + user.getAuthenticationProvider().getIdentifier() + "\")";
|
||||||
|
|
||||||
|
return "User \"" + identifier + "\" (authenticated by \"" + user.getAuthenticationProvider().getIdentifier() + "\")";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -35,6 +35,7 @@ import org.apache.guacamole.auth.file.FileAuthenticationProvider;
|
|||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleServerException;
|
import org.apache.guacamole.GuacamoleServerException;
|
||||||
import org.apache.guacamole.environment.Environment;
|
import org.apache.guacamole.environment.Environment;
|
||||||
|
import org.apache.guacamole.event.EventLoggingListener;
|
||||||
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
import org.apache.guacamole.net.event.listener.Listener;
|
import org.apache.guacamole.net.event.listener.Listener;
|
||||||
import org.apache.guacamole.properties.StringSetProperty;
|
import org.apache.guacamole.properties.StringSetProperty;
|
||||||
@@ -628,8 +629,9 @@ public class ExtensionModule extends ServletModule {
|
|||||||
final Set<String> toleratedAuthProviders = getToleratedAuthenticationProviders();
|
final Set<String> toleratedAuthProviders = getToleratedAuthenticationProviders();
|
||||||
loadExtensions(javaScriptResources, cssResources, toleratedAuthProviders);
|
loadExtensions(javaScriptResources, cssResources, toleratedAuthProviders);
|
||||||
|
|
||||||
// Always bind default file-driven auth last
|
// Always bind default file-driven auth and event logging last
|
||||||
bindAuthenticationProvider(FileAuthenticationProvider.class, toleratedAuthProviders);
|
bindAuthenticationProvider(FileAuthenticationProvider.class, toleratedAuthProviders);
|
||||||
|
bindListener(EventLoggingListener.class);
|
||||||
|
|
||||||
// Dynamically generate app.js and app.css from extensions
|
// Dynamically generate app.js and app.css from extensions
|
||||||
serve("/app.js").with(new ResourceServlet(new SequenceResource(javaScriptResources)));
|
serve("/app.js").with(new ResourceServlet(new SequenceResource(javaScriptResources)));
|
||||||
|
@@ -26,6 +26,7 @@ import javax.ws.rs.Produces;
|
|||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.net.auth.ActiveConnection;
|
import org.apache.guacamole.net.auth.ActiveConnection;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Permissions;
|
import org.apache.guacamole.net.auth.Permissions;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
@@ -48,6 +49,9 @@ public class ActiveConnectionDirectoryResource
|
|||||||
* operations and subresources available for the given ActiveConnection
|
* operations and subresources available for the given ActiveConnection
|
||||||
* Directory.
|
* Directory.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -63,11 +67,13 @@ public class ActiveConnectionDirectoryResource
|
|||||||
* representing ActiveConnections.
|
* representing ActiveConnections.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public ActiveConnectionDirectoryResource(@Assisted UserContext userContext,
|
public ActiveConnectionDirectoryResource(
|
||||||
|
@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<ActiveConnection> directory,
|
@Assisted Directory<ActiveConnection> directory,
|
||||||
DirectoryObjectTranslator<ActiveConnection, APIActiveConnection> translator,
|
DirectoryObjectTranslator<ActiveConnection, APIActiveConnection> translator,
|
||||||
DirectoryObjectResourceFactory<ActiveConnection, APIActiveConnection> resourceFactory) {
|
DirectoryObjectResourceFactory<ActiveConnection, APIActiveConnection> resourceFactory) {
|
||||||
super(userContext, directory, translator, resourceFactory);
|
super(authenticatedUser, userContext, ActiveConnection.class, directory, translator, resourceFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -30,6 +30,7 @@ import javax.ws.rs.Produces;
|
|||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.net.auth.ActiveConnection;
|
import org.apache.guacamole.net.auth.ActiveConnection;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
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;
|
||||||
@@ -47,17 +48,6 @@ import org.apache.guacamole.rest.directory.DirectoryResourceFactory;
|
|||||||
public class ActiveConnectionResource
|
public class ActiveConnectionResource
|
||||||
extends DirectoryObjectResource<ActiveConnection, APIActiveConnection> {
|
extends DirectoryObjectResource<ActiveConnection, APIActiveConnection> {
|
||||||
|
|
||||||
/**
|
|
||||||
* The UserContext associated with the Directory which contains the
|
|
||||||
* Connection exposed by this resource.
|
|
||||||
*/
|
|
||||||
private final UserContext userContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The ActiveConnection exposed by this ActiveConnectionResource.
|
|
||||||
*/
|
|
||||||
private final ActiveConnection activeConnection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory which can be used to create instances of resources representing
|
* A factory which can be used to create instances of resources representing
|
||||||
* Connection.
|
* Connection.
|
||||||
@@ -70,6 +60,9 @@ public class ActiveConnectionResource
|
|||||||
* Creates a new ActiveConnectionResource which exposes the operations and
|
* Creates a new ActiveConnectionResource which exposes the operations and
|
||||||
* subresources available for the given ActiveConnection.
|
* subresources available for the given ActiveConnection.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -85,13 +78,12 @@ public class ActiveConnectionResource
|
|||||||
* ActiveConnections.
|
* ActiveConnections.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public ActiveConnectionResource(@Assisted UserContext userContext,
|
public ActiveConnectionResource(@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<ActiveConnection> directory,
|
@Assisted Directory<ActiveConnection> directory,
|
||||||
@Assisted ActiveConnection activeConnection,
|
@Assisted ActiveConnection activeConnection,
|
||||||
DirectoryObjectTranslator<ActiveConnection, APIActiveConnection> translator) {
|
DirectoryObjectTranslator<ActiveConnection, APIActiveConnection> translator) {
|
||||||
super(userContext, directory, activeConnection, translator);
|
super(authenticatedUser, userContext, ActiveConnection.class, directory, activeConnection, translator);
|
||||||
this.userContext = userContext;
|
|
||||||
this.activeConnection = activeConnection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,9 +101,12 @@ public class ActiveConnectionResource
|
|||||||
public DirectoryObjectResource<Connection, APIConnection> getConnection()
|
public DirectoryObjectResource<Connection, APIConnection> getConnection()
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
UserContext userContext = getUserContext();
|
||||||
|
ActiveConnection activeConnection = getInternalObject();
|
||||||
|
|
||||||
// Return the underlying connection as a resource
|
// Return the underlying connection as a resource
|
||||||
return connectionDirectoryResourceFactory
|
return connectionDirectoryResourceFactory
|
||||||
.create(userContext, userContext.getConnectionDirectory())
|
.create(getAuthenticatedUser(), userContext, userContext.getConnectionDirectory())
|
||||||
.getObjectResource(activeConnection.getConnectionIdentifier());
|
.getObjectResource(activeConnection.getConnectionIdentifier());
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -137,7 +132,7 @@ public class ActiveConnectionResource
|
|||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// Generate and return sharing credentials for the active connection
|
// Generate and return sharing credentials for the active connection
|
||||||
return new APIUserCredentials(activeConnection.getSharingCredentials(sharingProfileIdentifier));
|
return new APIUserCredentials(getInternalObject().getSharingCredentials(sharingProfileIdentifier));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,16 +21,13 @@ package org.apache.guacamole.rest.auth;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
import org.apache.guacamole.GuacamoleServerException;
|
import org.apache.guacamole.GuacamoleServerException;
|
||||||
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
import org.apache.guacamole.GuacamoleUnauthorizedException;
|
||||||
import org.apache.guacamole.GuacamoleSession;
|
import org.apache.guacamole.GuacamoleSession;
|
||||||
import org.apache.guacamole.environment.Environment;
|
|
||||||
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.AuthenticationProvider;
|
||||||
import org.apache.guacamole.net.auth.Credentials;
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
@@ -56,12 +53,6 @@ public class AuthenticationService {
|
|||||||
*/
|
*/
|
||||||
private static final Logger logger = LoggerFactory.getLogger(AuthenticationService.class);
|
private static final Logger logger = LoggerFactory.getLogger(AuthenticationService.class);
|
||||||
|
|
||||||
/**
|
|
||||||
* The Guacamole server environment.
|
|
||||||
*/
|
|
||||||
@Inject
|
|
||||||
private Environment environment;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All configured authentication providers which can be used to
|
* All configured authentication providers which can be used to
|
||||||
* authenticate users or retrieve data associated with authenticated users.
|
* authenticate users or retrieve data associated with authenticated users.
|
||||||
@@ -105,57 +96,6 @@ public class AuthenticationService {
|
|||||||
*/
|
*/
|
||||||
public static final String TOKEN_PARAMETER_NAME = "token";
|
public static final String TOKEN_PARAMETER_NAME = "token";
|
||||||
|
|
||||||
/**
|
|
||||||
* Regular expression which matches any IPv4 address.
|
|
||||||
*/
|
|
||||||
private static final String IPV4_ADDRESS_REGEX = "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regular expression which matches any IPv6 address.
|
|
||||||
*/
|
|
||||||
private static final String IPV6_ADDRESS_REGEX = "([0-9a-fA-F]*(:[0-9a-fA-F]*){0,7})";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regular expression which matches any IP address, regardless of version.
|
|
||||||
*/
|
|
||||||
private static final String IP_ADDRESS_REGEX = "(" + IPV4_ADDRESS_REGEX + "|" + IPV6_ADDRESS_REGEX + ")";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Regular expression which matches any Port Number.
|
|
||||||
*/
|
|
||||||
private static final String PORT_NUMBER_REGEX = "(:[0-9]{1,5})?";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pattern which matches valid values of the de-facto standard
|
|
||||||
* "X-Forwarded-For" header.
|
|
||||||
*/
|
|
||||||
private static final Pattern X_FORWARDED_FOR = Pattern.compile("^" + IP_ADDRESS_REGEX + PORT_NUMBER_REGEX + "(, " + IP_ADDRESS_REGEX + PORT_NUMBER_REGEX + ")*$");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a formatted string containing an IP address, or list of IP
|
|
||||||
* addresses, which represent the HTTP client and any involved proxies. As
|
|
||||||
* the headers used to determine proxies can easily be forged, this data is
|
|
||||||
* superficially validated to ensure that it at least looks like a list of
|
|
||||||
* IPs.
|
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
* The HTTP request to format.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* A formatted string containing one or more IP addresses.
|
|
||||||
*/
|
|
||||||
private String getLoggableAddress(HttpServletRequest request) {
|
|
||||||
|
|
||||||
// Log X-Forwarded-For, if present and valid
|
|
||||||
String header = request.getHeader("X-Forwarded-For");
|
|
||||||
if (header != null && X_FORWARDED_FOR.matcher(header).matches())
|
|
||||||
return "[" + header + ", " + request.getRemoteAddr() + "]";
|
|
||||||
|
|
||||||
// If header absent or invalid, just use source IP
|
|
||||||
return request.getRemoteAddr();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts authentication against all AuthenticationProviders, in order,
|
* Attempts authentication against all AuthenticationProviders, in order,
|
||||||
* using the provided credentials. The first authentication failure takes
|
* using the provided credentials. The first authentication failure takes
|
||||||
@@ -443,13 +383,13 @@ public class AuthenticationService {
|
|||||||
// If no existing session, generate a new token/session pair
|
// If no existing session, generate a new token/session pair
|
||||||
else {
|
else {
|
||||||
authToken = authTokenGenerator.getToken();
|
authToken = authTokenGenerator.getToken();
|
||||||
tokenSessionMap.put(authToken, new GuacamoleSession(environment, authenticatedUser, userContexts));
|
tokenSessionMap.put(authToken, new GuacamoleSession(listenerService, authenticatedUser, userContexts));
|
||||||
logger.debug("Login was successful for user \"{}\".", authenticatedUser.getIdentifier());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report authentication success
|
// Report authentication success
|
||||||
try {
|
try {
|
||||||
listenerService.handleEvent(new AuthenticationSuccessEvent(authenticatedUser));
|
listenerService.handleEvent(new AuthenticationSuccessEvent(authenticatedUser,
|
||||||
|
existingSession != null));
|
||||||
}
|
}
|
||||||
catch (GuacamoleException e) {
|
catch (GuacamoleException e) {
|
||||||
throw new GuacamoleAuthenticationProcessException("User "
|
throw new GuacamoleAuthenticationProcessException("User "
|
||||||
@@ -461,25 +401,9 @@ public class AuthenticationService {
|
|||||||
// Log and rethrow any authentication errors
|
// Log and rethrow any authentication errors
|
||||||
catch (GuacamoleAuthenticationProcessException e) {
|
catch (GuacamoleAuthenticationProcessException e) {
|
||||||
|
|
||||||
// Get request and username for sake of logging
|
|
||||||
HttpServletRequest request = credentials.getRequest();
|
|
||||||
String username = credentials.getUsername();
|
|
||||||
|
|
||||||
listenerService.handleEvent(new AuthenticationFailureEvent(credentials,
|
listenerService.handleEvent(new AuthenticationFailureEvent(credentials,
|
||||||
e.getAuthenticationProvider(), e.getCause()));
|
e.getAuthenticationProvider(), e.getCause()));
|
||||||
|
|
||||||
// Log authentication failures with associated usernames
|
|
||||||
if (username != null) {
|
|
||||||
if (logger.isWarnEnabled())
|
|
||||||
logger.warn("Authentication attempt from {} for user \"{}\" failed.",
|
|
||||||
getLoggableAddress(request), username);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log anonymous authentication failures
|
|
||||||
else if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Anonymous authentication attempt from {} failed.",
|
|
||||||
getLoggableAddress(request));
|
|
||||||
|
|
||||||
// Rethrow exception
|
// Rethrow exception
|
||||||
e.rethrowCause();
|
e.rethrowCause();
|
||||||
|
|
||||||
@@ -497,11 +421,6 @@ public class AuthenticationService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logger.isInfoEnabled())
|
|
||||||
logger.info("User \"{}\" successfully authenticated from {}.",
|
|
||||||
authenticatedUser.getIdentifier(),
|
|
||||||
getLoggableAddress(credentials.getRequest()));
|
|
||||||
|
|
||||||
return authToken;
|
return authToken;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -225,7 +225,13 @@ public class HashTokenSessionMap implements TokenSessionMap {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
|
|
||||||
|
// Terminate the automatic session invalidation thread
|
||||||
executor.shutdownNow();
|
executor.shutdownNow();
|
||||||
|
|
||||||
|
// Forcibly invalidate any remaining sessions
|
||||||
|
sessionMap.values().stream().forEach(GuacamoleSession::invalidate);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import javax.ws.rs.Consumes;
|
|||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Permissions;
|
import org.apache.guacamole.net.auth.Permissions;
|
||||||
@@ -47,6 +48,9 @@ public class ConnectionDirectoryResource
|
|||||||
* Creates a new ConnectionDirectoryResource which exposes the operations
|
* Creates a new ConnectionDirectoryResource which exposes the operations
|
||||||
* and subresources available for the given Connection Directory.
|
* and subresources available for the given Connection Directory.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -62,11 +66,11 @@ public class ConnectionDirectoryResource
|
|||||||
* representing Connections.
|
* representing Connections.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public ConnectionDirectoryResource(@Assisted UserContext userContext,
|
public ConnectionDirectoryResource(@Assisted AuthenticatedUser authenticatedUser,
|
||||||
@Assisted Directory<Connection> directory,
|
@Assisted UserContext userContext, @Assisted Directory<Connection> directory,
|
||||||
DirectoryObjectTranslator<Connection, APIConnection> translator,
|
DirectoryObjectTranslator<Connection, APIConnection> translator,
|
||||||
DirectoryObjectResourceFactory<Connection, APIConnection> resourceFactory) {
|
DirectoryObjectResourceFactory<Connection, APIConnection> resourceFactory) {
|
||||||
super(userContext, directory, translator, resourceFactory);
|
super(authenticatedUser, userContext, Connection.class, directory, translator, resourceFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -32,6 +32,7 @@ import org.apache.guacamole.GuacamoleException;
|
|||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
import org.apache.guacamole.GuacamoleUnsupportedException;
|
import org.apache.guacamole.GuacamoleUnsupportedException;
|
||||||
import org.apache.guacamole.net.auth.ActivityRecordSet;
|
import org.apache.guacamole.net.auth.ActivityRecordSet;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
import org.apache.guacamole.net.auth.Connection;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Permissions;
|
import org.apache.guacamole.net.auth.Permissions;
|
||||||
@@ -65,17 +66,6 @@ public class ConnectionResource extends DirectoryObjectResource<Connection, APIC
|
|||||||
* Logger for this class.
|
* Logger for this class.
|
||||||
*/
|
*/
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ConnectionResource.class);
|
private static final Logger logger = LoggerFactory.getLogger(ConnectionResource.class);
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory which can be used to create instances of resources representing
|
* A factory which can be used to create instances of resources representing
|
||||||
@@ -89,6 +79,9 @@ public class ConnectionResource extends DirectoryObjectResource<Connection, APIC
|
|||||||
* Creates a new ConnectionResource which exposes the operations and
|
* Creates a new ConnectionResource which exposes the operations and
|
||||||
* subresources available for the given Connection.
|
* subresources available for the given Connection.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -103,13 +96,12 @@ public class ConnectionResource extends DirectoryObjectResource<Connection, APIC
|
|||||||
* object given.
|
* object given.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public ConnectionResource(@Assisted UserContext userContext,
|
public ConnectionResource(@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<Connection> directory,
|
@Assisted Directory<Connection> directory,
|
||||||
@Assisted Connection connection,
|
@Assisted Connection connection,
|
||||||
DirectoryObjectTranslator<Connection, APIConnection> translator) {
|
DirectoryObjectTranslator<Connection, APIConnection> translator) {
|
||||||
super(userContext, directory, connection, translator);
|
super(authenticatedUser, userContext, Connection.class, directory, connection, translator);
|
||||||
this.userContext = userContext;
|
|
||||||
this.connection = connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,8 +118,10 @@ public class ConnectionResource extends DirectoryObjectResource<Connection, APIC
|
|||||||
public Map<String, String> getConnectionParameters()
|
public Map<String, String> getConnectionParameters()
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
Connection connection = getInternalObject();
|
||||||
|
|
||||||
// Pull effective permissions
|
// Pull effective permissions
|
||||||
Permissions effective = userContext.self().getEffectivePermissions();
|
Permissions effective = getUserContext().self().getEffectivePermissions();
|
||||||
|
|
||||||
// Retrieve permission sets
|
// Retrieve permission sets
|
||||||
SystemPermissionSet systemPermissions = effective.getSystemPermissions();
|
SystemPermissionSet systemPermissions = effective.getSystemPermissions();
|
||||||
@@ -162,6 +156,8 @@ public class ConnectionResource extends DirectoryObjectResource<Connection, APIC
|
|||||||
public ConnectionHistoryResource getConnectionHistory()
|
public ConnectionHistoryResource getConnectionHistory()
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
Connection connection = getInternalObject();
|
||||||
|
|
||||||
// Try the current getConnectionHistory() method, first, for connection history.
|
// Try the current getConnectionHistory() method, first, for connection history.
|
||||||
try {
|
try {
|
||||||
return new ConnectionHistoryResource(connection.getConnectionHistory()
|
return new ConnectionHistoryResource(connection.getConnectionHistory()
|
||||||
@@ -201,6 +197,9 @@ public class ConnectionResource extends DirectoryObjectResource<Connection, APIC
|
|||||||
public DirectoryResource<SharingProfile, APISharingProfile>
|
public DirectoryResource<SharingProfile, APISharingProfile>
|
||||||
getSharingProfileDirectoryResource() throws GuacamoleException {
|
getSharingProfileDirectoryResource() throws GuacamoleException {
|
||||||
|
|
||||||
|
UserContext userContext = getUserContext();
|
||||||
|
Connection connection = getInternalObject();
|
||||||
|
|
||||||
// Produce subset of all SharingProfiles, containing only those which
|
// Produce subset of all SharingProfiles, containing only those which
|
||||||
// are associated with this connection
|
// are associated with this connection
|
||||||
Directory<SharingProfile> sharingProfiles = new DirectoryView<>(
|
Directory<SharingProfile> sharingProfiles = new DirectoryView<>(
|
||||||
@@ -209,7 +208,7 @@ public class ConnectionResource extends DirectoryObjectResource<Connection, APIC
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Return a new resource which provides access to only those SharingProfiles
|
// Return a new resource which provides access to only those SharingProfiles
|
||||||
return sharingProfileDirectoryResourceFactory.create(userContext, sharingProfiles);
|
return sharingProfileDirectoryResourceFactory.create(getAuthenticatedUser(), userContext, sharingProfiles);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,6 +25,7 @@ import javax.ws.rs.Consumes;
|
|||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
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.Permissions;
|
import org.apache.guacamole.net.auth.Permissions;
|
||||||
@@ -44,28 +45,14 @@ import org.apache.guacamole.rest.directory.DirectoryResource;
|
|||||||
public class ConnectionGroupDirectoryResource
|
public class ConnectionGroupDirectoryResource
|
||||||
extends DirectoryResource<ConnectionGroup, APIConnectionGroup> {
|
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
|
* Creates a new ConnectionGroupDirectoryResource which exposes the
|
||||||
* operations and subresources available for the given ConnectionGroup
|
* operations and subresources available for the given ConnectionGroup
|
||||||
* Directory.
|
* Directory.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -81,23 +68,24 @@ public class ConnectionGroupDirectoryResource
|
|||||||
* representing ConnectionGroups.
|
* representing ConnectionGroups.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public ConnectionGroupDirectoryResource(@Assisted UserContext userContext,
|
public ConnectionGroupDirectoryResource(
|
||||||
|
@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<ConnectionGroup> directory,
|
@Assisted Directory<ConnectionGroup> directory,
|
||||||
DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup> translator,
|
DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup> translator,
|
||||||
DirectoryObjectResourceFactory<ConnectionGroup, APIConnectionGroup> resourceFactory) {
|
DirectoryObjectResourceFactory<ConnectionGroup, APIConnectionGroup> resourceFactory) {
|
||||||
super(userContext, directory, translator, resourceFactory);
|
super(authenticatedUser, userContext, ConnectionGroup.class, directory, translator, resourceFactory);
|
||||||
this.userContext = userContext;
|
|
||||||
this.directory = directory;
|
|
||||||
this.resourceFactory = resourceFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DirectoryObjectResource<ConnectionGroup, APIConnectionGroup>
|
public DirectoryObjectResource<ConnectionGroup, APIConnectionGroup>
|
||||||
getObjectResource(String identifier) throws GuacamoleException {
|
getObjectResource(String identifier) throws GuacamoleException {
|
||||||
|
|
||||||
|
UserContext userContext = getUserContext();
|
||||||
|
|
||||||
// Use root group if identifier is the standard root identifier
|
// Use root group if identifier is the standard root identifier
|
||||||
if (identifier != null && identifier.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
if (identifier != null && identifier.equals(APIConnectionGroup.ROOT_IDENTIFIER))
|
||||||
return resourceFactory.create(userContext, directory,
|
return getResourceFactory().create(getAuthenticatedUser(), userContext, getDirectory(),
|
||||||
userContext.getRootConnectionGroup());
|
userContext.getRootConnectionGroup());
|
||||||
|
|
||||||
return super.getObjectResource(identifier);
|
return super.getObjectResource(identifier);
|
||||||
|
@@ -29,6 +29,7 @@ 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;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
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;
|
||||||
@@ -45,21 +46,13 @@ import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
|||||||
public class ConnectionGroupResource
|
public class ConnectionGroupResource
|
||||||
extends DirectoryObjectResource<ConnectionGroup, APIConnectionGroup> {
|
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
|
* Creates a new ConnectionGroupResource which exposes the operations and
|
||||||
* subresources available for the given ConnectionGroup.
|
* subresources available for the given ConnectionGroup.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -75,13 +68,13 @@ public class ConnectionGroupResource
|
|||||||
* object given.
|
* object given.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public ConnectionGroupResource(@Assisted UserContext userContext,
|
public ConnectionGroupResource(
|
||||||
|
@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<ConnectionGroup> directory,
|
@Assisted Directory<ConnectionGroup> directory,
|
||||||
@Assisted ConnectionGroup connectionGroup,
|
@Assisted ConnectionGroup connectionGroup,
|
||||||
DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup> translator) {
|
DirectoryObjectTranslator<ConnectionGroup, APIConnectionGroup> translator) {
|
||||||
super(userContext, directory, connectionGroup, translator);
|
super(authenticatedUser, userContext, ConnectionGroup.class, directory, connectionGroup, translator);
|
||||||
this.userContext = userContext;
|
|
||||||
this.connectionGroup = connectionGroup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,8 +100,8 @@ public class ConnectionGroupResource
|
|||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// Retrieve the requested tree, filtering by the given permissions
|
// Retrieve the requested tree, filtering by the given permissions
|
||||||
ConnectionGroupTree tree = new ConnectionGroupTree(userContext,
|
ConnectionGroupTree tree = new ConnectionGroupTree(getUserContext(),
|
||||||
connectionGroup, permissions);
|
getInternalObject(), permissions);
|
||||||
|
|
||||||
// Return tree as a connection group
|
// Return tree as a connection group
|
||||||
return tree.getRootAPIConnectionGroup();
|
return tree.getRootAPIConnectionGroup();
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.rest.directory;
|
package org.apache.guacamole.rest.directory;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
@@ -27,9 +28,15 @@ import javax.ws.rs.Produces;
|
|||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleClientException;
|
import org.apache.guacamole.GuacamoleClientException;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Identifiable;
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
import org.apache.guacamole.net.event.DirectoryEvent;
|
||||||
|
import org.apache.guacamole.net.event.DirectoryFailureEvent;
|
||||||
|
import org.apache.guacamole.net.event.DirectorySuccessEvent;
|
||||||
|
import org.apache.guacamole.rest.event.ListenerService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A REST resource which abstracts the operations available on an existing
|
* A REST resource which abstracts the operations available on an existing
|
||||||
@@ -51,12 +58,22 @@ import org.apache.guacamole.net.auth.UserContext;
|
|||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public abstract class DirectoryObjectResource<InternalType extends Identifiable, ExternalType> {
|
public abstract class DirectoryObjectResource<InternalType extends Identifiable, ExternalType> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*/
|
||||||
|
private final AuthenticatedUser authenticatedUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The UserContext associated with the Directory containing the object
|
* The UserContext associated with the Directory containing the object
|
||||||
* represented by this DirectoryObjectResource.
|
* represented by this DirectoryObjectResource.
|
||||||
*/
|
*/
|
||||||
private final UserContext userContext;
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of object represented by this DirectoryObjectResource.
|
||||||
|
*/
|
||||||
|
private final Class<InternalType> internalType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Directory which contains the object represented by this
|
* The Directory which contains the object represented by this
|
||||||
* DirectoryObjectResource.
|
* DirectoryObjectResource.
|
||||||
@@ -74,13 +91,26 @@ public abstract class DirectoryObjectResource<InternalType extends Identifiable,
|
|||||||
*/
|
*/
|
||||||
private final DirectoryObjectTranslator<InternalType, ExternalType> translator;
|
private final DirectoryObjectTranslator<InternalType, ExternalType> translator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for dispatching events to registered listeners.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ListenerService listenerService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new DirectoryObjectResource which exposes the operations
|
* Creates a new DirectoryObjectResource which exposes the operations
|
||||||
* available for the given object.
|
* available for the given object.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
|
* @param internalType
|
||||||
|
* The type of object that this DirectoryObjectResource should
|
||||||
|
* represent.
|
||||||
|
*
|
||||||
* @param directory
|
* @param directory
|
||||||
* The Directory which contains the given object.
|
* The Directory which contains the given object.
|
||||||
*
|
*
|
||||||
@@ -91,15 +121,162 @@ public abstract class DirectoryObjectResource<InternalType extends Identifiable,
|
|||||||
* A DirectoryObjectTranslator implementation which handles the type of
|
* A DirectoryObjectTranslator implementation which handles the type of
|
||||||
* object given.
|
* object given.
|
||||||
*/
|
*/
|
||||||
public DirectoryObjectResource(UserContext userContext,
|
public DirectoryObjectResource(AuthenticatedUser authenticatedUser,
|
||||||
|
UserContext userContext, Class<InternalType> internalType,
|
||||||
Directory<InternalType> directory, InternalType object,
|
Directory<InternalType> directory, InternalType object,
|
||||||
DirectoryObjectTranslator<InternalType, ExternalType> translator) {
|
DirectoryObjectTranslator<InternalType, ExternalType> translator) {
|
||||||
|
this.authenticatedUser = authenticatedUser;
|
||||||
this.userContext = userContext;
|
this.userContext = userContext;
|
||||||
this.directory = directory;
|
this.directory = directory;
|
||||||
|
this.internalType = internalType;
|
||||||
this.object = object;
|
this.object = object;
|
||||||
this.translator = translator;
|
this.translator = translator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies all registered listeners that the given operation has succeeded
|
||||||
|
* against the object represented by this resource.
|
||||||
|
*
|
||||||
|
* @param operation
|
||||||
|
* The operation that was performed.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If a listener throws a GuacamoleException from its event handler.
|
||||||
|
*/
|
||||||
|
protected void fireDirectorySuccessEvent(DirectoryEvent.Operation operation)
|
||||||
|
throws GuacamoleException {
|
||||||
|
listenerService.handleEvent(new DirectorySuccessEvent<InternalType>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Directory.Type getDirectoryType() {
|
||||||
|
return Directory.Type.of(internalType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DirectoryEvent.Operation getOperation() {
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getObjectIdentifier() {
|
||||||
|
return object.getIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InternalType getObject() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatedUser getAuthenticatedUser() {
|
||||||
|
return authenticatedUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationProvider getAuthenticationProvider() {
|
||||||
|
return userContext.getAuthenticationProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies all registered listeners that the given operation has failed
|
||||||
|
* against the object represented by this resource.
|
||||||
|
*
|
||||||
|
* @param operation
|
||||||
|
* The operation that failed.
|
||||||
|
*
|
||||||
|
* @param failure
|
||||||
|
* The failure that occurred.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If a listener throws a GuacamoleException from its event handler.
|
||||||
|
*/
|
||||||
|
protected void fireDirectoryFailureEvent(DirectoryEvent.Operation operation,
|
||||||
|
Throwable failure) throws GuacamoleException {
|
||||||
|
listenerService.handleEvent(new DirectoryFailureEvent<InternalType>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Directory.Type getDirectoryType() {
|
||||||
|
return Directory.Type.of(internalType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DirectoryEvent.Operation getOperation() {
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getObjectIdentifier() {
|
||||||
|
return object.getIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InternalType getObject() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatedUser getAuthenticatedUser() {
|
||||||
|
return authenticatedUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationProvider getAuthenticationProvider() {
|
||||||
|
return userContext.getAuthenticationProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Throwable getFailure() {
|
||||||
|
return failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the user accessing this resource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The user accessing this resource.
|
||||||
|
*/
|
||||||
|
protected AuthenticatedUser getAuthenticatedUser() {
|
||||||
|
return authenticatedUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the UserContext providing the Directory that contains the object
|
||||||
|
* exposed by this resource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The UserContext providing the Directory that contains the object
|
||||||
|
* exposed by this resource.
|
||||||
|
*/
|
||||||
|
protected UserContext getUserContext() {
|
||||||
|
return userContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Directory containing the object exposed by this resource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The Directory containing the object exposed by this resource.
|
||||||
|
*/
|
||||||
|
protected Directory<InternalType> getDirectory() {
|
||||||
|
return directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the object exposed by this resource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The object exposed by this resource.
|
||||||
|
*/
|
||||||
|
protected InternalType getInternalObject() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the object represented by this DirectoryObjectResource, in a
|
* Returns the object represented by this DirectoryObjectResource, in a
|
||||||
* format intended for interchange.
|
* format intended for interchange.
|
||||||
@@ -138,7 +315,15 @@ public abstract class DirectoryObjectResource<InternalType extends Identifiable,
|
|||||||
|
|
||||||
// Perform update
|
// Perform update
|
||||||
translator.applyExternalChanges(object, modifiedObject);
|
translator.applyExternalChanges(object, modifiedObject);
|
||||||
directory.update(object);
|
|
||||||
|
try {
|
||||||
|
directory.update(object);
|
||||||
|
fireDirectorySuccessEvent(DirectoryEvent.Operation.UPDATE);
|
||||||
|
}
|
||||||
|
catch (GuacamoleException | RuntimeException | Error e) {
|
||||||
|
fireDirectoryFailureEvent(DirectoryEvent.Operation.UPDATE, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +335,14 @@ public abstract class DirectoryObjectResource<InternalType extends Identifiable,
|
|||||||
*/
|
*/
|
||||||
@DELETE
|
@DELETE
|
||||||
public void deleteObject() throws GuacamoleException {
|
public void deleteObject() throws GuacamoleException {
|
||||||
directory.remove(object.getIdentifier());
|
try {
|
||||||
|
directory.remove(object.getIdentifier());
|
||||||
|
fireDirectorySuccessEvent(DirectoryEvent.Operation.REMOVE);
|
||||||
|
}
|
||||||
|
catch (GuacamoleException | RuntimeException | Error e) {
|
||||||
|
fireDirectoryFailureEvent(DirectoryEvent.Operation.REMOVE, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.rest.directory;
|
package org.apache.guacamole.rest.directory;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Identifiable;
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
@@ -41,6 +42,9 @@ public interface DirectoryObjectResourceFactory<InternalType extends Identifiabl
|
|||||||
/**
|
/**
|
||||||
* Creates a new DirectoryObjectResource which exposes the given object.
|
* Creates a new DirectoryObjectResource which exposes the given object.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing the resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext which contains the given Directory.
|
* The UserContext which contains the given Directory.
|
||||||
*
|
*
|
||||||
@@ -55,7 +59,7 @@ public interface DirectoryObjectResourceFactory<InternalType extends Identifiabl
|
|||||||
* A new DirectoryObjectResource which exposes the given object.
|
* A new DirectoryObjectResource which exposes the given object.
|
||||||
*/
|
*/
|
||||||
DirectoryObjectResource<InternalType, ExternalType>
|
DirectoryObjectResource<InternalType, ExternalType>
|
||||||
create(UserContext userContext, Directory<InternalType> directory,
|
create(AuthenticatedUser authenticatedUser, UserContext userContext,
|
||||||
InternalType object);
|
Directory<InternalType> directory, InternalType object);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import java.util.Collection;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.inject.Inject;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.PATCH;
|
import javax.ws.rs.PATCH;
|
||||||
@@ -36,6 +37,8 @@ import org.apache.guacamole.GuacamoleClientException;
|
|||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
||||||
import org.apache.guacamole.GuacamoleUnsupportedException;
|
import org.apache.guacamole.GuacamoleUnsupportedException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Identifiable;
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
import org.apache.guacamole.net.auth.Permissions;
|
import org.apache.guacamole.net.auth.Permissions;
|
||||||
@@ -44,7 +47,11 @@ import org.apache.guacamole.net.auth.permission.ObjectPermission;
|
|||||||
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
|
import org.apache.guacamole.net.auth.permission.ObjectPermissionSet;
|
||||||
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
import org.apache.guacamole.net.auth.permission.SystemPermission;
|
||||||
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
|
import org.apache.guacamole.net.auth.permission.SystemPermissionSet;
|
||||||
|
import org.apache.guacamole.net.event.DirectoryEvent;
|
||||||
|
import org.apache.guacamole.net.event.DirectoryFailureEvent;
|
||||||
|
import org.apache.guacamole.net.event.DirectorySuccessEvent;
|
||||||
import org.apache.guacamole.rest.APIPatch;
|
import org.apache.guacamole.rest.APIPatch;
|
||||||
|
import org.apache.guacamole.rest.event.ListenerService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A REST resource which abstracts the operations available on all Guacamole
|
* A REST resource which abstracts the operations available on all Guacamole
|
||||||
@@ -68,12 +75,23 @@ import org.apache.guacamole.rest.APIPatch;
|
|||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public abstract class DirectoryResource<InternalType extends Identifiable, ExternalType> {
|
public abstract class DirectoryResource<InternalType extends Identifiable, ExternalType> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*/
|
||||||
|
private final AuthenticatedUser authenticatedUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The UserContext associated with the Directory being exposed by this
|
* The UserContext associated with the Directory being exposed by this
|
||||||
* DirectoryResource.
|
* DirectoryResource.
|
||||||
*/
|
*/
|
||||||
private final UserContext userContext;
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of object contained within the Directory exposed by this
|
||||||
|
* DirectoryResource.
|
||||||
|
*/
|
||||||
|
private final Class<InternalType> internalType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Directory being exposed by this DirectoryResource.
|
* The Directory being exposed by this DirectoryResource.
|
||||||
*/
|
*/
|
||||||
@@ -92,13 +110,25 @@ public abstract class DirectoryResource<InternalType extends Identifiable, Exter
|
|||||||
*/
|
*/
|
||||||
private final DirectoryObjectResourceFactory<InternalType, ExternalType> resourceFactory;
|
private final DirectoryObjectResourceFactory<InternalType, ExternalType> resourceFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for dispatching events to registered listeners.
|
||||||
|
*/
|
||||||
|
@Inject
|
||||||
|
private ListenerService listenerService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new DirectoryResource which exposes the operations available
|
* Creates a new DirectoryResource which exposes the operations available
|
||||||
* for the given Directory.
|
* for the given Directory.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
|
* @param internalType
|
||||||
|
* The type of object contained within the given Directory.
|
||||||
|
*
|
||||||
* @param directory
|
* @param directory
|
||||||
* The Directory being exposed by this DirectoryResource.
|
* The Directory being exposed by this DirectoryResource.
|
||||||
*
|
*
|
||||||
@@ -110,11 +140,15 @@ public abstract class DirectoryResource<InternalType extends Identifiable, Exter
|
|||||||
* A factory which can be used to create instances of resources
|
* A factory which can be used to create instances of resources
|
||||||
* representing individual objects contained within the given Directory.
|
* representing individual objects contained within the given Directory.
|
||||||
*/
|
*/
|
||||||
public DirectoryResource(UserContext userContext, Directory<InternalType> directory,
|
public DirectoryResource(AuthenticatedUser authenticatedUser,
|
||||||
|
UserContext userContext, Class<InternalType> internalType,
|
||||||
|
Directory<InternalType> directory,
|
||||||
DirectoryObjectTranslator<InternalType, ExternalType> translator,
|
DirectoryObjectTranslator<InternalType, ExternalType> translator,
|
||||||
DirectoryObjectResourceFactory<InternalType, ExternalType> resourceFactory) {
|
DirectoryObjectResourceFactory<InternalType, ExternalType> resourceFactory) {
|
||||||
|
this.authenticatedUser = authenticatedUser;
|
||||||
this.userContext = userContext;
|
this.userContext = userContext;
|
||||||
this.directory = directory;
|
this.directory = directory;
|
||||||
|
this.internalType = internalType;
|
||||||
this.translator = translator;
|
this.translator = translator;
|
||||||
this.resourceFactory = resourceFactory;
|
this.resourceFactory = resourceFactory;
|
||||||
}
|
}
|
||||||
@@ -139,6 +173,174 @@ public abstract class DirectoryResource<InternalType extends Identifiable, Exter
|
|||||||
protected abstract ObjectPermissionSet getObjectPermissions(
|
protected abstract ObjectPermissionSet getObjectPermissions(
|
||||||
Permissions permissions) throws GuacamoleException;
|
Permissions permissions) throws GuacamoleException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies all registered listeners that the given operation has succeeded
|
||||||
|
* against the object having the given identifier within the Directory
|
||||||
|
* represented by this resource.
|
||||||
|
*
|
||||||
|
* @param operation
|
||||||
|
* The operation that was performed.
|
||||||
|
*
|
||||||
|
* @param identifier
|
||||||
|
* The identifier of the object affected by the operation.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
* The specific object affected by the operation, if available. If not
|
||||||
|
* available, this may be null.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If a listener throws a GuacamoleException from its event handler.
|
||||||
|
*/
|
||||||
|
protected void fireDirectorySuccessEvent(DirectoryEvent.Operation operation,
|
||||||
|
String identifier, InternalType object)
|
||||||
|
throws GuacamoleException {
|
||||||
|
listenerService.handleEvent(new DirectorySuccessEvent<InternalType>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Directory.Type getDirectoryType() {
|
||||||
|
return Directory.Type.of(internalType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DirectoryEvent.Operation getOperation() {
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getObjectIdentifier() {
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InternalType getObject() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatedUser getAuthenticatedUser() {
|
||||||
|
return authenticatedUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationProvider getAuthenticationProvider() {
|
||||||
|
return userContext.getAuthenticationProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies all registered listeners that the given operation has failed
|
||||||
|
* against the object having the given identifier within the Directory
|
||||||
|
* represented by this resource.
|
||||||
|
*
|
||||||
|
* @param operation
|
||||||
|
* The operation that failed.
|
||||||
|
*
|
||||||
|
* @param identifier
|
||||||
|
* The identifier of the object that would have been affected by the
|
||||||
|
* operation had it succeeded.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
* The specific object would have been affected by the operation, if
|
||||||
|
* available, had it succeeded, including any changes that were
|
||||||
|
* intended to be applied to the object. If not available, this may be
|
||||||
|
* null.
|
||||||
|
*
|
||||||
|
* @param failure
|
||||||
|
* The failure that occurred.
|
||||||
|
*
|
||||||
|
* @throws GuacamoleException
|
||||||
|
* If a listener throws a GuacamoleException from its event handler.
|
||||||
|
*/
|
||||||
|
protected void fireDirectoryFailureEvent(DirectoryEvent.Operation operation,
|
||||||
|
String identifier, InternalType object, Throwable failure)
|
||||||
|
throws GuacamoleException {
|
||||||
|
listenerService.handleEvent(new DirectoryFailureEvent<InternalType>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Directory.Type getDirectoryType() {
|
||||||
|
return Directory.Type.of(internalType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DirectoryEvent.Operation getOperation() {
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getObjectIdentifier() {
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InternalType getObject() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticatedUser getAuthenticatedUser() {
|
||||||
|
return authenticatedUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AuthenticationProvider getAuthenticationProvider() {
|
||||||
|
return userContext.getAuthenticationProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Throwable getFailure() {
|
||||||
|
return failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the user accessing this resource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The user accessing this resource.
|
||||||
|
*/
|
||||||
|
protected AuthenticatedUser getAuthenticatedUser() {
|
||||||
|
return authenticatedUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the UserContext providing the Directory exposed by this
|
||||||
|
* resource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The UserContext providing the Directory exposed by this resource.
|
||||||
|
*/
|
||||||
|
protected UserContext getUserContext() {
|
||||||
|
return userContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Directory exposed by this resource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The Directory exposed by this resource.
|
||||||
|
*/
|
||||||
|
protected Directory<InternalType> getDirectory() {
|
||||||
|
return directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a factory that can be used to create instances of resources
|
||||||
|
* representing individual objects contained within the Directory exposed
|
||||||
|
* by this resource.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A factory that can be used to create instances of resources
|
||||||
|
* representing individual objects contained within the Directory
|
||||||
|
* exposed by this resource.
|
||||||
|
*/
|
||||||
|
public DirectoryObjectResourceFactory<InternalType, ExternalType> getResourceFactory() {
|
||||||
|
return resourceFactory;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a map of all objects available within this DirectoryResource,
|
* Returns a map of all objects available within this DirectoryResource,
|
||||||
* filtering the returned map by the given permission, if specified.
|
* filtering the returned map by the given permission, if specified.
|
||||||
@@ -213,7 +415,15 @@ public abstract class DirectoryResource<InternalType extends Identifiable, Exter
|
|||||||
throw new GuacamoleClientException("Patch paths must start with \"/\".");
|
throw new GuacamoleClientException("Patch paths must start with \"/\".");
|
||||||
|
|
||||||
// Remove specified object
|
// Remove specified object
|
||||||
directory.remove(path.substring(1));
|
String identifier = path.substring(1);
|
||||||
|
try {
|
||||||
|
directory.remove(identifier);
|
||||||
|
fireDirectorySuccessEvent(DirectoryEvent.Operation.REMOVE, identifier, null);
|
||||||
|
}
|
||||||
|
catch (GuacamoleException | RuntimeException | Error e) {
|
||||||
|
fireDirectoryFailureEvent(DirectoryEvent.Operation.REMOVE, identifier, null, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,11 +454,18 @@ public abstract class DirectoryResource<InternalType extends Identifiable, Exter
|
|||||||
|
|
||||||
// Filter/sanitize object contents
|
// Filter/sanitize object contents
|
||||||
translator.filterExternalObject(userContext, object);
|
translator.filterExternalObject(userContext, object);
|
||||||
|
InternalType internal = translator.toInternalObject(object);
|
||||||
|
|
||||||
// Create the new object within the directory
|
// Create the new object within the directory
|
||||||
directory.add(translator.toInternalObject(object));
|
try {
|
||||||
|
directory.add(internal);
|
||||||
return object;
|
fireDirectorySuccessEvent(DirectoryEvent.Operation.ADD, internal.getIdentifier(), internal);
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
catch (GuacamoleException | RuntimeException | Error e) {
|
||||||
|
fireDirectoryFailureEvent(DirectoryEvent.Operation.ADD, internal.getIdentifier(), internal, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,12 +489,21 @@ public abstract class DirectoryResource<InternalType extends Identifiable, Exter
|
|||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
// Retrieve the object having the given identifier
|
// Retrieve the object having the given identifier
|
||||||
InternalType object = directory.get(identifier);
|
InternalType object;
|
||||||
if (object == null)
|
try {
|
||||||
throw new GuacamoleResourceNotFoundException("Not found: \"" + identifier + "\"");
|
object = directory.get(identifier);
|
||||||
|
if (object == null)
|
||||||
|
throw new GuacamoleResourceNotFoundException("Not found: \"" + identifier + "\"");
|
||||||
|
}
|
||||||
|
catch (GuacamoleException | RuntimeException | Error e) {
|
||||||
|
fireDirectoryFailureEvent(DirectoryEvent.Operation.GET, identifier, null, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
// Return a resource which provides access to the retrieved object
|
// Return a resource which provides access to the retrieved object
|
||||||
return resourceFactory.create(userContext, directory, object);
|
DirectoryObjectResource<InternalType, ExternalType> resource = resourceFactory.create(authenticatedUser, userContext, directory, object);
|
||||||
|
fireDirectorySuccessEvent(DirectoryEvent.Operation.GET, identifier, object);
|
||||||
|
return resource;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.rest.directory;
|
package org.apache.guacamole.rest.directory;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Identifiable;
|
import org.apache.guacamole.net.auth.Identifiable;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
@@ -41,6 +42,9 @@ public interface DirectoryResourceFactory<InternalType extends Identifiable, Ext
|
|||||||
/**
|
/**
|
||||||
* Creates a new DirectoryResource which exposes the given Directory.
|
* Creates a new DirectoryResource which exposes the given Directory.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing the resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext from which the given Directory was obtained.
|
* The UserContext from which the given Directory was obtained.
|
||||||
*
|
*
|
||||||
@@ -52,6 +56,7 @@ public interface DirectoryResourceFactory<InternalType extends Identifiable, Ext
|
|||||||
* A new DirectoryResource which exposes the given Directory.
|
* A new DirectoryResource which exposes the given Directory.
|
||||||
*/
|
*/
|
||||||
DirectoryResource<InternalType, ExternalType>
|
DirectoryResource<InternalType, ExternalType>
|
||||||
create(UserContext userContext, Directory<InternalType> directory);
|
create(AuthenticatedUser authenticatedUser, UserContext userContext,
|
||||||
|
Directory<InternalType> directory);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -116,7 +116,7 @@ public class SessionResource {
|
|||||||
UserContext userContext = session.getUserContext(authProviderIdentifier);
|
UserContext userContext = session.getUserContext(authProviderIdentifier);
|
||||||
|
|
||||||
// Return a resource exposing the retrieved UserContext
|
// Return a resource exposing the retrieved UserContext
|
||||||
return userContextResourceFactory.create(userContext);
|
return userContextResourceFactory.create(session.getAuthenticatedUser(), userContext);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,6 +30,7 @@ import javax.ws.rs.Produces;
|
|||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.net.auth.ActiveConnection;
|
import org.apache.guacamole.net.auth.ActiveConnection;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Connection;
|
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.SharingProfile;
|
import org.apache.guacamole.net.auth.SharingProfile;
|
||||||
@@ -59,6 +60,11 @@ public class UserContextResource {
|
|||||||
*/
|
*/
|
||||||
private final UserContext userContext;
|
private final UserContext userContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*/
|
||||||
|
private final AuthenticatedUser authenticatedUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for creating DirectoryObjectResources which expose a given User.
|
* Factory for creating DirectoryObjectResources which expose a given User.
|
||||||
*/
|
*/
|
||||||
@@ -115,12 +121,17 @@ public class UserContextResource {
|
|||||||
* Creates a new UserContextResource which exposes the data within the
|
* Creates a new UserContextResource which exposes the data within the
|
||||||
* given UserContext.
|
* given UserContext.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext which should be exposed through this
|
* The UserContext which should be exposed through this
|
||||||
* UserContextResource.
|
* UserContextResource.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public UserContextResource(@Assisted UserContext userContext) {
|
public UserContextResource(@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext) {
|
||||||
|
this.authenticatedUser = authenticatedUser;
|
||||||
this.userContext = userContext;
|
this.userContext = userContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +151,7 @@ public class UserContextResource {
|
|||||||
@Path("self")
|
@Path("self")
|
||||||
public DirectoryObjectResource<User, APIUser> getSelfResource()
|
public DirectoryObjectResource<User, APIUser> getSelfResource()
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
return userResourceFactory.create(userContext,
|
return userResourceFactory.create(authenticatedUser, userContext,
|
||||||
userContext.getUserDirectory(), userContext.self());
|
userContext.getUserDirectory(), userContext.self());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,8 +169,8 @@ public class UserContextResource {
|
|||||||
@Path("activeConnections")
|
@Path("activeConnections")
|
||||||
public DirectoryResource<ActiveConnection, APIActiveConnection>
|
public DirectoryResource<ActiveConnection, APIActiveConnection>
|
||||||
getActiveConnectionDirectoryResource() throws GuacamoleException {
|
getActiveConnectionDirectoryResource() throws GuacamoleException {
|
||||||
return activeConnectionDirectoryResourceFactory.create(userContext,
|
return activeConnectionDirectoryResourceFactory.create(authenticatedUser,
|
||||||
userContext.getActiveConnectionDirectory());
|
userContext, userContext.getActiveConnectionDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,8 +187,8 @@ public class UserContextResource {
|
|||||||
@Path("connections")
|
@Path("connections")
|
||||||
public DirectoryResource<Connection, APIConnection> getConnectionDirectoryResource()
|
public DirectoryResource<Connection, APIConnection> getConnectionDirectoryResource()
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
return connectionDirectoryResourceFactory.create(userContext,
|
return connectionDirectoryResourceFactory.create(authenticatedUser,
|
||||||
userContext.getConnectionDirectory());
|
userContext, userContext.getConnectionDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -194,8 +205,8 @@ public class UserContextResource {
|
|||||||
@Path("connectionGroups")
|
@Path("connectionGroups")
|
||||||
public DirectoryResource<ConnectionGroup, APIConnectionGroup> getConnectionGroupDirectoryResource()
|
public DirectoryResource<ConnectionGroup, APIConnectionGroup> getConnectionGroupDirectoryResource()
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
return connectionGroupDirectoryResourceFactory.create(userContext,
|
return connectionGroupDirectoryResourceFactory.create(authenticatedUser,
|
||||||
userContext.getConnectionGroupDirectory());
|
userContext, userContext.getConnectionGroupDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -212,8 +223,8 @@ public class UserContextResource {
|
|||||||
@Path("sharingProfiles")
|
@Path("sharingProfiles")
|
||||||
public DirectoryResource<SharingProfile, APISharingProfile>
|
public DirectoryResource<SharingProfile, APISharingProfile>
|
||||||
getSharingProfileDirectoryResource() throws GuacamoleException {
|
getSharingProfileDirectoryResource() throws GuacamoleException {
|
||||||
return sharingProfileDirectoryResourceFactory.create(userContext,
|
return sharingProfileDirectoryResourceFactory.create(authenticatedUser,
|
||||||
userContext.getSharingProfileDirectory());
|
userContext, userContext.getSharingProfileDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -230,8 +241,8 @@ public class UserContextResource {
|
|||||||
@Path("users")
|
@Path("users")
|
||||||
public DirectoryResource<User, APIUser> getUserDirectoryResource()
|
public DirectoryResource<User, APIUser> getUserDirectoryResource()
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
return userDirectoryResourceFactory.create(userContext,
|
return userDirectoryResourceFactory.create(authenticatedUser,
|
||||||
userContext.getUserDirectory());
|
userContext, userContext.getUserDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -248,8 +259,8 @@ public class UserContextResource {
|
|||||||
@Path("userGroups")
|
@Path("userGroups")
|
||||||
public DirectoryResource<UserGroup, APIUserGroup> getUserGroupDirectoryResource()
|
public DirectoryResource<UserGroup, APIUserGroup> getUserGroupDirectoryResource()
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
return userGroupDirectoryResourceFactory.create(userContext,
|
return userGroupDirectoryResourceFactory.create(authenticatedUser,
|
||||||
userContext.getUserGroupDirectory());
|
userContext, userContext.getUserGroupDirectory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.rest.session;
|
package org.apache.guacamole.rest.session;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,6 +32,9 @@ public interface UserContextResourceFactory {
|
|||||||
* Creates a new UserContextResource which exposes the contents of the
|
* Creates a new UserContextResource which exposes the contents of the
|
||||||
* given UserContext.
|
* given UserContext.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing the resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext whose contents should be exposed.
|
* The UserContext whose contents should be exposed.
|
||||||
*
|
*
|
||||||
@@ -38,6 +42,7 @@ public interface UserContextResourceFactory {
|
|||||||
* A new UserContextResource which exposes the contents of the given
|
* A new UserContextResource which exposes the contents of the given
|
||||||
* UserContext.
|
* UserContext.
|
||||||
*/
|
*/
|
||||||
UserContextResource create(UserContext userContext);
|
UserContextResource create(AuthenticatedUser authenticatedUser,
|
||||||
|
UserContext userContext);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import javax.ws.rs.Consumes;
|
|||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Permissions;
|
import org.apache.guacamole.net.auth.Permissions;
|
||||||
import org.apache.guacamole.net.auth.SharingProfile;
|
import org.apache.guacamole.net.auth.SharingProfile;
|
||||||
@@ -48,6 +49,9 @@ public class SharingProfileDirectoryResource
|
|||||||
* operations and subresources available for the given SharingProfile
|
* operations and subresources available for the given SharingProfile
|
||||||
* Directory.
|
* Directory.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -63,11 +67,13 @@ public class SharingProfileDirectoryResource
|
|||||||
* representing SharingProfiles.
|
* representing SharingProfiles.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public SharingProfileDirectoryResource(@Assisted UserContext userContext,
|
public SharingProfileDirectoryResource(
|
||||||
|
@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<SharingProfile> directory,
|
@Assisted Directory<SharingProfile> directory,
|
||||||
DirectoryObjectTranslator<SharingProfile, APISharingProfile> translator,
|
DirectoryObjectTranslator<SharingProfile, APISharingProfile> translator,
|
||||||
DirectoryObjectResourceFactory<SharingProfile, APISharingProfile> resourceFactory) {
|
DirectoryObjectResourceFactory<SharingProfile, APISharingProfile> resourceFactory) {
|
||||||
super(userContext, directory, translator, resourceFactory);
|
super(authenticatedUser, userContext, SharingProfile.class, directory, translator, resourceFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -29,6 +29,7 @@ import javax.ws.rs.Produces;
|
|||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Permissions;
|
import org.apache.guacamole.net.auth.Permissions;
|
||||||
import org.apache.guacamole.net.auth.SharingProfile;
|
import org.apache.guacamole.net.auth.SharingProfile;
|
||||||
@@ -49,21 +50,13 @@ import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
|||||||
public class SharingProfileResource
|
public class SharingProfileResource
|
||||||
extends DirectoryObjectResource<SharingProfile, APISharingProfile> {
|
extends DirectoryObjectResource<SharingProfile, APISharingProfile> {
|
||||||
|
|
||||||
/**
|
|
||||||
* The UserContext associated with the Directory which contains the
|
|
||||||
* SharingProfile exposed by this resource.
|
|
||||||
*/
|
|
||||||
private final UserContext userContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The SharingProfile object represented by this SharingProfileResource.
|
|
||||||
*/
|
|
||||||
private final SharingProfile sharingProfile;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new SharingProfileResource which exposes the operations and
|
* Creates a new SharingProfileResource which exposes the operations and
|
||||||
* subresources available for the given SharingProfile.
|
* subresources available for the given SharingProfile.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -78,13 +71,12 @@ public class SharingProfileResource
|
|||||||
* object given.
|
* object given.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public SharingProfileResource(@Assisted UserContext userContext,
|
public SharingProfileResource(@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<SharingProfile> directory,
|
@Assisted Directory<SharingProfile> directory,
|
||||||
@Assisted SharingProfile sharingProfile,
|
@Assisted SharingProfile sharingProfile,
|
||||||
DirectoryObjectTranslator<SharingProfile, APISharingProfile> translator) {
|
DirectoryObjectTranslator<SharingProfile, APISharingProfile> translator) {
|
||||||
super(userContext, directory, sharingProfile, translator);
|
super(authenticatedUser, userContext, SharingProfile.class, directory, sharingProfile, translator);
|
||||||
this.userContext = userContext;
|
|
||||||
this.sharingProfile = sharingProfile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,8 +95,10 @@ public class SharingProfileResource
|
|||||||
public Map<String, String> getParameters()
|
public Map<String, String> getParameters()
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
SharingProfile sharingProfile = getInternalObject();
|
||||||
|
|
||||||
// Pull effective permissions
|
// Pull effective permissions
|
||||||
Permissions effective = userContext.self().getEffectivePermissions();
|
Permissions effective = getUserContext().self().getEffectivePermissions();
|
||||||
|
|
||||||
// Retrieve permission sets
|
// Retrieve permission sets
|
||||||
SystemPermissionSet systemPermissions = effective.getSystemPermissions();
|
SystemPermissionSet systemPermissions = effective.getSystemPermissions();
|
||||||
|
@@ -105,7 +105,7 @@ public class TunnelCollectionResource {
|
|||||||
throw new GuacamoleResourceNotFoundException("No such tunnel.");
|
throw new GuacamoleResourceNotFoundException("No such tunnel.");
|
||||||
|
|
||||||
// Return corresponding tunnel resource
|
// Return corresponding tunnel resource
|
||||||
return tunnelResourceFactory.create(tunnel);
|
return tunnelResourceFactory.create(session.getAuthenticatedUser(), tunnel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,6 +34,7 @@ import org.apache.guacamole.GuacamoleException;
|
|||||||
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
import org.apache.guacamole.GuacamoleResourceNotFoundException;
|
||||||
import org.apache.guacamole.environment.Environment;
|
import org.apache.guacamole.environment.Environment;
|
||||||
import org.apache.guacamole.net.auth.ActiveConnection;
|
import org.apache.guacamole.net.auth.ActiveConnection;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
import org.apache.guacamole.protocols.ProtocolInfo;
|
import org.apache.guacamole.protocols.ProtocolInfo;
|
||||||
import org.apache.guacamole.rest.activeconnection.APIActiveConnection;
|
import org.apache.guacamole.rest.activeconnection.APIActiveConnection;
|
||||||
@@ -55,6 +56,11 @@ public class TunnelResource {
|
|||||||
*/
|
*/
|
||||||
private static final String DEFAULT_MEDIA_TYPE = MediaType.APPLICATION_OCTET_STREAM;
|
private static final String DEFAULT_MEDIA_TYPE = MediaType.APPLICATION_OCTET_STREAM;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*/
|
||||||
|
private final AuthenticatedUser authenticatedUser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The tunnel that this TunnelResource represents.
|
* The tunnel that this TunnelResource represents.
|
||||||
*/
|
*/
|
||||||
@@ -78,11 +84,16 @@ public class TunnelResource {
|
|||||||
* Creates a new TunnelResource which exposes the operations and
|
* Creates a new TunnelResource which exposes the operations and
|
||||||
* subresources available for the given tunnel.
|
* subresources available for the given tunnel.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param tunnel
|
* @param tunnel
|
||||||
* The tunnel that this TunnelResource should represent.
|
* The tunnel that this TunnelResource should represent.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public TunnelResource(@Assisted UserTunnel tunnel) {
|
public TunnelResource(@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserTunnel tunnel) {
|
||||||
|
this.authenticatedUser = authenticatedUser;
|
||||||
this.tunnel = tunnel;
|
this.tunnel = tunnel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +121,7 @@ public class TunnelResource {
|
|||||||
throw new GuacamoleResourceNotFoundException("No readable active connection for tunnel.");
|
throw new GuacamoleResourceNotFoundException("No readable active connection for tunnel.");
|
||||||
|
|
||||||
// Return the associated ActiveConnection as a resource
|
// Return the associated ActiveConnection as a resource
|
||||||
return activeConnectionResourceFactory.create(userContext,
|
return activeConnectionResourceFactory.create(authenticatedUser, userContext,
|
||||||
userContext.getActiveConnectionDirectory(), activeConnection);
|
userContext.getActiveConnectionDirectory(), activeConnection);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.apache.guacamole.rest.tunnel;
|
package org.apache.guacamole.rest.tunnel;
|
||||||
|
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.tunnel.UserTunnel;
|
import org.apache.guacamole.tunnel.UserTunnel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,12 +32,15 @@ public interface TunnelResourceFactory {
|
|||||||
* Creates a new TunnelResource which exposes the contents of the
|
* Creates a new TunnelResource which exposes the contents of the
|
||||||
* given tunnel.
|
* given tunnel.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing the resource.
|
||||||
|
*
|
||||||
* @param tunnel
|
* @param tunnel
|
||||||
* The tunnel whose contents should be exposed.
|
* The tunnel whose contents should be exposed.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* A new TunnelResource which exposes the contents of the given tunnel.
|
* A new TunnelResource which exposes the contents of the given tunnel.
|
||||||
*/
|
*/
|
||||||
TunnelResource create(UserTunnel tunnel);
|
TunnelResource create(AuthenticatedUser authenticatedUser, UserTunnel tunnel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import javax.ws.rs.Consumes;
|
|||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.User;
|
import org.apache.guacamole.net.auth.User;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Permissions;
|
import org.apache.guacamole.net.auth.Permissions;
|
||||||
@@ -46,6 +47,9 @@ public class UserDirectoryResource extends DirectoryResource<User, APIUser> {
|
|||||||
* Creates a new UserDirectoryResource which exposes the operations and
|
* Creates a new UserDirectoryResource which exposes the operations and
|
||||||
* subresources available for the given User Directory.
|
* subresources available for the given User Directory.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -61,11 +65,12 @@ public class UserDirectoryResource extends DirectoryResource<User, APIUser> {
|
|||||||
* representing Users.
|
* representing Users.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public UserDirectoryResource(@Assisted UserContext userContext,
|
public UserDirectoryResource(@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<User> directory,
|
@Assisted Directory<User> directory,
|
||||||
DirectoryObjectTranslator<User, APIUser> translator,
|
DirectoryObjectTranslator<User, APIUser> translator,
|
||||||
DirectoryObjectResourceFactory<User, APIUser> resourceFactory) {
|
DirectoryObjectResourceFactory<User, APIUser> resourceFactory) {
|
||||||
super(userContext, directory, translator, resourceFactory);
|
super(authenticatedUser, userContext, User.class, directory, translator, resourceFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -33,6 +33,7 @@ import javax.ws.rs.core.MediaType;
|
|||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
import org.apache.guacamole.GuacamoleSecurityException;
|
import org.apache.guacamole.GuacamoleSecurityException;
|
||||||
import org.apache.guacamole.GuacamoleUnsupportedException;
|
import org.apache.guacamole.GuacamoleUnsupportedException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
import org.apache.guacamole.net.auth.AuthenticationProvider;
|
||||||
import org.apache.guacamole.net.auth.Credentials;
|
import org.apache.guacamole.net.auth.Credentials;
|
||||||
import org.apache.guacamole.net.auth.User;
|
import org.apache.guacamole.net.auth.User;
|
||||||
@@ -40,6 +41,7 @@ import org.apache.guacamole.net.auth.Directory;
|
|||||||
import org.apache.guacamole.net.auth.UserContext;
|
import org.apache.guacamole.net.auth.UserContext;
|
||||||
import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException;
|
import org.apache.guacamole.net.auth.credentials.GuacamoleCredentialsException;
|
||||||
import org.apache.guacamole.net.auth.simple.SimpleActivityRecordSet;
|
import org.apache.guacamole.net.auth.simple.SimpleActivityRecordSet;
|
||||||
|
import org.apache.guacamole.net.event.DirectoryEvent;
|
||||||
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
import org.apache.guacamole.rest.directory.DirectoryObjectResource;
|
||||||
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
import org.apache.guacamole.rest.directory.DirectoryObjectTranslator;
|
||||||
import org.apache.guacamole.rest.history.UserHistoryResource;
|
import org.apache.guacamole.rest.history.UserHistoryResource;
|
||||||
@@ -63,27 +65,13 @@ public class UserResource
|
|||||||
*/
|
*/
|
||||||
private static final Logger logger = LoggerFactory.getLogger(UserResource.class);
|
private static final Logger logger = LoggerFactory.getLogger(UserResource.class);
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* Creates a new UserResource which exposes the operations and subresources
|
||||||
* available for the given User.
|
* available for the given User.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -97,14 +85,12 @@ public class UserResource
|
|||||||
* A DirectoryObjectTranslator implementation which handles Users.
|
* A DirectoryObjectTranslator implementation which handles Users.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public UserResource(@Assisted UserContext userContext,
|
public UserResource(@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<User> directory,
|
@Assisted Directory<User> directory,
|
||||||
@Assisted User user,
|
@Assisted User user,
|
||||||
DirectoryObjectTranslator<User, APIUser> translator) {
|
DirectoryObjectTranslator<User, APIUser> translator) {
|
||||||
super(userContext, directory, user, translator);
|
super(authenticatedUser, userContext, User.class, directory, user, translator);
|
||||||
this.userContext = userContext;
|
|
||||||
this.directory = directory;
|
|
||||||
this.user = user;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,6 +108,8 @@ public class UserResource
|
|||||||
public UserHistoryResource getUserHistory()
|
public UserHistoryResource getUserHistory()
|
||||||
throws GuacamoleException {
|
throws GuacamoleException {
|
||||||
|
|
||||||
|
User user = getInternalObject();
|
||||||
|
|
||||||
// First try to retrieve history using the current getUserHistory() method.
|
// First try to retrieve history using the current getUserHistory() method.
|
||||||
try {
|
try {
|
||||||
return new UserHistoryResource(user.getUserHistory());
|
return new UserHistoryResource(user.getUserHistory());
|
||||||
@@ -147,13 +135,19 @@ public class UserResource
|
|||||||
public void updateObject(APIUser modifiedObject) throws GuacamoleException {
|
public void updateObject(APIUser modifiedObject) throws GuacamoleException {
|
||||||
|
|
||||||
// A user may not use this endpoint to update their password
|
// A user may not use this endpoint to update their password
|
||||||
User currentUser = userContext.self();
|
try {
|
||||||
if (
|
User currentUser = getUserContext().self();
|
||||||
currentUser.getIdentifier().equals(modifiedObject.getUsername())
|
if (
|
||||||
&& modifiedObject.getPassword() != null) {
|
currentUser.getIdentifier().equals(modifiedObject.getUsername())
|
||||||
throw new GuacamoleSecurityException(
|
&& modifiedObject.getPassword() != null) {
|
||||||
"Permission denied. The password update endpoint must"
|
throw new GuacamoleSecurityException(
|
||||||
+ " be used to change the current user's password.");
|
"Permission denied. The password update endpoint must"
|
||||||
|
+ " be used to change the current user's password.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (GuacamoleException | RuntimeException | Error e) {
|
||||||
|
fireDirectoryFailureEvent(DirectoryEvent.Operation.UPDATE, e);
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.updateObject(modifiedObject);
|
super.updateObject(modifiedObject);
|
||||||
@@ -178,13 +172,15 @@ public class UserResource
|
|||||||
public void updatePassword(APIUserPasswordUpdate userPasswordUpdate,
|
public void updatePassword(APIUserPasswordUpdate userPasswordUpdate,
|
||||||
@Context HttpServletRequest request) throws GuacamoleException {
|
@Context HttpServletRequest request) throws GuacamoleException {
|
||||||
|
|
||||||
|
User user = getInternalObject();
|
||||||
|
|
||||||
// Build credentials
|
// Build credentials
|
||||||
Credentials credentials = new Credentials(user.getIdentifier(),
|
Credentials credentials = new Credentials(user.getIdentifier(),
|
||||||
userPasswordUpdate.getOldPassword(), request);
|
userPasswordUpdate.getOldPassword(), request);
|
||||||
|
|
||||||
// Verify that the old password was correct
|
// Verify that the old password was correct
|
||||||
try {
|
try {
|
||||||
AuthenticationProvider authProvider = userContext.getAuthenticationProvider();
|
AuthenticationProvider authProvider = getUserContext().getAuthenticationProvider();
|
||||||
if (authProvider.authenticateUser(credentials) == null)
|
if (authProvider.authenticateUser(credentials) == null)
|
||||||
throw new GuacamoleSecurityException("Permission denied.");
|
throw new GuacamoleSecurityException("Permission denied.");
|
||||||
}
|
}
|
||||||
@@ -195,8 +191,15 @@ public class UserResource
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set password to the newly provided one
|
// Set password to the newly provided one
|
||||||
user.setPassword(userPasswordUpdate.getNewPassword());
|
try {
|
||||||
directory.update(user);
|
user.setPassword(userPasswordUpdate.getNewPassword());
|
||||||
|
getDirectory().update(user);
|
||||||
|
fireDirectorySuccessEvent(DirectoryEvent.Operation.UPDATE);
|
||||||
|
}
|
||||||
|
catch (GuacamoleException | RuntimeException | Error e) {
|
||||||
|
fireDirectoryFailureEvent(DirectoryEvent.Operation.UPDATE, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +214,7 @@ public class UserResource
|
|||||||
*/
|
*/
|
||||||
@Path("permissions")
|
@Path("permissions")
|
||||||
public PermissionSetResource getPermissions() {
|
public PermissionSetResource getPermissions() {
|
||||||
return new PermissionSetResource(user);
|
return new PermissionSetResource(getInternalObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -228,7 +231,7 @@ public class UserResource
|
|||||||
@GET
|
@GET
|
||||||
@Path("effectivePermissions")
|
@Path("effectivePermissions")
|
||||||
public APIPermissionSet getEffectivePermissions() throws GuacamoleException {
|
public APIPermissionSet getEffectivePermissions() throws GuacamoleException {
|
||||||
return new APIPermissionSet(user.getEffectivePermissions());
|
return new APIPermissionSet(getInternalObject().getEffectivePermissions());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -245,7 +248,7 @@ public class UserResource
|
|||||||
*/
|
*/
|
||||||
@Path("userGroups")
|
@Path("userGroups")
|
||||||
public RelatedObjectSetResource getUserGroups() throws GuacamoleException {
|
public RelatedObjectSetResource getUserGroups() throws GuacamoleException {
|
||||||
return new RelatedObjectSetResource(user.getUserGroups());
|
return new RelatedObjectSetResource(getInternalObject().getUserGroups());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import javax.ws.rs.Consumes;
|
|||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.UserGroup;
|
import org.apache.guacamole.net.auth.UserGroup;
|
||||||
import org.apache.guacamole.net.auth.Directory;
|
import org.apache.guacamole.net.auth.Directory;
|
||||||
import org.apache.guacamole.net.auth.Permissions;
|
import org.apache.guacamole.net.auth.Permissions;
|
||||||
@@ -46,6 +47,9 @@ public class UserGroupDirectoryResource extends DirectoryResource<UserGroup, API
|
|||||||
* Creates a new UserGroupDirectoryResource which exposes the operations
|
* Creates a new UserGroupDirectoryResource which exposes the operations
|
||||||
* and subresources available for the given UserGroup Directory.
|
* and subresources available for the given UserGroup Directory.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -61,11 +65,13 @@ public class UserGroupDirectoryResource extends DirectoryResource<UserGroup, API
|
|||||||
* representing UserGroups.
|
* representing UserGroups.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public UserGroupDirectoryResource(@Assisted UserContext userContext,
|
public UserGroupDirectoryResource(
|
||||||
|
@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<UserGroup> directory,
|
@Assisted Directory<UserGroup> directory,
|
||||||
DirectoryObjectTranslator<UserGroup, APIUserGroup> translator,
|
DirectoryObjectTranslator<UserGroup, APIUserGroup> translator,
|
||||||
DirectoryObjectResourceFactory<UserGroup, APIUserGroup> resourceFactory) {
|
DirectoryObjectResourceFactory<UserGroup, APIUserGroup> resourceFactory) {
|
||||||
super(userContext, directory, translator, resourceFactory);
|
super(authenticatedUser, userContext, UserGroup.class, directory, translator, resourceFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -26,6 +26,7 @@ import javax.ws.rs.Path;
|
|||||||
import javax.ws.rs.Produces;
|
import javax.ws.rs.Produces;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import org.apache.guacamole.GuacamoleException;
|
import org.apache.guacamole.GuacamoleException;
|
||||||
|
import org.apache.guacamole.net.auth.AuthenticatedUser;
|
||||||
import org.apache.guacamole.net.auth.UserGroup;
|
import org.apache.guacamole.net.auth.UserGroup;
|
||||||
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;
|
||||||
@@ -43,15 +44,13 @@ import org.apache.guacamole.rest.permission.PermissionSetResource;
|
|||||||
public class UserGroupResource
|
public class UserGroupResource
|
||||||
extends DirectoryObjectResource<UserGroup, APIUserGroup> {
|
extends DirectoryObjectResource<UserGroup, APIUserGroup> {
|
||||||
|
|
||||||
/**
|
|
||||||
* The UserGroup object represented by this UserGroupResource.
|
|
||||||
*/
|
|
||||||
private final UserGroup userGroup;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new UserGroupResource which exposes the operations and
|
* Creates a new UserGroupResource which exposes the operations and
|
||||||
* subresources available for the given UserGroup.
|
* subresources available for the given UserGroup.
|
||||||
*
|
*
|
||||||
|
* @param authenticatedUser
|
||||||
|
* The user that is accessing this resource.
|
||||||
|
*
|
||||||
* @param userContext
|
* @param userContext
|
||||||
* The UserContext associated with the given Directory.
|
* The UserContext associated with the given Directory.
|
||||||
*
|
*
|
||||||
@@ -65,12 +64,12 @@ public class UserGroupResource
|
|||||||
* A DirectoryObjectTranslator implementation which handles Users.
|
* A DirectoryObjectTranslator implementation which handles Users.
|
||||||
*/
|
*/
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
public UserGroupResource(@Assisted UserContext userContext,
|
public UserGroupResource(@Assisted AuthenticatedUser authenticatedUser,
|
||||||
|
@Assisted UserContext userContext,
|
||||||
@Assisted Directory<UserGroup> directory,
|
@Assisted Directory<UserGroup> directory,
|
||||||
@Assisted UserGroup userGroup,
|
@Assisted UserGroup userGroup,
|
||||||
DirectoryObjectTranslator<UserGroup, APIUserGroup> translator) {
|
DirectoryObjectTranslator<UserGroup, APIUserGroup> translator) {
|
||||||
super(userContext, directory, userGroup, translator);
|
super(authenticatedUser, userContext, UserGroup.class, directory, userGroup, translator);
|
||||||
this.userGroup = userGroup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,7 +86,7 @@ public class UserGroupResource
|
|||||||
*/
|
*/
|
||||||
@Path("userGroups")
|
@Path("userGroups")
|
||||||
public RelatedObjectSetResource getUserGroups() throws GuacamoleException {
|
public RelatedObjectSetResource getUserGroups() throws GuacamoleException {
|
||||||
return new RelatedObjectSetResource(userGroup.getUserGroups());
|
return new RelatedObjectSetResource(getInternalObject().getUserGroups());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,7 +103,7 @@ public class UserGroupResource
|
|||||||
*/
|
*/
|
||||||
@Path("memberUsers")
|
@Path("memberUsers")
|
||||||
public RelatedObjectSetResource getMemberUsers() throws GuacamoleException {
|
public RelatedObjectSetResource getMemberUsers() throws GuacamoleException {
|
||||||
return new RelatedObjectSetResource(userGroup.getMemberUsers());
|
return new RelatedObjectSetResource(getInternalObject().getMemberUsers());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,7 +120,7 @@ public class UserGroupResource
|
|||||||
*/
|
*/
|
||||||
@Path("memberUserGroups")
|
@Path("memberUserGroups")
|
||||||
public RelatedObjectSetResource getMemberUserGroups() throws GuacamoleException {
|
public RelatedObjectSetResource getMemberUserGroups() throws GuacamoleException {
|
||||||
return new RelatedObjectSetResource(userGroup.getMemberUserGroups());
|
return new RelatedObjectSetResource(getInternalObject().getMemberUserGroups());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,7 +134,7 @@ public class UserGroupResource
|
|||||||
*/
|
*/
|
||||||
@Path("permissions")
|
@Path("permissions")
|
||||||
public PermissionSetResource getPermissions() {
|
public PermissionSetResource getPermissions() {
|
||||||
return new PermissionSetResource(userGroup);
|
return new PermissionSetResource(getInternalObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user