Skip to content

Commit

Permalink
Change name of method to better reflect usage
Browse files Browse the repository at this point in the history
Also cleaned up SecurityContext interface/classes
  • Loading branch information
OliviaYtterbrink committed Feb 5, 2018
1 parent 5b27ae1 commit 67ff0ed
Show file tree
Hide file tree
Showing 24 changed files with 179 additions and 312 deletions.
Expand Up @@ -22,8 +22,9 @@
import org.neo4j.internal.kernel.api.Token;

/**
* The LoginContext hold the executing authenticated user (subject). By calling {@link #freeze(Token)} the user is also authorized, and a
* full SecurityContext is returned, which can be used to assert user permissions during query execution.
* The LoginContext hold the executing authenticated user (subject).
* By calling {@link #authorize(Token)} the user is also authorized, and a full SecurityContext is returned,
* which can be used to assert user permissions during query execution.
*/
public interface LoginContext
{
Expand All @@ -38,7 +39,7 @@ public interface LoginContext
* @param token token lookup, used to compile property level security verification
* @return the security context
*/
SecurityContext freeze( Token token );
SecurityContext authorize( Token token );

LoginContext AUTH_DISABLED = new LoginContext()
{
Expand All @@ -49,7 +50,7 @@ public AuthSubject subject()
}

@Override
public SecurityContext freeze( Token token )
public SecurityContext authorize( Token token )
{
return SecurityContext.AUTH_DISABLED;
}
Expand Down
Expand Up @@ -28,135 +28,96 @@
*
* Must extend LoginContext to handle procedures creating internal transactions, periodic commit and the parallel cypher prototype.
*/
public interface SecurityContext extends LoginContext
public class SecurityContext implements LoginContext
{
protected final AuthSubject subject;
protected final AccessMode mode;

public SecurityContext( AuthSubject subject, AccessMode mode )
{
this.subject = subject;
this.mode = mode;
}

/**
* Get the authorization data of the user. This is immutable.
*/
AccessMode mode();
public AccessMode mode()
{
return mode;
}

/**
* Check whether the user is an admin.
*/
boolean isAdmin();
public boolean isAdmin()
{
return true;
}

@Override
public AuthSubject subject()
{
return subject;
}

@Override
public SecurityContext authorize( Token token )
{
return this;
}

/**
* Create a copy of this SecurityContext with the provided mode.
*/
SecurityContext withMode( AccessMode mode );
public SecurityContext withMode( AccessMode mode )
{
return new SecurityContext( subject, mode );
}

default void assertCredentialsNotExpired()
public void assertCredentialsNotExpired()
{
if ( subject().getAuthenticationResult().equals( AuthenticationResult.PASSWORD_CHANGE_REQUIRED ) )
{
throw mode().onViolation( PERMISSION_DENIED );
}
}

default String description()
public String description()
{
return String.format( "user '%s' with %s", subject().username(), mode().name() );
}

default String defaultString( String name )
protected String defaultString( String name )
{
return String.format( "%s{ username=%s, accessMode=%s }", name, subject().username(), mode() );
}

/** Allows all operations. */
SecurityContext AUTH_DISABLED = new AuthDisabled( AccessMode.Static.FULL );
public static final SecurityContext AUTH_DISABLED = authDisabled( AccessMode.Static.FULL );

final class AuthDisabled implements SecurityContext
private static SecurityContext authDisabled( AccessMode mode )
{
private final AccessMode mode;

private AuthDisabled( AccessMode mode )
{
this.mode = mode;
}

@Override
public AccessMode mode()
{
return mode;
}

@Override
public AuthSubject subject()
return new SecurityContext( AuthSubject.AUTH_DISABLED, mode )
{
return AuthSubject.AUTH_DISABLED;
}

@Override
public boolean isAdmin()
{
return true;
}

@Override
public String toString()
{
return defaultString( "auth-disabled" );
}

@Override
public String description()
{
return "AUTH_DISABLED with " + mode.name();
}

@Override
public SecurityContext freeze( Token token )
{
return this;
}

@Override
public SecurityContext withMode( AccessMode mode )
{
return new AuthDisabled( mode );
}
}

final class Frozen implements SecurityContext
{
private final AuthSubject subject;
private final AccessMode mode;

public Frozen( AuthSubject subject, AccessMode mode )
{
this.subject = subject;
this.mode = mode;
}

@Override
public AccessMode mode()
{
return mode;
}

@Override
public AuthSubject subject()
{
return subject;
}

@Override
public boolean isAdmin()
{
return true;
}

@Override
public SecurityContext freeze( Token token )
{
return this;
}

@Override
public SecurityContext withMode( AccessMode mode )
{
return new Frozen( subject, mode );
}
@Override
public SecurityContext withMode( AccessMode mode )
{
return authDisabled( mode );
}

@Override
public String description()
{
return "AUTH_DISABLED with " + mode().name();
}

@Override
public String toString()
{
return defaultString( "auth-disabled" );
}
};
}
}
Expand Up @@ -67,8 +67,8 @@ public AuthSubject subject()
}

