Skip to content
Permalink
Browse files
Merge pull request #22 from myrle-krantz/develop
provisioning synchronisation
  • Loading branch information
myrle-krantz committed Jul 14, 2017
2 parents 3d8b7be + a92cb37 commit b28f5f6228e19a46a3d3eb55ea3246216aa251be
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 111 deletions.
@@ -96,7 +96,7 @@ public class Provisioner {
this.saltGenerator = saltGenerator;
}

public ApplicationSignatureSet provisionTenant(final String initialPasswordHash) {
public synchronized ApplicationSignatureSet provisionTenant(final String initialPasswordHash) {
logger.info("Provisioning cassandra tables for tenant {}...", TenantContextHolder.checkedGetIdentifier());
final RsaKeyPairFactory.KeyPairHolder keys = RsaKeyPairFactory.createKeyPair();

@@ -57,14 +57,13 @@ public ApplicationCallEndpointSets(
}

public void buildTable() {
final Create create = SchemaBuilder.createTable(TABLE_NAME)
.ifNotExists()
.addPartitionKey(APPLICATION_IDENTIFIER_COLUMN, DataType.text())
.addClusteringColumn(CALLENDPOINTSET_IDENTIFIER_COLUMN, DataType.text())
.addColumn(CALLENDPOINT_GROUP_IDENTIFIERS_COLUMN, DataType.list(DataType.text()));

final Create createTableStatement =
SchemaBuilder.createTable(TABLE_NAME)
.addPartitionKey(APPLICATION_IDENTIFIER_COLUMN, DataType.text())
.addClusteringColumn(CALLENDPOINTSET_IDENTIFIER_COLUMN, DataType.text())
.addColumn(CALLENDPOINT_GROUP_IDENTIFIERS_COLUMN, DataType.list(DataType.text()));

cassandraSessionProvider.getTenantSession().execute(createTableStatement);
cassandraSessionProvider.getTenantSession().execute(create);
}

public void add(final ApplicationCallEndpointSetEntity entity) {
@@ -44,15 +44,14 @@ public ApplicationPermissionUsers(final CassandraSessionProvider cassandraSessio
}

public void buildTable() {
final Create create = SchemaBuilder.createTable(TABLE_NAME)
.ifNotExists()
.addPartitionKey(APPLICATION_IDENTIFIER_COLUMN, DataType.text())
.addClusteringColumn(PERMITTABLE_GROUP_IDENTIFIER_COLUMN, DataType.text())
.addClusteringColumn(USER_IDENTIFIER_COLUMN, DataType.text())
.addColumn(ENABLED_COLUMN, DataType.cboolean());

final Create createTableStatement =
SchemaBuilder.createTable(TABLE_NAME)
.addPartitionKey(APPLICATION_IDENTIFIER_COLUMN, DataType.text())
.addClusteringColumn(PERMITTABLE_GROUP_IDENTIFIER_COLUMN, DataType.text())
.addClusteringColumn(USER_IDENTIFIER_COLUMN, DataType.text())
.addColumn(ENABLED_COLUMN, DataType.cboolean());

cassandraSessionProvider.getTenantSession().execute(createTableStatement);
cassandraSessionProvider.getTenantSession().execute(create);
}

public boolean enabled(final String applicationIdentifier,
@@ -56,14 +56,13 @@ public ApplicationPermissions(final CassandraSessionProvider cassandraSessionPro
}

public void buildTable() {
final Create create = SchemaBuilder.createTable(TABLE_NAME)
.ifNotExists()
.addPartitionKey(APPLICATION_IDENTIFIER_COLUMN, DataType.text())
.addClusteringColumn(PERMITTABLE_GROUP_IDENTIFIER_COLUMN, DataType.text())
.addUDTColumn(PERMISSION_COLUMN, SchemaBuilder.frozen(Permissions.TYPE_NAME));

final Create createTableStatement =
SchemaBuilder.createTable(TABLE_NAME)
.addPartitionKey(APPLICATION_IDENTIFIER_COLUMN, DataType.text())
.addClusteringColumn(PERMITTABLE_GROUP_IDENTIFIER_COLUMN, DataType.text())
.addUDTColumn(PERMISSION_COLUMN, SchemaBuilder.frozen(Permissions.TYPE_NAME));

cassandraSessionProvider.getTenantSession().execute(createTableStatement);
cassandraSessionProvider.getTenantSession().execute(create);

}

@@ -59,15 +59,15 @@ public ApplicationSignatures(final CassandraSessionProvider cassandraSessionProv
this.tenantAwareCassandraMapperProvider = tenantAwareCassandraMapperProvider;
}

public void buildTable()
{
final Create createTable = SchemaBuilder.createTable(TABLE_NAME)
.addPartitionKey(APPLICATION_IDENTIFIER_COLUMN, DataType.text())
.addClusteringColumn(KEY_TIMESTAMP_COLUMN, DataType.text())
.addColumn(PUBLIC_KEY_MOD_COLUMN, DataType.varint())
.addColumn(PUBLIC_KEY_EXP_COLUMN, DataType.varint());

cassandraSessionProvider.getTenantSession().execute(createTable);
public void buildTable() {
final Create create = SchemaBuilder.createTable(TABLE_NAME)
.ifNotExists()
.addPartitionKey(APPLICATION_IDENTIFIER_COLUMN, DataType.text())
.addClusteringColumn(KEY_TIMESTAMP_COLUMN, DataType.text())
.addColumn(PUBLIC_KEY_MOD_COLUMN, DataType.varint())
.addColumn(PUBLIC_KEY_EXP_COLUMN, DataType.varint());

cassandraSessionProvider.getTenantSession().execute(create);
}

public void add(final ApplicationSignatureEntity entity) {
@@ -19,6 +19,8 @@
import com.datastax.driver.core.Session;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.schemabuilder.Create;
import com.datastax.driver.core.schemabuilder.CreateType;
import com.datastax.driver.core.schemabuilder.SchemaBuilder;
import com.datastax.driver.mapping.Mapper;
import io.mifos.core.cassandra.core.CassandraSessionProvider;
@@ -28,9 +30,9 @@
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
* @author Myrle Krantz
@@ -61,21 +63,20 @@ public class PermittableGroups {
}

public void buildTable() {
final String type_statement =
SchemaBuilder.createType(TYPE_NAME)
.addColumn(PATH_FIELD, DataType.text())
.addColumn(METHOD_FIELD, DataType.text())
.addColumn(SOURCE_GROUP_ID_FIELD, DataType.text())
.buildInternal();
cassandraSessionProvider.getTenantSession().execute(type_statement);

final String table_statement =
SchemaBuilder.createTable(TABLE_NAME)
.addPartitionKey(IDENTIFIER_COLUMN, DataType.text())
.addUDTListColumn(PERMITTABLES_COLUMN, SchemaBuilder.frozen(TYPE_NAME))
.buildInternal();

cassandraSessionProvider.getTenantSession().execute(table_statement);
final CreateType createType = SchemaBuilder.createType(TYPE_NAME)
.ifNotExists()
.addColumn(PATH_FIELD, DataType.text())
.addColumn(METHOD_FIELD, DataType.text())
.addColumn(SOURCE_GROUP_ID_FIELD, DataType.text());

cassandraSessionProvider.getTenantSession().execute(createType);

final Create create = SchemaBuilder.createTable(TABLE_NAME)
.ifNotExists()
.addPartitionKey(IDENTIFIER_COLUMN, DataType.text())
.addUDTListColumn(PERMITTABLES_COLUMN, SchemaBuilder.frozen(TYPE_NAME));

cassandraSessionProvider.getTenantSession().execute(create);

}

@@ -101,7 +102,6 @@ public List<PermittableGroupEntity> getAll() {

final Statement statement = QueryBuilder.select().all().from(TABLE_NAME);

return entityMapper.map(tenantSession.execute(statement)).all()
.stream().collect(Collectors.toList());
return new ArrayList<>(entityMapper.map(tenantSession.execute(statement)).all());
}
}
@@ -19,6 +19,7 @@
import com.datastax.driver.core.Session;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.schemabuilder.Create;
import com.datastax.driver.core.schemabuilder.SchemaBuilder;
import com.datastax.driver.mapping.Mapper;
import io.mifos.core.cassandra.core.CassandraSessionProvider;
@@ -28,9 +29,9 @@
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
* @author Myrle Krantz
@@ -56,14 +57,12 @@ public class Roles {
}

public void buildTable() {
final Create create = SchemaBuilder.createTable(TABLE_NAME)
.ifNotExists()
.addPartitionKey(IDENTIFIER_COLUMN, DataType.text())
.addUDTListColumn(PERMISSIONS_COLUMN, SchemaBuilder.frozen(Permissions.TYPE_NAME));

final String table_statement =
SchemaBuilder.createTable(TABLE_NAME)
.addPartitionKey(IDENTIFIER_COLUMN, DataType.text())
.addUDTListColumn(PERMISSIONS_COLUMN, SchemaBuilder.frozen(Permissions.TYPE_NAME))
.buildInternal();

cassandraSessionProvider.getTenantSession().execute(table_statement);
cassandraSessionProvider.getTenantSession().execute(create);

}

@@ -99,7 +98,6 @@ public List<RoleEntity> getAll()

final Statement statement = QueryBuilder.select().all().from(TABLE_NAME);

return entityMapper.map(tenantSession.execute(statement)).all()
.stream().collect(Collectors.toList());
return new ArrayList<>(entityMapper.map(tenantSession.execute(statement)).all());
}
}
@@ -22,7 +22,9 @@
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
import com.datastax.driver.core.querybuilder.Update;
import com.datastax.driver.core.schemabuilder.Create;
import com.datastax.driver.core.schemabuilder.SchemaBuilder;
import com.datastax.driver.core.schemabuilder.SchemaStatement;
import com.datastax.driver.mapping.Mapper;
import io.mifos.core.cassandra.core.CassandraSessionProvider;
import io.mifos.core.cassandra.core.TenantAwareCassandraMapperProvider;
@@ -37,6 +39,13 @@
import java.util.stream.StreamSupport;

/**
* All write accesses are synchronized. These occur only during provisioning or key rotation, so they are not
* performance critical. These are only necessary because for some reason (that I have not yet been able to track
* down), provisioning is being called multiple times in rapid succession for a tenant.
*
* All calls to cassandra which could conceivably be performed before provisioning is complete are surrounded by
* a try-catch block for an InvalidQueryException. If provisioning is not completed, the table is treated as empty.
*
* @author Myrle Krantz
*/
@Component
@@ -61,29 +70,27 @@ public Signatures(
this.tenantAwareCassandraMapperProvider = tenantAwareCassandraMapperProvider;
}

public void buildTable() {
final String statement =
SchemaBuilder.createTable(TABLE_NAME)
.addPartitionKey(KEY_TIMESTAMP_COLUMN, DataType.text())
.addColumn(VALID_COLUMN, DataType.cboolean())
.addColumn(PRIVATE_KEY_MOD_COLUMN, DataType.varint())
.addColumn(PRIVATE_KEY_EXP_COLUMN, DataType.varint())
.addColumn(PUBLIC_KEY_MOD_COLUMN, DataType.varint())
.addColumn(PUBLIC_KEY_EXP_COLUMN, DataType.varint())
.buildInternal();

cassandraSessionProvider.getTenantSession().execute(statement);

final String createValidIndex = SchemaBuilder.createIndex(INDEX_NAME)
.ifNotExists()
.onTable(TABLE_NAME)
.andColumn(VALID_COLUMN)
.toString();
public synchronized void buildTable() {
final Create create = SchemaBuilder.createTable(TABLE_NAME)
.ifNotExists()
.addPartitionKey(KEY_TIMESTAMP_COLUMN, DataType.text())
.addColumn(VALID_COLUMN, DataType.cboolean())
.addColumn(PRIVATE_KEY_MOD_COLUMN, DataType.varint())
.addColumn(PRIVATE_KEY_EXP_COLUMN, DataType.varint())
.addColumn(PUBLIC_KEY_MOD_COLUMN, DataType.varint())
.addColumn(PUBLIC_KEY_EXP_COLUMN, DataType.varint());

cassandraSessionProvider.getTenantSession().execute(create);

final SchemaStatement createValidIndex = SchemaBuilder.createIndex(INDEX_NAME)
.ifNotExists()
.onTable(TABLE_NAME)
.andColumn(VALID_COLUMN);

cassandraSessionProvider.getTenantSession().execute(createValidIndex);
}

public SignatureEntity add(final RsaKeyPairFactory.KeyPairHolder keys)
public synchronized SignatureEntity add(final RsaKeyPairFactory.KeyPairHolder keys)
{
//There will only be one entry in this table.
final BoundStatement tenantCreationStatement =
@@ -116,37 +123,41 @@ public SignatureEntity add(final RsaKeyPairFactory.KeyPairHolder keys)
}

public Optional<SignatureEntity> getSignature(final String keyTimestamp) {
final Mapper<SignatureEntity> signatureEntityMapper
= tenantAwareCassandraMapperProvider.getMapper(SignatureEntity.class);
try {
final Mapper<SignatureEntity> signatureEntityMapper
= tenantAwareCassandraMapperProvider.getMapper(SignatureEntity.class);

final Optional<SignatureEntity> ret = Optional.ofNullable(signatureEntityMapper.get(keyTimestamp));
return ret.filter(SignatureEntity::getValid);
final Optional<SignatureEntity> ret = Optional.ofNullable(signatureEntityMapper.get(keyTimestamp));
return ret.filter(SignatureEntity::getValid);
}
catch (final InvalidQueryException e) {
return Optional.empty();
}
}

/**
* @return the most current valid private key pair with key timestamp. If there are no valid key pairs, returns Optional.empty.
*/
public Optional<PrivateSignatureEntity> getPrivateSignature()
{
final Optional<String> maximumKeyTimestamp = streamValidKeyTimestamps().max(String::compareTo);

return maximumKeyTimestamp.flatMap(this::getPrivateSignatureEntity);
}

private Optional<PrivateSignatureEntity> getPrivateSignatureEntity(final String keyTimestamp) {
try {
final Optional<String> maximumKeyTimestamp = streamValidKeyTimestamps().max(String::compareTo);
final Mapper<PrivateSignatureEntity> privateSignatureEntityMapper
= tenantAwareCassandraMapperProvider.getMapper(PrivateSignatureEntity.class);

return maximumKeyTimestamp.flatMap(this::getPrivateSignatureEntity);
final Optional<PrivateSignatureEntity> ret = Optional.ofNullable(privateSignatureEntityMapper.get(keyTimestamp));
return ret.filter(PrivateSignatureEntity::getValid);
}
catch (final InvalidQueryException e) {
return Optional.empty();
}
}

private Optional<PrivateSignatureEntity> getPrivateSignatureEntity(final String keyTimestamp) {

final Mapper<PrivateSignatureEntity> privateSignatureEntityMapper
= tenantAwareCassandraMapperProvider.getMapper(PrivateSignatureEntity.class);

final Optional<PrivateSignatureEntity> ret = Optional.ofNullable(privateSignatureEntityMapper.get(keyTimestamp));
return ret.filter(PrivateSignatureEntity::getValid);
}

public List<String> getAllKeyTimestamps() {
return streamValidKeyTimestamps().collect(Collectors.toList());
}
@@ -165,9 +176,8 @@ private Stream<String> streamValidKeyTimestamps() {
}
}

public void invalidateEntry(final String keyTimestamp) {
public synchronized void invalidateEntry(final String keyTimestamp) {
final Update.Assignments updateQuery = QueryBuilder.update(TABLE_NAME).where(QueryBuilder.eq(KEY_TIMESTAMP_COLUMN, keyTimestamp)).with(QueryBuilder.set(VALID_COLUMN, false));
cassandraSessionProvider.getTenantSession().execute(updateQuery);

}
}
@@ -18,6 +18,7 @@
import com.datastax.driver.core.BoundStatement;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.KeyspaceMetadata;
import com.datastax.driver.core.schemabuilder.Create;
import com.datastax.driver.core.schemabuilder.SchemaBuilder;
import io.mifos.core.cassandra.core.CassandraSessionProvider;
import io.mifos.core.cassandra.core.TenantAwareEntityTemplate;
@@ -51,15 +52,14 @@ public class Tenants {
}

public void buildTable() {
final String statement =
SchemaBuilder.createTable(TABLE_NAME)
.addPartitionKey(VERSION_COLUMN, DataType.cint())
.addColumn(FIXED_SALT_COLUMN, DataType.blob())
.addColumn(PASSWORD_EXPIRES_IN_DAYS_COLUMN, DataType.cint())
.addColumn(TIME_TO_CHANGE_PASSWORD_AFTER_EXPIRATION_IN_DAYS, DataType.cint())
.buildInternal();

cassandraSessionProvider.getTenantSession().execute(statement);
final Create create = SchemaBuilder.createTable(TABLE_NAME)
.ifNotExists()
.addPartitionKey(VERSION_COLUMN, DataType.cint())
.addColumn(FIXED_SALT_COLUMN, DataType.blob())
.addColumn(PASSWORD_EXPIRES_IN_DAYS_COLUMN, DataType.cint())
.addColumn(TIME_TO_CHANGE_PASSWORD_AFTER_EXPIRATION_IN_DAYS, DataType.cint());

cassandraSessionProvider.getTenantSession().execute(create);
}

public void add(

0 comments on commit b28f5f6

Please sign in to comment.