Skip to content

Commit

Permalink
Use InvalidArgumentsException in BuiltInProcedures
Browse files Browse the repository at this point in the history
o InvalidArgumentsException is now a generic exception and no longer tied to security
o Wrote some utility code for tunneling checked exceptions out of stream pipelines
  • Loading branch information
boggle authored and systay committed Sep 14, 2016
1 parent 6a3b85c commit edff48c
Show file tree
Hide file tree
Showing 36 changed files with 218 additions and 100 deletions.
Expand Up @@ -27,7 +27,7 @@
import org.neo4j.kernel.api.security.AuthManager;
import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.AuthToken;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.kernel.api.security.exception.InvalidAuthTokenException;
import org.neo4j.logging.Log;
import org.neo4j.logging.LogProvider;
Expand Down
Expand Up @@ -320,7 +320,7 @@ public void shouldFailWhenReusingTheSamePassword() throws Throwable
PullAllMessage.pullAll() ) );

// Then
assertThat( client, eventuallyReceives( msgFailure(Status.Security.InvalidArguments,
assertThat( client, eventuallyReceives( msgFailure(Status.General.InvalidArguments,
"Old password and new password cannot be the same.") ) );
}

Expand All @@ -344,7 +344,7 @@ public void shouldFailWhenSubmittingEmptyPassword() throws Throwable
PullAllMessage.pullAll() ) );