@Override
public SecurityContext freeze( Token token )
public SecurityContext authorize( Token token )
{
return new SecurityContext.Frozen( subject(), accessMode );
return new SecurityContext( subject(), accessMode );
}
}
Expand Up @@ -175,7 +175,7 @@ public Supplier<ExplicitIndexTransactionState> explicitIndexTxStateSupplier()
public KernelTransaction newInstance( KernelTransaction.Type type, LoginContext loginContext, long timeout )
{
assertCurrentThreadIsNotBlockingNewTransactions();
SecurityContext securityContext = loginContext.freeze( token );
SecurityContext securityContext = loginContext.authorize( token );
try
{
while ( !newTransactionsLock.readLock().tryLock( 1, TimeUnit.SECONDS ) )
Expand Down
Expand Up @@ -107,7 +107,7 @@ storageEngine, new CanWrite(), new KernelToken( storeReadLayer ), new DefaultCur

StatementLocks statementLocks = new SimpleStatementLocks( new NoOpClient() );

transaction.initialize( 0, 0, statementLocks, KernelTransaction.Type.implicit, loginContext.freeze( mock( Token.class ) ), 0L, 1L );
transaction.initialize( 0, 0, statementLocks, KernelTransaction.Type.implicit, loginContext.authorize( mock( Token.class ) ), 0L, 1L );

return new Instances( transaction, storageEngine, storeReadLayer, storageStatement );
}
Expand Down
Expand Up @@ -450,7 +450,7 @@ public void shouldIncrementReuseCounterOnReuse() throws Exception
transaction.close();
SimpleStatementLocks statementLocks = new SimpleStatementLocks( new NoOpClient() );
transaction.initialize( 1, BASE_TX_COMMIT_TIMESTAMP, statementLocks, KernelTransaction.Type.implicit,
loginContext().freeze( mock( Token.class ) ), 0L, 1L );
loginContext().authorize( mock( Token.class ) ), 0L, 1L );

// THEN
assertEquals( reuseCount + 1, transaction.getReuseCount() );
Expand Down Expand Up @@ -671,7 +671,7 @@ public void markForTerminationWithCorrectReuseCount() throws Exception

Locks.Client locksClient = mock( Locks.Client.class );
SimpleStatementLocks statementLocks = new SimpleStatementLocks( locksClient );
tx.initialize( 42, 42, statementLocks, KernelTransaction.Type.implicit, loginContext().freeze( mock( Token.class ) ), 0L, 0L );
tx.initialize( 42, 42, statementLocks, KernelTransaction.Type.implicit, loginContext().authorize( mock( Token.class ) ), 0L, 0L );

assertTrue( tx.markForTermination( reuseCount, terminationReason ) );

Expand All @@ -691,7 +691,7 @@ public void markForTerminationWithIncorrectReuseCount() throws Exception

Locks.Client locksClient = mock( Locks.Client.class );
SimpleStatementLocks statementLocks = new SimpleStatementLocks( locksClient );
tx.initialize( 42, 42, statementLocks, KernelTransaction.Type.implicit, loginContext().freeze( mock( Token.class ) ), 0L, 0L );
tx.initialize( 42, 42, statementLocks, KernelTransaction.Type.implicit, loginContext().authorize( mock( Token.class ) ), 0L, 0L );

assertFalse( tx.markForTermination( nextReuseCount, terminationReason ) );

