mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-07 13:41:21 +00:00
GUAC-1161: Generalize APICredentialError into APIError. Provide consistent error responses for all REST endpoints.
This commit is contained in:
@@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2015 Glyptodon LLC
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.glyptodon.guacamole.net.basic.rest;
|
|
||||||
|
|
||||||
import org.glyptodon.guacamole.net.auth.credentials.CredentialsInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents an error related to either invalid or insufficient credentials
|
|
||||||
* submitted to a REST endpoint.
|
|
||||||
*
|
|
||||||
* @author Michael Jumper
|
|
||||||
*/
|
|
||||||
public class APICredentialError extends APIError {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The required credentials.
|
|
||||||
*/
|
|
||||||
private final CredentialsInfo info;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of error that occurred.
|
|
||||||
*/
|
|
||||||
private final Type type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All possible types of credential errors.
|
|
||||||
*/
|
|
||||||
public enum Type {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The credentials provided were invalid.
|
|
||||||
*/
|
|
||||||
INVALID,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The credentials provided were not necessarily invalid, but were not
|
|
||||||
* sufficient to determine validity.
|
|
||||||
*/
|
|
||||||
INSUFFICIENT
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new APICredentialError with the specified error message and
|
|
||||||
* credentials information.
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* The type of error that occurred.
|
|
||||||
*
|
|
||||||
* @param message
|
|
||||||
* The error message.
|
|
||||||
*
|
|
||||||
* @param info
|
|
||||||
* An object which describes the required credentials.
|
|
||||||
*/
|
|
||||||
public APICredentialError(Type type, String message, CredentialsInfo info) {
|
|
||||||
super(message);
|
|
||||||
this.type = type;
|
|
||||||
this.info = info;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the type of error that occurred.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The type of error that occurred.
|
|
||||||
*/
|
|
||||||
public Type getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an object which describes the required credentials.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* An object which describes the required credentials.
|
|
||||||
*/
|
|
||||||
public CredentialsInfo getInfo() {
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2014 Glyptodon LLC
|
* Copyright (C) 2015 Glyptodon LLC
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -22,9 +22,15 @@
|
|||||||
|
|
||||||
package org.glyptodon.guacamole.net.basic.rest;
|
package org.glyptodon.guacamole.net.basic.rest;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import org.glyptodon.guacamole.form.Parameter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple object to represent an error to be sent from the REST API.
|
* Describes an error that occurred within a REST endpoint.
|
||||||
|
*
|
||||||
* @author James Muehlner
|
* @author James Muehlner
|
||||||
|
* @author Michael Jumper
|
||||||
*/
|
*/
|
||||||
public class APIError {
|
public class APIError {
|
||||||
|
|
||||||
@@ -34,19 +40,143 @@ public class APIError {
|
|||||||
private final String message;
|
private final String message;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the error message.
|
* All expected request parameters, if any.
|
||||||
* @return The error message.
|
*/
|
||||||
|
private final Collection<Parameter> expected;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of error that occurred.
|
||||||
|
*/
|
||||||
|
private final Type type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All possible types of REST API errors.
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The requested operation could not be performed because the request
|
||||||
|
* itself was malformed.
|
||||||
|
*/
|
||||||
|
BAD_REQUEST(Response.Status.BAD_REQUEST),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The credentials provided were invalid.
|
||||||
|
*/
|
||||||
|
INVALID_CREDENTIALS(Response.Status.FORBIDDEN),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The credentials provided were not necessarily invalid, but were not
|
||||||
|
* sufficient to determine validity.
|
||||||
|
*/
|
||||||
|
INSUFFICIENT_CREDENTIALS(Response.Status.FORBIDDEN),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An internal server error has occurred.
|
||||||
|
*/
|
||||||
|
INTERNAL_ERROR(Response.Status.INTERNAL_SERVER_ERROR),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object related to the request does not exist.
|
||||||
|
*/
|
||||||
|
NOT_FOUND(Response.Status.NOT_FOUND),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permission was denied to perform the requested operation.
|
||||||
|
*/
|
||||||
|
PERMISSION_DENIED(Response.Status.FORBIDDEN);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The HTTP status associated with this error type.
|
||||||
|
*/
|
||||||
|
private final Response.Status status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a new error type associated with the given HTTP status.
|
||||||
|
*
|
||||||
|
* @param status
|
||||||
|
* The HTTP status to associate with the error type.
|
||||||
|
*/
|
||||||
|
Type(Response.Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the HTTP status associated with this error type.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The HTTP status associated with this error type.
|
||||||
|
*/
|
||||||
|
public Response.Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new APIError with the specified error message.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* The type of error that occurred.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* The error message.
|
||||||
|
*/
|
||||||
|
public APIError(Type type, String message) {
|
||||||
|
this.type = type;
|
||||||
|
this.message = message;
|
||||||
|
this.expected = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new APIError with the specified error message and parameter
|
||||||
|
* information.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* The type of error that occurred.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* The error message.
|
||||||
|
*
|
||||||
|
* @param expected
|
||||||
|
* All parameters expected in the original request, or now required as
|
||||||
|
* a result of the original request.
|
||||||
|
*/
|
||||||
|
public APIError(Type type, String message, Collection<Parameter> expected) {
|
||||||
|
this.type = type;
|
||||||
|
this.message = message;
|
||||||
|
this.expected = expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type of error that occurred.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The type of error that occurred.
|
||||||
|
*/
|
||||||
|
public Type getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an object which describes the required credentials.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* An object which describes the required credentials.
|
||||||
|
*/
|
||||||
|
public Collection<Parameter> getExpected() {
|
||||||
|
return expected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a human-readable error message describing the error that
|
||||||
|
* occurred.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* A human-readable error message.
|
||||||
*/
|
*/
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new APIError with the specified error message.
|
|
||||||
* @param message The error message.
|
|
||||||
*/
|
|
||||||
public APIError(String message) {
|
|
||||||
this.message = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@ import org.aopalliance.intercept.MethodInterceptor;
|
|||||||
import org.aopalliance.intercept.MethodInvocation;
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
import org.glyptodon.guacamole.GuacamoleClientException;
|
import org.glyptodon.guacamole.GuacamoleClientException;
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
|
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
||||||
import org.glyptodon.guacamole.GuacamoleSecurityException;
|
import org.glyptodon.guacamole.GuacamoleSecurityException;
|
||||||
import org.glyptodon.guacamole.net.auth.credentials.CredentialsInfo;
|
import org.glyptodon.guacamole.net.auth.credentials.CredentialsInfo;
|
||||||
import org.glyptodon.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
|
import org.glyptodon.guacamole.net.auth.credentials.GuacamoleInsufficientCredentialsException;
|
||||||
@@ -61,11 +62,11 @@ public class AuthProviderRESTExceptionWrapper implements MethodInterceptor {
|
|||||||
if (message == null)
|
if (message == null)
|
||||||
message = "Permission denied.";
|
message = "Permission denied.";
|
||||||
|
|
||||||
throw new HTTPException(Response.Status.FORBIDDEN, new APICredentialError(
|
throw new HTTPException(
|
||||||
APICredentialError.Type.INSUFFICIENT,
|
APIError.Type.INSUFFICIENT_CREDENTIALS,
|
||||||
message,
|
message,
|
||||||
e.getCredentialsInfo()
|
e.getCredentialsInfo().getParameters()
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The provided credentials are wrong
|
// The provided credentials are wrong
|
||||||
@@ -76,11 +77,11 @@ public class AuthProviderRESTExceptionWrapper implements MethodInterceptor {
|
|||||||
if (message == null)
|
if (message == null)
|
||||||
message = "Permission denied.";
|
message = "Permission denied.";
|
||||||
|
|
||||||
throw new HTTPException(Response.Status.FORBIDDEN, new APICredentialError(
|
throw new HTTPException(
|
||||||
APICredentialError.Type.INVALID,
|
APIError.Type.INVALID_CREDENTIALS,
|
||||||
message,
|
message,
|
||||||
e.getCredentialsInfo()
|
e.getCredentialsInfo().getParameters()
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic permission denied
|
// Generic permission denied
|
||||||
@@ -91,7 +92,25 @@ public class AuthProviderRESTExceptionWrapper implements MethodInterceptor {
|
|||||||
if (message == null)
|
if (message == null)
|
||||||
message = "Permission denied.";
|
message = "Permission denied.";
|
||||||
|
|
||||||
throw new HTTPException(Response.Status.FORBIDDEN, message);
|
throw new HTTPException(
|
||||||
|
APIError.Type.PERMISSION_DENIED,
|
||||||
|
message
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Arbitrary resource not found
|
||||||
|
catch (GuacamoleResourceNotFoundException e) {
|
||||||
|
|
||||||
|
// Generate default message
|
||||||
|
String message = e.getMessage();
|
||||||
|
if (message == null)
|
||||||
|
message = "Not found.";
|
||||||
|
|
||||||
|
throw new HTTPException(
|
||||||
|
APIError.Type.NOT_FOUND,
|
||||||
|
message
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +122,10 @@ public class AuthProviderRESTExceptionWrapper implements MethodInterceptor {
|
|||||||
if (message == null)
|
if (message == null)
|
||||||
message = "Invalid request.";
|
message = "Invalid request.";
|
||||||
|
|
||||||
throw new HTTPException(Response.Status.BAD_REQUEST, message);
|
throw new HTTPException(
|
||||||
|
APIError.Type.BAD_REQUEST,
|
||||||
|
message
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,7 +138,10 @@ public class AuthProviderRESTExceptionWrapper implements MethodInterceptor {
|
|||||||
message = "Unexpected server error.";
|
message = "Unexpected server error.";
|
||||||
|
|
||||||
logger.debug("Unexpected exception in REST endpoint.", e);
|
logger.debug("Unexpected exception in REST endpoint.", e);
|
||||||
throw new HTTPException(Response.Status.INTERNAL_SERVER_ERROR, message);
|
throw new HTTPException(
|
||||||
|
APIError.Type.INTERNAL_ERROR,
|
||||||
|
message
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,37 +22,64 @@
|
|||||||
|
|
||||||
package org.glyptodon.guacamole.net.basic.rest;
|
package org.glyptodon.guacamole.net.basic.rest;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import javax.ws.rs.WebApplicationException;
|
import javax.ws.rs.WebApplicationException;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.Response.Status;
|
import org.glyptodon.guacamole.form.Parameter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An exception that will result in the given HTTP Status and message or entity
|
* An exception that will result in the given HTTP Status and error being
|
||||||
* being returned from the API layer.
|
* returned from the API layer. All error messages have the same format which
|
||||||
|
* is defined by APIError.
|
||||||
*
|
*
|
||||||
* @author James Muehlner
|
* @author James Muehlner
|
||||||
|
* @author Michael Jumper
|
||||||
*/
|
*/
|
||||||
public class HTTPException extends WebApplicationException {
|
public class HTTPException extends WebApplicationException {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new HTTPException with the given HTTP status and entity.
|
* Construct a new HTTPException with the given error. All information
|
||||||
|
* associated with this new exception will be extracted from the given
|
||||||
|
* APIError.
|
||||||
*
|
*
|
||||||
* @param status The HTTP Status to use for the response.
|
* @param error
|
||||||
* @param entity The entity to use as the body of the response.
|
* The error that occurred.
|
||||||
*/
|
*/
|
||||||
public HTTPException(Status status, Object entity) {
|
public HTTPException(APIError error) {
|
||||||
super(Response.status(status).entity(entity).build());
|
super(Response.status(error.getType().getStatus()).entity(error).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new HTTPException with the given HTTP status and message. The
|
* Creates a new HTTPException with the given type and message. The
|
||||||
* message will be wrapped in an APIError container.
|
* corresponding APIError will be created from the provided information.
|
||||||
*
|
*
|
||||||
* @param status The HTTP Status to use for the response.
|
* @param type
|
||||||
* @param message The message to build the response entity with.
|
* The type of error that occurred.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* A human-readable message describing the error.
|
||||||
*/
|
*/
|
||||||
public HTTPException(Status status, String message) {
|
public HTTPException(APIError.Type type, String message) {
|
||||||
super(Response.status(status).entity(new APIError(message)).build());
|
this(new APIError(type, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new HTTPException with the given type, message, and
|
||||||
|
* parameter information. The corresponding APIError will be created from
|
||||||
|
* the provided information.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* The type of error that occurred.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* A human-readable message describing the error.
|
||||||
|
*
|
||||||
|
* @param expected
|
||||||
|
* All parameters expected in the original request, or now required as
|
||||||
|
* a result of the original request.
|
||||||
|
*/
|
||||||
|
public HTTPException(APIError.Type type, String message, Collection<Parameter> expected) {
|
||||||
|
this(new APIError(type, message, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,6 @@ import javax.ws.rs.Produces;
|
|||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response.Status;
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
import javax.xml.bind.DatatypeConverter;
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
||||||
@@ -44,6 +43,7 @@ import org.glyptodon.guacamole.net.auth.UserContext;
|
|||||||
import org.glyptodon.guacamole.net.auth.credentials.CredentialsInfo;
|
import org.glyptodon.guacamole.net.auth.credentials.CredentialsInfo;
|
||||||
import org.glyptodon.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
import org.glyptodon.guacamole.net.auth.credentials.GuacamoleInvalidCredentialsException;
|
||||||
import org.glyptodon.guacamole.net.basic.GuacamoleSession;
|
import org.glyptodon.guacamole.net.basic.GuacamoleSession;
|
||||||
|
import org.glyptodon.guacamole.net.basic.rest.APIError;
|
||||||
import org.glyptodon.guacamole.net.basic.rest.APIRequest;
|
import org.glyptodon.guacamole.net.basic.rest.APIRequest;
|
||||||
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
|
import org.glyptodon.guacamole.net.basic.rest.AuthProviderRESTExposure;
|
||||||
import org.glyptodon.guacamole.net.basic.rest.HTTPException;
|
import org.glyptodon.guacamole.net.basic.rest.HTTPException;
|
||||||
@@ -290,7 +290,7 @@ public class TokenRESTService {
|
|||||||
|
|
||||||
GuacamoleSession session = tokenSessionMap.remove(authToken);
|
GuacamoleSession session = tokenSessionMap.remove(authToken);
|
||||||
if (session == null)
|
if (session == null)
|
||||||
throw new HTTPException(Status.NOT_FOUND, "No such token.");
|
throw new HTTPException(APIError.Type.NOT_FOUND, "No such token.");
|
||||||
|
|
||||||
session.invalidate();
|
session.invalidate();
|
||||||
|
|
||||||
|
@@ -39,8 +39,6 @@ import javax.ws.rs.Produces;
|
|||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.Response.Status;
|
|
||||||
import org.glyptodon.guacamole.GuacamoleException;
|
import org.glyptodon.guacamole.GuacamoleException;
|
||||||
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
import org.glyptodon.guacamole.GuacamoleResourceNotFoundException;
|
||||||
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
import org.glyptodon.guacamole.net.auth.AuthenticationProvider;
|
||||||
@@ -53,6 +51,7 @@ import org.glyptodon.guacamole.net.auth.permission.ObjectPermissionSet;
|
|||||||
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
import org.glyptodon.guacamole.net.auth.permission.Permission;
|
||||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
import org.glyptodon.guacamole.net.auth.permission.SystemPermission;
|
||||||
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
|
import org.glyptodon.guacamole.net.auth.permission.SystemPermissionSet;
|
||||||
|
import org.glyptodon.guacamole.net.basic.rest.APIError;
|
||||||
import org.glyptodon.guacamole.net.basic.rest.APIPatch;
|
import org.glyptodon.guacamole.net.basic.rest.APIPatch;
|
||||||
import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.add;
|
import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.add;
|
||||||
import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.remove;
|
import static org.glyptodon.guacamole.net.basic.rest.APIPatch.Operation.remove;
|
||||||
@@ -276,12 +275,12 @@ public class UserRESTService {
|
|||||||
|
|
||||||
// Validate data and path are sane
|
// Validate data and path are sane
|
||||||
if (!user.getUsername().equals(username))
|
if (!user.getUsername().equals(username))
|
||||||
throw new HTTPException(Response.Status.BAD_REQUEST,
|
throw new HTTPException(APIError.Type.BAD_REQUEST,
|
||||||
"Username in path does not match username provided JSON data.");
|
"Username in path does not match username provided JSON data.");
|
||||||
|
|
||||||
// A user may not use this endpoint to modify himself
|
// A user may not use this endpoint to modify himself
|
||||||
if (userContext.self().getIdentifier().equals(user.getUsername())) {
|
if (userContext.self().getIdentifier().equals(user.getUsername())) {
|
||||||
throw new HTTPException(Response.Status.FORBIDDEN,
|
throw new HTTPException(APIError.Type.PERMISSION_DENIED,
|
||||||
"Permission denied.");
|
"Permission denied.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,7 +335,7 @@ public class UserRESTService {
|
|||||||
|
|
||||||
// Verify that the old password was correct
|
// Verify that the old password was correct
|
||||||
if (authProvider.getUserContext(credentials) == null) {
|
if (authProvider.getUserContext(credentials) == null) {
|
||||||
throw new HTTPException(Response.Status.FORBIDDEN,
|
throw new HTTPException(APIError.Type.PERMISSION_DENIED,
|
||||||
"Permission denied.");
|
"Permission denied.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,7 +466,7 @@ public class UserRESTService {
|
|||||||
|
|
||||||
// Unsupported patch operation
|
// Unsupported patch operation
|
||||||
default:
|
default:
|
||||||
throw new HTTPException(Status.BAD_REQUEST,
|
throw new HTTPException(APIError.Type.BAD_REQUEST,
|
||||||
"Unsupported patch operation: \"" + operation + "\"");
|
"Unsupported patch operation: \"" + operation + "\"");
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -586,7 +585,7 @@ public class UserRESTService {
|
|||||||
|
|
||||||
// Otherwise, the path is not supported
|
// Otherwise, the path is not supported
|
||||||
else
|
else
|
||||||
throw new HTTPException(Status.BAD_REQUEST, "Unsupported patch path: \"" + path + "\"");
|
throw new HTTPException(APIError.Type.BAD_REQUEST, "Unsupported patch path: \"" + path + "\"");
|
||||||
|
|
||||||
} // end for each patch operation
|
} // end for each patch operation
|
||||||
|
|
||||||
|
122
guacamole/src/main/webapp/app/rest/types/Error.js
Normal file
122
guacamole/src/main/webapp/app/rest/types/Error.js
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Glyptodon LLC
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service which defines the Error class.
|
||||||
|
*/
|
||||||
|
angular.module('rest').factory('Error', [function defineError() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object returned by REST API calls when an error occurs.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {Error|Object} [template={}]
|
||||||
|
* The object whose properties should be copied within the new
|
||||||
|
* Error.
|
||||||
|
*/
|
||||||
|
var Error = function Error(template) {
|
||||||
|
|
||||||
|
// Use empty object by default
|
||||||
|
template = template || {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A human-readable message describing the error that occurred.
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
this.message = template.message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type string defining which values this parameter may contain,
|
||||||
|
* as well as what properties are applicable. Valid types are listed
|
||||||
|
* within Error.Type.
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
* @default Error.Type.INTERNAL_ERROR
|
||||||
|
*/
|
||||||
|
this.type = template.type || Error.Type.INTERNAL_ERROR;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any parameters which were expected in the original request, or are
|
||||||
|
* now expected as a result of the original request, if any. If no
|
||||||
|
* such information is available, this will be null.
|
||||||
|
*
|
||||||
|
* @type Field[]
|
||||||
|
*/
|
||||||
|
this.expected = template.expected;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All valid field types.
|
||||||
|
*/
|
||||||
|
Error.Type = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The requested operation could not be performed because the request
|
||||||
|
* itself was malformed.
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
BAD_REQUEST : 'BAD_REQUEST',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The credentials provided were invalid.
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
INVALID_CREDENTIALS : 'INVALID_CREDENTIALS',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The credentials provided were not necessarily invalid, but were not
|
||||||
|
* sufficient to determine validity.
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
INSUFFICIENT_CREDENTIALS : 'INSUFFICIENT_CREDENTIALS',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An internal server error has occurred.
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
INTERNAL_ERROR : 'INTERNAL_ERROR',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object related to the request does not exist.
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
NOT_FOUND : 'NOT_FOUND',
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permission was denied to perform the requested operation.
|
||||||
|
*
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
PERMISSION_DENIED : 'PERMISSION_DENIED'
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return Error;
|
||||||
|
|
||||||
|
}]);
|
Reference in New Issue
Block a user