// Then
assertThat( client, eventuallyReceives( msgFailure(Status.Security.InvalidArguments,
assertThat( client, eventuallyReceives( msgFailure(Status.General.InvalidArguments,
"A password cannot be empty.") ) );
}

Expand Down
Expand Up @@ -19,6 +19,9 @@
*/
package org.neo4j.function;

import java.util.Optional;
import java.util.function.Function;

/**
* Represents a function that accepts one argument and produces a result, or throws an exception.
*
Expand All @@ -36,4 +39,53 @@ public interface ThrowingFunction<T, R, E extends Exception>
* @throws E an exception if the function fails
*/
R apply( T t ) throws E;

/**
* Construct a regular function that calls a throwing function and catches all checked exceptions
* declared and thrown by the throwing function and rethrows them as {@link UncaughtCheckedException}
* for handling further up the stack.
*
* @see UncaughtCheckedException
*
* @param throwing the throwing function to wtap
* @param <T> type of arguments
* @param <R> type of results
* @param <E> type of checked exceptions thrown by the throwing function
* @return a new, non-throwing function
* @throws IllegalStateException if an unexpected exception is caught (ie. neither of type E or a runtime exception)
*/
static <T, R, E extends Exception> Function<T, R> catchThrown( Class<E> clazz, ThrowingFunction<T, R, E> throwing )
{
return input ->
{
try
{
return throwing.apply( input );
}
catch ( Exception e )
{
if ( clazz.isInstance( e ) )
{
throw new UncaughtCheckedException( throwing, clazz.cast( e ) );
}
else if ( e instanceof RuntimeException )
{
throw (RuntimeException) e;
}
else
{
throw new IllegalStateException( "Unexpected exception", e );
}
}
};
}

@SuppressWarnings( "OptionalUsedAsFieldOrParameterType" )
static <E extends Exception> void throwIfPresent( Optional<E> exception ) throws E
{
if ( exception.isPresent() )
{
throw exception.get();
}
}
}
Expand Up @@ -24,43 +24,25 @@
*/
public final class ThrowingFunctions
{
private static final ThrowingUnaryOperator IDENTITY = new ThrowingUnaryOperator()
{
@Override
public Object apply( Object value )
{
return value;
}
};
private static final ThrowingUnaryOperator IDENTITY = value -> value;

@SuppressWarnings( "unchecked" )
public static <T, E extends Exception> ThrowingUnaryOperator<T,E> identity()
{
return IDENTITY;
}

public static <T, E extends Exception> ThrowingFunction<T,Void,E> fromConsumer( final ThrowingConsumer<T,E> consumer )
public static <T, E extends Exception> ThrowingFunction<T,Void,E> fromConsumer( ThrowingConsumer<T,E> consumer )
{
return new ThrowingFunction<T,Void,E>()
return t ->
{
@Override
public Void apply( T t ) throws E
{
consumer.accept( t );
return null;
}
consumer.accept( t );
return null;
};
}

public static <T, E extends Exception> ThrowingFunction<Void,T,E> fromSupplier( final ThrowingSupplier<T,E> supplier )
public static <T, E extends Exception> ThrowingFunction<Void,T,E> fromSupplier( ThrowingSupplier<T,E> supplier )
{
return new ThrowingFunction<Void,T,E>()
{
@Override
public T apply( Void t ) throws E
{
return supplier.get();
}
};
return t -> supplier.get();
}
}
@@ -0,0 +1,49 @@
package org.neo4j.function;

import java.util.Optional;

/**
* Wrapper around checked exceptions for rethrowing them as runtime exceotions when the signature of the containing method
* cannot be changed to declare them.
*
* Thrown by {@link ThrowingFunction#catchThrown(Class, ThrowingFunction)}
*/
public class UncaughtCheckedException extends RuntimeException
{
private final Object source;

public UncaughtCheckedException( Object source, Throwable cause )
{
super( "Uncaught checked exception", cause );
if ( cause == null )
{
throw new IllegalArgumentException( "Expected non-null cause" );
}
this.source = source;
}

/**
* Check the that the cause has the given type and if succesful, return it.
*
* @param clazz class object for the desired type of the cause
* @param <E> the desired type of the cause
* @return the underlying cause of this exception but only if it is of desired type E, nothing otherwise
*/
public <E extends Exception> Optional<E> getCauseIfOfType( Class<E> clazz )
{
Throwable cause = getCause();
if ( clazz.isInstance( cause ) )
{
return Optional.of( clazz.cast( cause ) );
}
else
{
return Optional.empty();
}
}

public Object source()
{
return source;
}
}
Expand Up @@ -404,7 +404,6 @@ public Code code()
enum Security implements Status // TODO: rework by the Security Team before these are updated
{
// client
InvalidArguments( ClientError, "The request contained fields that were empty or are not allowed." ),
CredentialsExpired( ClientError, "The credentials have expired and need to be updated." ),
Unauthorized( ClientError, "The client is unauthorized due to authentication failure." ),
AuthenticationRateLimit( ClientError, "The client has provided incorrect authentication details too many times in a row." ),
Expand All @@ -429,6 +428,7 @@ public Code code()
enum General implements Status
{
// client errors
InvalidArguments( ClientError, "The request contained fields that were empty or are not allowed." ),
ForbiddenOnReadOnlyDatabase( ClientError,
"This is a read only database, writing or modifying the database is not allowed." ),

Expand Down
Expand Up @@ -17,18 +17,21 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.api.security.exception;

import org.neo4j.kernel.api.exceptions.Status;
package org.neo4j.kernel.api.exceptions;

public class InvalidArgumentsException extends Exception implements Status.HasStatus
{
private final Status status;

public InvalidArgumentsException( String message )
{
super(message);
this.status = Status.Security.InvalidArguments;
this( message, null );
}

public InvalidArgumentsException( String message, Throwable cause )
{
super( message, cause );
this.status = Status.General.InvalidArguments;
}

@Override
Expand Down
Expand Up @@ -22,7 +22,7 @@
import java.io.IOException;

import org.neo4j.graphdb.security.AuthorizationViolationException;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;

public interface AuthSubject extends AccessMode
{
Expand Down
Expand Up @@ -29,7 +29,7 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.kernel.lifecycle.LifecycleAdapter;
import org.neo4j.server.security.auth.exception.ConcurrentModificationException;

Expand Down
Expand Up @@ -26,7 +26,7 @@
import java.util.stream.Stream;

import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.procedure.Context;
import org.neo4j.procedure.Description;
import org.neo4j.procedure.Name;
Expand Down
Expand Up @@ -29,7 +29,7 @@
import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.AuthToken;
import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.kernel.api.security.exception.InvalidAuthTokenException;
import org.neo4j.server.security.auth.exception.ConcurrentModificationException;

Expand Down
Expand Up @@ -25,7 +25,7 @@
import org.neo4j.kernel.api.security.AccessMode;
import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;

import static org.neo4j.kernel.api.security.AuthenticationResult.FAILURE;
import static org.neo4j.kernel.api.security.AuthenticationResult.PASSWORD_CHANGE_REQUIRED;
Expand Down
Expand Up @@ -19,7 +19,7 @@
*/
package org.neo4j.server.security.auth;

import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;

public class BasicPasswordPolicy implements PasswordPolicy
{
Expand Down
Expand Up @@ -19,7 +19,7 @@
*/
package org.neo4j.server.security.auth;

import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;

public interface PasswordPolicy
{
Expand Down
Expand Up @@ -22,7 +22,7 @@
import java.io.IOException;
import java.util.Set;

import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;

public interface UserManager
{
Expand Down
Expand Up @@ -22,7 +22,7 @@
import java.io.IOException;
import java.util.Set;

import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.kernel.lifecycle.Lifecycle;
import org.neo4j.server.security.auth.exception.ConcurrentModificationException;

Expand Down
Expand Up @@ -30,7 +30,7 @@
import org.neo4j.commandline.admin.OutsideWorld;
import org.neo4j.io.fs.DelegateFileSystemAbstraction;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.logging.NullLogProvider;
import org.neo4j.server.security.auth.Credential;
import org.neo4j.server.security.auth.FileUserRepository;
Expand Down
Expand Up @@ -43,7 +43,7 @@
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction;
import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.kernel.api.security.exception.InvalidAuthTokenException;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.test.TestGraphDatabaseBuilder;
Expand Down
Expand Up @@ -29,7 +29,7 @@

import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.kernel.api.security.exception.InvalidAuthTokenException;

import static org.hamcrest.Matchers.containsString;
Expand Down
Expand Up @@ -32,7 +32,7 @@

import org.neo4j.kernel.api.security.AuthManager;
import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.server.rest.repr.AuthorizationRepresentation;
import org.neo4j.server.rest.repr.BadInputException;
import org.neo4j.server.rest.repr.ExceptionRepresentation;
Expand Down
Expand Up @@ -33,7 +33,7 @@
import javax.ws.rs.core.Response;

import org.neo4j.kernel.api.security.AuthManager;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;
import org.neo4j.server.rest.repr.OutputFormat;
import org.neo4j.server.rest.repr.formats.JsonFormat;
import org.neo4j.server.security.auth.AuthenticationStrategy;
Expand Down
Expand Up @@ -24,7 +24,7 @@
import org.neo4j.graphdb.security.AuthorizationViolationException;
import org.neo4j.kernel.api.security.AuthSubject;
import org.neo4j.kernel.api.security.AuthenticationResult;
import org.neo4j.kernel.api.security.exception.InvalidArgumentsException;
import org.neo4j.kernel.api.exceptions.InvalidArgumentsException;

/**
* A logged in user.
Expand Down

0 comments on commit edff48c

Please sign in to comment.