Expand Down Expand Up @@ -758,7 +758,7 @@ private void initializeAndClose( KernelTransactionImplementation tx, int times )
for ( int i = 0; i < times; i++ )
{
SimpleStatementLocks statementLocks = new SimpleStatementLocks( new NoOpClient() );
tx.initialize( i + 10, i + 10, statementLocks, KernelTransaction.Type.implicit, loginContext().freeze( mock( Token.class ) ), 0L, 0L );
tx.initialize( i + 10, i + 10, statementLocks, KernelTransaction.Type.implicit, loginContext().authorize( mock( Token.class ) ), 0L, 0L );
tx.close();
}
}
Expand Down
Expand Up @@ -144,7 +144,7 @@ public KernelTransactionImplementation newTransaction( long lastTransactionIdWhe
{
KernelTransactionImplementation tx = newNotInitializedTransaction();
StatementLocks statementLocks = new SimpleStatementLocks( locks );
SecurityContext securityContext = loginContext.freeze( mock( Token.class ) );
SecurityContext securityContext = loginContext.authorize( mock( Token.class ) );
tx.initialize( lastTransactionIdWhenStarted, BASE_TX_COMMIT_TIMESTAMP,statementLocks, Type.implicit,
securityContext, transactionTimeout, 1L );
return tx;
Expand Down
Expand Up @@ -409,7 +409,7 @@ public void shouldNotLeakTransactionOnSecurityContextFreezeFailure() throws Thro
{
KernelTransactions kernelTransactions = newKernelTransactions();
LoginContext loginContext = mock( LoginContext.class );
when( loginContext.freeze( any() ) ).thenThrow( new AuthorizationExpiredException( "Freeze failed." ) );
when( loginContext.authorize( any() ) ).thenThrow( new AuthorizationExpiredException( "Freeze failed." ) );

assertException(() -> kernelTransactions.newInstance(KernelTransaction.Type.explicit, loginContext, 0L),
AuthorizationExpiredException.class, "Freeze failed.");
Expand Down
Expand Up @@ -268,7 +268,7 @@ public void failWhenCallingNonExistingProcedures() throws Throwable
{
// When
dbmsOperations().procedureCallDbms( procedureName( "dbms", "iDoNotExist" ), new Object[0],
AnonymousContext.none().freeze( mock( Token.class ) ) );
AnonymousContext.none().authorize( mock( Token.class ) ) );
fail( "This should never get here" );
}
catch ( Exception e )
Expand Down
Expand Up @@ -346,7 +346,7 @@ public void accessTransactionIdAndCommitTime()
@Test
public void shouldGetEmptyUsernameForAnonymousContext()
{
when( transaction.securityContext() ).thenReturn( AnonymousContext.read().freeze( mock( Token.class ) ) );
when( transaction.securityContext() ).thenReturn( AnonymousContext.read().authorize( mock( Token.class ) ) );

TxStateTransactionDataSnapshot transactionDataSnapshot = snapshot();
assertEquals( "", transactionDataSnapshot.username() );
Expand All @@ -358,7 +358,7 @@ public void shouldAccessUsernameFromAuthSubject()
AuthSubject authSubject = mock( AuthSubject.class );
when( authSubject.username() ).thenReturn( "Christof" );
when( transaction.securityContext() )
.thenReturn( new SecurityContext.Frozen( authSubject, AccessMode.Static.FULL ) );
.thenReturn( new SecurityContext( authSubject, AccessMode.Static.FULL ) );

TxStateTransactionDataSnapshot transactionDataSnapshot = snapshot();
assertEquals( "Christof", transactionDataSnapshot.username() );
Expand Down
Expand Up @@ -197,9 +197,9 @@ public AuthSubject subject()
}

@Override
public SecurityContext freeze( Token token )
public SecurityContext authorize( Token token )
{
return new SecurityContext.Frozen( subject, AccessMode.Static.WRITE );
return new SecurityContext( subject, AccessMode.Static.WRITE );
}
};
Map<String,Object> metadata = genericMap( "username", "joe" );
Expand Down
Expand Up @@ -107,8 +107,8 @@ public AuthSubject subject()
}

@Override
public SecurityContext freeze( Token token )
public SecurityContext authorize( Token token )
{
return new SecurityContext.Frozen( authSubject, accessMode );
return new SecurityContext( authSubject, accessMode );
}
}
Expand Up @@ -51,7 +51,7 @@ public void shouldFailWhenDeprecatedChangePasswordWithStaticAccessModeInDbmsMode

// When
dbmsOperations().procedureCallDbms( procedureName( "dbms", "changePassword" ), inputArray,
AnonymousContext.none().freeze( mock( Token.class ) ) );
AnonymousContext.none().authorize( mock( Token.class ) ) );
}

@Test
Expand All @@ -67,7 +67,7 @@ public void shouldFailWhenChangePasswordWithStaticAccessModeInDbmsMode() throws

// When
dbmsOperations().procedureCallDbms( procedureName( "dbms", "security", "changePassword" ), inputArray,
AnonymousContext.none().freeze( mock( Token.class ) ) );
AnonymousContext.none().authorize( mock( Token.class ) ) );
}

@Override
Expand Down
Expand Up @@ -54,7 +54,7 @@ public void setup() throws Throwable
manager.init();
manager.start();
manager.newUser( "johan", "bar", false );
context = manager.login( authToken( "johan", "bar" ) ).freeze( mock( Token.class ) );
context = manager.login( authToken( "johan", "bar" ) ).authorize( mock( Token.class ) );
}

@After
Expand Down
Expand Up @@ -153,7 +153,7 @@ private void setUpMocks()
QueryRegistryOperations registryOperations = mock( QueryRegistryOperations.class );
when( statement.queryRegistration() ).thenReturn( registryOperations );
when( statementBridge.get() ).thenReturn( statement );
when( kernelTransaction.securityContext() ).thenReturn( loginContext.freeze( mock( Token.class ) ) );
when( kernelTransaction.securityContext() ).thenReturn( loginContext.authorize( mock( Token.class ) ) );
when( kernelTransaction.transactionType() ).thenReturn( type );
when( database.getGraph() ).thenReturn( databaseFacade );
when( databaseFacade.getDependencyResolver() ).thenReturn( resolver );
Expand Down

0 comments on commit 67ff0ed

Please sign in to comment.