Fixing demo-server compatible with latest changes to portfolio. Added rhythm and user for beats.
diff --git a/build.gradle b/build.gradle
index 28fcd2c..6644f9a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,6 +24,7 @@
frameworkservicestarter : '0.1.0-BUILD-SNAPSHOT',
mifosidentity : '0.1.0-BUILD-SNAPSHOT',
mifosprovisioner : '0.1.0-BUILD-SNAPSHOT',
+ mifosrhythm : '0.1.0-BUILD-SNAPSHOT',
mifosoffice : '0.1.0-BUILD-SNAPSHOT',
mifoscustomer : '0.1.0-BUILD-SNAPSHOT',
mifosaccounting : '0.1.0-BUILD-SNAPSHOT',
@@ -72,6 +73,8 @@
[group: 'io.mifos.office', name: 'api', version: versions.mifosoffice],
[group: 'io.mifos.provisioner', name: 'api', version: versions.mifosprovisioner],
[group: 'io.mifos.identity', name: 'api', version: versions.mifosidentity],
+ [group: 'io.mifos.rhythm', name: 'api', version: versions.mifosrhythm],
+ [group: 'io.mifos.rhythm', name: 'spi', version: versions.mifosrhythm],
[group: 'io.mifos.customer', name: 'api', version: versions.mifoscustomer],
[group: 'io.mifos.accounting', name: 'api', version: versions.mifosaccounting],
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 2a39c0d..d93f55f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Sat Apr 08 09:53:20 CEST 2017
+#Mon Jun 12 22:30:04 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-all.zip
diff --git a/src/main/java/io/mifos/dev/AdminPasswordHolder.java b/src/main/java/io/mifos/dev/AdminPasswordHolder.java
deleted file mode 100644
index 4936f81..0000000
--- a/src/main/java/io/mifos/dev/AdminPasswordHolder.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2017 The Mifos Initiative.
- *
- * Licensed 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 io.mifos.dev;
-
-class AdminPasswordHolder {
-
- private String password;
-
- AdminPasswordHolder() {
- super();
- }
-
- String getPassword() {
- return this.password;
- }
-
- void setPassword(final String password) {
- this.password = password;
- }
-}
diff --git a/src/main/java/io/mifos/dev/ServiceRunner.java b/src/main/java/io/mifos/dev/ServiceRunner.java
index a7782d3..27e83ce 100644
--- a/src/main/java/io/mifos/dev/ServiceRunner.java
+++ b/src/main/java/io/mifos/dev/ServiceRunner.java
@@ -20,6 +20,7 @@
import io.mifos.accounting.api.v1.client.LedgerManager;
import io.mifos.anubis.api.v1.domain.AllowedOperation;
import io.mifos.core.api.config.EnableApiFactory;
+import io.mifos.core.api.context.AutoGuest;
import io.mifos.core.api.context.AutoSeshat;
import io.mifos.core.api.context.AutoUserContext;
import io.mifos.core.api.util.ApiConstants;
@@ -27,6 +28,8 @@
import io.mifos.core.cassandra.util.CassandraConnectorConstants;
import io.mifos.core.lang.AutoTenantContext;
import io.mifos.core.mariadb.util.MariaDBConstants;
+import io.mifos.core.test.env.ExtraProperties;
+import io.mifos.core.test.listener.EnableEventRecording;
import io.mifos.core.test.listener.EventRecorder;
import io.mifos.core.test.servicestarter.ActiveMQForTest;
import io.mifos.core.test.servicestarter.EurekaForTest;
@@ -35,31 +38,27 @@
import io.mifos.customer.api.v1.client.CustomerManager;
import io.mifos.deposit.api.v1.client.DepositAccountManager;
import io.mifos.identity.api.v1.client.IdentityManager;
-import io.mifos.identity.api.v1.domain.Authentication;
-import io.mifos.identity.api.v1.domain.Password;
-import io.mifos.identity.api.v1.domain.Permission;
-import io.mifos.identity.api.v1.domain.Role;
-import io.mifos.identity.api.v1.domain.UserWithPassword;
+import io.mifos.identity.api.v1.domain.*;
+import io.mifos.identity.api.v1.events.ApplicationPermissionEvent;
+import io.mifos.identity.api.v1.events.ApplicationPermissionUserEvent;
+import io.mifos.identity.api.v1.events.ApplicationSignatureEvent;
import io.mifos.identity.api.v1.events.EventConstants;
import io.mifos.office.api.v1.client.OrganizationManager;
import io.mifos.portfolio.api.v1.client.PortfolioManager;
import io.mifos.provisioner.api.v1.client.Provisioner;
-import io.mifos.provisioner.api.v1.domain.Application;
-import io.mifos.provisioner.api.v1.domain.AssignedApplication;
-import io.mifos.provisioner.api.v1.domain.AuthenticationResponse;
-import io.mifos.provisioner.api.v1.domain.IdentityManagerInitialization;
-import io.mifos.provisioner.api.v1.domain.Tenant;
+import io.mifos.provisioner.api.v1.domain.*;
+import io.mifos.rhythm.api.v1.client.RhythmManager;
+import io.mifos.rhythm.api.v1.events.BeatEvent;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
+import org.eclipse.aether.resolution.ArtifactResolutionException;
+import org.junit.*;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@@ -67,10 +66,10 @@
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Base64Utils;
+import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import java.util.Properties;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;
@@ -79,13 +78,18 @@
@SpringBootTest()
public class ServiceRunner {
private static final String CLIENT_ID = "service-runner";
+ private static final String SCHEDULER_USER_NAME = "imhotep";
+ private static final String ADMIN_USER_NAME = "antony";
+ private static final String TEST_LOGGER = "test-logger";
+
private static Microservice<Provisioner> provisionerService;
- private static Microservice<IdentityManager> identityService;
- private static Microservice<OrganizationManager> officeClient;
- private static Microservice<CustomerManager> customerClient;
- private static Microservice<LedgerManager> accountingClient;
- private static Microservice<PortfolioManager> portfolioClient;
- private static Microservice<DepositAccountManager> depositClient;
+ private static Microservice<IdentityManager> identityManager;
+ private static Microservice<RhythmManager> rhythmManager;
+ private static Microservice<OrganizationManager> organizationManager;
+ private static Microservice<CustomerManager> customerManager;
+ private static Microservice<LedgerManager> ledgerManager;
+ private static Microservice<PortfolioManager> portfolioManager;
+ private static Microservice<DepositAccountManager> depositAccountManager;
private static DB embeddedMariaDb;
@@ -94,15 +98,16 @@
@Configuration
@ActiveMQForTest.EnableActiveMQListen
@EnableApiFactory
+ @EnableEventRecording(maxWait = 60_000)
@ComponentScan("io.mifos.dev.listener")
public static class TestConfiguration {
public TestConfiguration() {
super();
}
- @Bean()
+ @Bean(name = TEST_LOGGER)
public Logger logger() {
- return LoggerFactory.getLogger("test-logger");
+ return LoggerFactory.getLogger(TEST_LOGGER);
}
}
@@ -124,7 +129,13 @@
@Autowired
private Environment environment;
- private Properties generalProperties;
+ @Autowired
+ protected DiscoveryClient discoveryClient;
+
+ @Autowired
+ @Qualifier(TEST_LOGGER)
+ private Logger logger;
+
private boolean isPersistent;
private boolean shouldProvision;
@@ -150,30 +161,57 @@
ServiceRunner.embeddedMariaDb.start();
}
- this.generalProperties = new Properties();
- this.generalProperties.setProperty("server.max-http-header-size", Integer.toString(16 * 1024));
- this.generalProperties.setProperty("bonecp.partitionCount", "1");
- this.generalProperties.setProperty("bonecp.maxConnectionsPerPartition", "4");
- this.generalProperties.setProperty("bonecp.minConnectionsPerPartition", "1");
- this.generalProperties.setProperty("bonecp.acquireIncrement", "1");
- this.setAdditionalProperties(this.generalProperties);
+ ExtraProperties generalProperties = new ExtraProperties();
+ generalProperties.setProperty("server.max-http-header-size", Integer.toString(16 * 1024));
+ generalProperties.setProperty("bonecp.partitionCount", "1");
+ generalProperties.setProperty("bonecp.maxConnectionsPerPartition", "4");
+ generalProperties.setProperty("bonecp.minConnectionsPerPartition", "1");
+ generalProperties.setProperty("bonecp.acquireIncrement", "1");
+ this.setAdditionalProperties(generalProperties);
- ServiceRunner.identityService = this.startService(IdentityManager.class, "identity", this.generalProperties);
- ServiceRunner.officeClient = this.startService(OrganizationManager.class, "office", this.generalProperties);
- ServiceRunner.customerClient = this.startService(CustomerManager.class, "customer", this.generalProperties);
- ServiceRunner.accountingClient = this.startService(LedgerManager.class, "accounting", this.generalProperties);
- ServiceRunner.portfolioClient = this.startService(PortfolioManager.class, "portfolio", this.generalProperties);
- ServiceRunner.depositClient = this.startService(DepositAccountManager.class, "deposit-account-management", this.generalProperties);
+ ServiceRunner.provisionerService = new Microservice<>(Provisioner.class, "provisioner", "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT);
+ provisionerService.getProcessEnvironment().addSystemPrivateKeyToProperties();
+ provisionerService.getProcessEnvironment().setProperty("system.initialclientid", ServiceRunner.CLIENT_ID);
+ startService(generalProperties, provisionerService);
+
+ ServiceRunner.identityManager = new Microservice<>(IdentityManager.class, "identity", "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT)
+ .addProperties(new ExtraProperties() {{
+ setProperty("identity.token.refresh.secureCookie", "false");}});
+ startService(generalProperties, identityManager);
+
+ ServiceRunner.rhythmManager = new Microservice<>(RhythmManager.class, "rhythm", "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT)
+ .addProperties(new ExtraProperties() {{
+ setProperty("rhythm.beatCheckRate", Long.toString(TimeUnit.MINUTES.toMillis(10)));
+ setProperty("rhythm.user", SCHEDULER_USER_NAME);}});
+ startService(generalProperties, rhythmManager);
+
+ ServiceRunner.organizationManager = new Microservice<>(OrganizationManager.class, "office", "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT);
+ startService(generalProperties, organizationManager);
+
+ ServiceRunner.customerManager = new Microservice<>(CustomerManager.class, "customer", "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT);
+ startService(generalProperties, customerManager);
+
+ ServiceRunner.ledgerManager = new Microservice<>(LedgerManager.class, "accounting", "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT);
+ startService(generalProperties, ledgerManager);
+
+ ServiceRunner.portfolioManager = new Microservice<>(PortfolioManager.class, "portfolio", "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT)
+ .addProperties(new ExtraProperties() {{
+ setProperty("portfolio.bookInterestAsUser", SCHEDULER_USER_NAME);}});
+ startService(generalProperties, portfolioManager);
+
+ ServiceRunner.depositAccountManager = new Microservice<>(DepositAccountManager.class, "deposit-account-management", "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT);
+ startService(generalProperties, depositAccountManager);
}
@After
public void tearDown() throws Exception {
- ServiceRunner.depositClient.kill();
- ServiceRunner.portfolioClient.kill();
- ServiceRunner.accountingClient.kill();
- ServiceRunner.customerClient.kill();
- ServiceRunner.officeClient.kill();
- ServiceRunner.identityService.kill();
+ ServiceRunner.depositAccountManager.kill();
+ ServiceRunner.rhythmManager.kill();
+ ServiceRunner.portfolioManager.kill();
+ ServiceRunner.ledgerManager.kill();
+ ServiceRunner.customerManager.kill();
+ ServiceRunner.organizationManager.kill();
+ ServiceRunner.identityManager.kill();
if (!isPersistent) {
ServiceRunner.embeddedMariaDb.stop();
@@ -182,24 +220,24 @@
}
@Test
- public void startDevServer() throws Exception {
-
- ServiceRunner.provisionerService = this.startService(Provisioner.class, "provisioner", this.generalProperties);
-
- if (this.shouldProvision) {
- this.provisionAppsViaSeshat();
- } else {
- this.migrateServices();
+ public void startDevServer() throws InterruptedException, IOException, ArtifactResolutionException {
+ try {
+ if (this.shouldProvision) {
+ this.provisionAppsViaSeshat();
+ } else {
+ this.migrateServices();
+ }
+ }
+ finally {
+ ServiceRunner.provisionerService.kill();
}
- ServiceRunner.provisionerService.kill();
-
- System.out.println("Identity Service: " + ServiceRunner.identityService.getProcessEnvironment().serverURI());
- System.out.println("Office Service: " + ServiceRunner.officeClient.getProcessEnvironment().serverURI());
- System.out.println("Customer Service: " + ServiceRunner.customerClient.getProcessEnvironment().serverURI());
- System.out.println("Accounting Service: " + ServiceRunner.accountingClient.getProcessEnvironment().serverURI());
- System.out.println("Portfolio Service: " + ServiceRunner.portfolioClient.getProcessEnvironment().serverURI());
- System.out.println("Deposit Service: " + ServiceRunner.depositClient.getProcessEnvironment().serverURI());
+ System.out.println("Identity Service: " + ServiceRunner.identityManager.getProcessEnvironment().serverURI());
+ System.out.println("Office Service: " + ServiceRunner.organizationManager.getProcessEnvironment().serverURI());
+ System.out.println("Customer Service: " + ServiceRunner.customerManager.getProcessEnvironment().serverURI());
+ System.out.println("Accounting Service: " + ServiceRunner.ledgerManager.getProcessEnvironment().serverURI());
+ System.out.println("Portfolio Service: " + ServiceRunner.portfolioManager.getProcessEnvironment().serverURI());
+ System.out.println("Deposit Service: " + ServiceRunner.depositAccountManager.getProcessEnvironment().serverURI());
boolean run = true;
@@ -209,28 +247,21 @@
if (nextLine != null && nextLine.equals("exit")) {
run = false;
}
+ eventRecorder.clear();
}
}
- private <T> Microservice<T> startService(final Class<T> serviceClass, final String serviceName, final Properties properties) throws Exception {
- final Microservice<T> microservice = new Microservice<>(serviceClass, serviceName, "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT);
- if (properties !=null) {
- properties.forEach((key, value) -> {
- if (serviceName.equals("provisioner")) {
- microservice.getProcessEnvironment().addSystemPrivateKeyToProperties();
- microservice.getProcessEnvironment().setProperty("system.initialclientid", ServiceRunner.CLIENT_ID);
- } else if (serviceName.equals("identity")) {
- microservice.getProcessEnvironment().setProperty("identity.token.refresh.secureCookie", "false");
- }
- microservice.getProcessEnvironment().setProperty(key.toString(), value.toString());
- });
- }
+ private void startService(ExtraProperties properties, Microservice microservice) throws InterruptedException, IOException, ArtifactResolutionException {
+ microservice.addProperties(properties);
microservice.start();
+ final boolean registered = microservice.waitTillRegistered(discoveryClient);
+ logger.info("Service '{}' started and {} with Eureka.", microservice.name(), registered ? "registered" : "not registered");
microservice.setApiFactory(this.apiFactory);
- return microservice;
+
+ TimeUnit.SECONDS.sleep(20); //Give it some extra time before the next service...
}
- private void migrateServices() throws Exception {
+ private void migrateServices() {
final AuthenticationResponse authenticationResponse =
ServiceRunner.provisionerService.api().authenticate(ServiceRunner.CLIENT_ID, ApiConstants.SYSTEM_SU, "oS/0IiAME/2unkN1momDrhAdNKOhGykYFH/mJN20");
@@ -239,7 +270,7 @@
tenants.forEach(tenant -> {
final List<AssignedApplication> assignedApplications = ServiceRunner.provisionerService.api().getAssignedApplications(tenant.getIdentifier());
assignedApplications.forEach(assignedApplication -> {
- if (assignedApplication.getName().equals(ServiceRunner.identityService.name())) {
+ if (assignedApplication.getName().equals(ServiceRunner.identityManager.name())) {
ServiceRunner.provisionerService.api().assignIdentityManager(tenant.getIdentifier(), assignedApplication);
} else {
ServiceRunner.provisionerService.api().assignApplications(tenant.getIdentifier(), Collections.singletonList(assignedApplication));
@@ -254,17 +285,18 @@
}
}
- private void provisionAppsViaSeshat() throws Exception {
+ private void provisionAppsViaSeshat() throws InterruptedException {
final AuthenticationResponse authenticationResponse =
ServiceRunner.provisionerService.api().authenticate(ServiceRunner.CLIENT_ID, ApiConstants.SYSTEM_SU, "oS/0IiAME/2unkN1momDrhAdNKOhGykYFH/mJN20");
final List<Application> applicationsToCreate = Arrays.asList(
- ApplicationBuilder.create(ServiceRunner.identityService.name(), ServiceRunner.identityService.uri()),
- ApplicationBuilder.create(ServiceRunner.officeClient.name(), ServiceRunner.officeClient.uri()),
- ApplicationBuilder.create(ServiceRunner.customerClient.name(), ServiceRunner.customerClient.uri()),
- ApplicationBuilder.create(ServiceRunner.accountingClient.name(), ServiceRunner.accountingClient.uri()),
- ApplicationBuilder.create(ServiceRunner.portfolioClient.name(), ServiceRunner.portfolioClient.uri()),
- ApplicationBuilder.create(ServiceRunner.depositClient.name(), ServiceRunner.depositClient.uri())
+ ApplicationBuilder.create(ServiceRunner.identityManager.name(), ServiceRunner.identityManager.uri()),
+ ApplicationBuilder.create(ServiceRunner.rhythmManager.name(), ServiceRunner.rhythmManager.uri()),
+ ApplicationBuilder.create(ServiceRunner.organizationManager.name(), ServiceRunner.organizationManager.uri()),
+ ApplicationBuilder.create(ServiceRunner.customerManager.name(), ServiceRunner.customerManager.uri()),
+ ApplicationBuilder.create(ServiceRunner.ledgerManager.name(), ServiceRunner.ledgerManager.uri()),
+ ApplicationBuilder.create(ServiceRunner.portfolioManager.name(), ServiceRunner.portfolioManager.uri()),
+ ApplicationBuilder.create(ServiceRunner.depositAccountManager.name(), ServiceRunner.depositAccountManager.uri())
);
final List<Tenant> tenantsToCreate = Arrays.asList(
@@ -279,53 +311,156 @@
try (final AutoSeshat ignored = new AutoSeshat(authenticationResponse.getToken())) {
applicationsToCreate.forEach(application -> ServiceRunner.provisionerService.api().createApplication(application));
}
-
- final AdminPasswordHolder adminPasswordHolder = new AdminPasswordHolder();
- tenantsToCreate.forEach(tenant -> {
+ for (final Tenant tenant : tenantsToCreate) {
try (final AutoSeshat ignored = new AutoSeshat(authenticationResponse.getToken())) {
- ServiceRunner.provisionerService.api().createTenant(tenant);
- applicationsToCreate.forEach(application -> {
- if (application.getName().equals(ServiceRunner.identityService.name())) {
- final AssignedApplication assignedApplication = new AssignedApplication();
- assignedApplication.setName(ServiceRunner.identityService.name());
-
- final IdentityManagerInitialization identityManagerInitialization = ServiceRunner.provisionerService.api().assignIdentityManager(tenant.getIdentifier(), assignedApplication);
- adminPasswordHolder.setPassword(identityManagerInitialization.getAdminPassword());
- } else {
- final AssignedApplication assignedApplication = new AssignedApplication();
- assignedApplication.setName(application.getName());
- ServiceRunner.provisionerService.api().assignApplications(tenant.getIdentifier(), Collections.singletonList(assignedApplication));
- try {
- Thread.sleep(5000L);
- } catch (InterruptedException e) {
- //do nothing
- }
- }
- });
+ provisionAppsViaSeshatForTenant(tenant);
}
-
- try (final AutoTenantContext autoTenantContext = new AutoTenantContext(tenant.getIdentifier())) {
- this.createAdmin(adminPasswordHolder.getPassword());
- } catch (final Exception ex) {
- ex.printStackTrace();
- }
- });
+ }
}
- private void createAdmin(final String tenantAdminPassword) throws Exception {
- final String tenantAdminUser = "antony";
- final Authentication adminPasswordOnlyAuthentication = ServiceRunner.identityService.api().login(tenantAdminUser, tenantAdminPassword);
- try (final AutoUserContext ignored = new AutoUserContext(tenantAdminUser, adminPasswordOnlyAuthentication.getAccessToken()))
- {
- ServiceRunner.identityService.api().changeUserPassword(tenantAdminUser, new Password(tenantAdminPassword));
- Assert.assertTrue(this.eventRecorder.wait(EventConstants.OPERATION_PUT_USER_PASSWORD, tenantAdminUser));
- }
- final Authentication adminAuthentication = ServiceRunner.identityService.api().login(tenantAdminUser, tenantAdminPassword);
+ private String provisionAppsViaSeshatForTenant(final Tenant tenant) throws InterruptedException {
+ provisionerService.api().createTenant(tenant);
- try (final AutoUserContext ignored = new AutoUserContext(tenantAdminUser, adminAuthentication.getAccessToken())) {
+ try (final AutoTenantContext ignored = new AutoTenantContext(tenant.getIdentifier())) {
+
+ final AssignedApplication isisAssigned = new AssignedApplication();
+ isisAssigned.setName(identityManager.name());
+
+ final IdentityManagerInitialization tenantAdminPassword
+ = provisionerService.api().assignIdentityManager(tenant.getIdentifier(), isisAssigned);
+
+
+ //Creation of the schedulerUserRole, and permitting it to create application permission requests are needed in the
+ //provisioning of portfolio. Portfolio asks rhythm for a callback. Rhythm asks identity for permission to send
+ //that call back. Rhythm needs permission to ask identity directly rather than through the provisioner because
+ //the request is made outside of rhythm's initialization.
+ final UserWithPassword schedulerUser = createSchedulerUserRoleAndPassword(tenantAdminPassword.getAdminPassword());
+
+ provisionApp(tenant, rhythmManager, io.mifos.rhythm.api.v1.events.EventConstants.INITIALIZE);
+
+ Assert.assertTrue(this.eventRecorder.wait(EventConstants.OPERATION_POST_APPLICATION_PERMISSION, new ApplicationPermissionEvent(rhythmManager.name(), io.mifos.identity.api.v1.PermittableGroupIds.APPLICATION_SELF_MANAGEMENT)));
+
+ final Authentication schedulerUserAuthentication;
+ try (final AutoGuest ignored2 = new AutoGuest()) {
+ enableUser(schedulerUser);
+ schedulerUserAuthentication = identityManager.api().login(schedulerUser.getIdentifier(), schedulerUser.getPassword());
+ }
+
+ try (final AutoUserContext ignored2 = new AutoUserContext(schedulerUser.getIdentifier(), schedulerUserAuthentication.getAccessToken())) {
+ identityManager.api().setApplicationPermissionEnabledForUser(
+ rhythmManager.name(),
+ io.mifos.identity.api.v1.PermittableGroupIds.APPLICATION_SELF_MANAGEMENT,
+ schedulerUser.getIdentifier(),
+ true);
+ Assert.assertTrue(this.eventRecorder.wait(EventConstants.OPERATION_PUT_APPLICATION_PERMISSION_USER_ENABLED, new ApplicationPermissionUserEvent(rhythmManager.name(), io.mifos.identity.api.v1.PermittableGroupIds.APPLICATION_SELF_MANAGEMENT, schedulerUser.getIdentifier())));
+ }
+
+ provisionApp(tenant, ledgerManager, io.mifos.accounting.api.v1.EventConstants.INITIALIZE);
+
+ provisionApp(tenant, portfolioManager, io.mifos.portfolio.api.v1.events.EventConstants.INITIALIZE);
+
+ Assert.assertTrue(this.eventRecorder.wait(EventConstants.OPERATION_POST_PERMITTABLE_GROUP,
+ io.mifos.rhythm.spi.v1.PermittableGroupIds.forApplication(portfolioManager.name())));
+
+ for (int i = 0; i < 24; i++) {
+ Assert.assertTrue("Beat #" + i,
+ eventRecorder.wait(io.mifos.rhythm.api.v1.events.EventConstants.POST_BEAT,
+ new BeatEvent(portfolioManager.name(), "alignment" + i)));
+ }
+
+ final Authentication schedulerAuthentication;
+ try (final AutoGuest ignored2 = new AutoGuest()) {
+ schedulerAuthentication = identityManager.api().login(schedulerUser.getIdentifier(), schedulerUser.getPassword());
+ }
+
+ try (final AutoUserContext ignored2 = new AutoUserContext(schedulerUser.getIdentifier(), schedulerAuthentication.getAccessToken())) {
+ //Allow rhythm to send a beat to portfolio as the scheduler user.
+ identityManager.api().setApplicationPermissionEnabledForUser(
+ rhythmManager.name(),
+ io.mifos.rhythm.spi.v1.PermittableGroupIds.forApplication(portfolioManager.name()),
+ schedulerUser.getIdentifier(),
+ true);
+ Assert.assertTrue(this.eventRecorder.wait(EventConstants.OPERATION_PUT_APPLICATION_PERMISSION_USER_ENABLED,
+ new ApplicationPermissionUserEvent(rhythmManager.name(),
+ io.mifos.rhythm.spi.v1.PermittableGroupIds.forApplication(portfolioManager.name()), schedulerUser.getIdentifier())));
+ }
+
+ provisionApp(tenant, depositAccountManager, io.mifos.deposit.api.v1.EventConstants.INITIALIZE);
+
+ createOrgAdminRoleAndUser(tenantAdminPassword.getAdminPassword());
+
+ return tenantAdminPassword.getAdminPassword();
+ }
+ }
+
+ private <T> void provisionApp(
+ final Tenant tenant,
+ final Microservice<T> service,
+ final String initialize_event) throws InterruptedException {
+
+ final AssignedApplication assignedApp = new AssignedApplication();
+ assignedApp.setName(service.name());
+
+ provisionerService.api().assignApplications(tenant.getIdentifier(), Collections.singletonList(assignedApp));
+
+ Assert.assertTrue(this.eventRecorder.wait(initialize_event, initialize_event));
+ Assert.assertTrue(this.eventRecorder.waitForMatch(EventConstants.OPERATION_PUT_APPLICATION_SIGNATURE,
+ (ApplicationSignatureEvent x) -> x.getApplicationIdentifier().equals(service.name())));
+ }
+
+ private UserWithPassword createSchedulerUserRoleAndPassword(String tenantAdminPassword) throws InterruptedException {
+ final Authentication adminAuthentication;
+ try (final AutoGuest ignored = new AutoGuest()) {
+ adminAuthentication = identityManager.api().login(ADMIN_USER_NAME, tenantAdminPassword);
+ }
+
+ final UserWithPassword schedulerUser;
+ try (final AutoUserContext ignored = new AutoUserContext(ADMIN_USER_NAME, adminAuthentication.getAccessToken())) {
+ final Role schedulerRole = defineSchedulerRole();
+ identityManager.api().createRole(schedulerRole);
+
+ schedulerUser = new UserWithPassword();
+ schedulerUser.setIdentifier(SCHEDULER_USER_NAME);
+ schedulerUser.setPassword(encodePassword("26500BC"));
+ schedulerUser.setRole(schedulerRole.getIdentifier());
+
+ identityManager.api().createUser(schedulerUser);
+ Assert.assertTrue(eventRecorder.wait(EventConstants.OPERATION_POST_USER, schedulerUser.getIdentifier()));
+ }
+
+ try (final AutoGuest ignored = new AutoGuest()) {
+ enableUser(schedulerUser);
+ }
+
+ return schedulerUser;
+ }
+
+ private Role defineSchedulerRole() {
+ final Permission permissionRequestionCreationPermission = new Permission();
+ permissionRequestionCreationPermission.setAllowedOperations(Collections.singleton(AllowedOperation.CHANGE));
+ permissionRequestionCreationPermission.setPermittableEndpointGroupIdentifier(io.mifos.identity.api.v1.PermittableGroupIds.APPLICATION_SELF_MANAGEMENT);
+
+ final Permission beatPublishToPortfolioPermission = new Permission();
+ beatPublishToPortfolioPermission.setAllowedOperations(Collections.singleton(AllowedOperation.CHANGE));
+ beatPublishToPortfolioPermission.setPermittableEndpointGroupIdentifier(io.mifos.rhythm.spi.v1.PermittableGroupIds.forApplication(portfolioManager.name()));
+
+ final Role role = new Role();
+ role.setIdentifier("scheduler");
+ role.setPermissions(Arrays.asList(permissionRequestionCreationPermission, beatPublishToPortfolioPermission));
+
+ return role;
+ }
+
+ private void createOrgAdminRoleAndUser(final String tenantAdminPassword) throws InterruptedException {
+ final Authentication adminAuthentication;
+ try (final AutoUserContext ignored = new AutoGuest()) {
+ adminAuthentication = ServiceRunner.identityManager.api().login(ADMIN_USER_NAME, tenantAdminPassword);
+ }
+
+ try (final AutoUserContext ignored = new AutoUserContext(ADMIN_USER_NAME, adminAuthentication.getAccessToken())) {
final Role fimsAdministratorRole = createOrgAdministratorRole();
- ServiceRunner.identityService.api().createRole(fimsAdministratorRole);
+ ServiceRunner.identityManager.api().createRole(fimsAdministratorRole);
Assert.assertTrue(this.eventRecorder.wait(EventConstants.OPERATION_POST_ROLE, fimsAdministratorRole.getIdentifier()));
final UserWithPassword fimsAdministratorUser = new UserWithPassword();
@@ -333,10 +468,10 @@
fimsAdministratorUser.setPassword(Base64Utils.encodeToString("init1@l".getBytes()));
fimsAdministratorUser.setRole(fimsAdministratorRole.getIdentifier());
- ServiceRunner.identityService.api().createUser(fimsAdministratorUser);
+ ServiceRunner.identityManager.api().createUser(fimsAdministratorUser);
Assert.assertTrue(this.eventRecorder.wait(EventConstants.OPERATION_POST_USER, fimsAdministratorUser.getIdentifier()));
- ServiceRunner.identityService.api().logout();
+ ServiceRunner.identityManager.api().logout();
}
}
@@ -376,7 +511,24 @@
return role;
}
- private void setAdditionalProperties(final Properties properties) {
+ private void enableUser(final UserWithPassword userWithPassword) throws InterruptedException {
+ final Authentication passwordOnlyAuthentication
+ = identityManager.api().login(userWithPassword.getIdentifier(), userWithPassword.getPassword());
+ try (final AutoUserContext ignored
+ = new AutoUserContext(userWithPassword.getIdentifier(), passwordOnlyAuthentication.getAccessToken()))
+ {
+ identityManager.api().changeUserPassword(
+ userWithPassword.getIdentifier(), new Password(userWithPassword.getPassword()));
+ Assert.assertTrue(eventRecorder.wait(EventConstants.OPERATION_PUT_USER_PASSWORD,
+ userWithPassword.getIdentifier()));
+ }
+ }
+
+ private static String encodePassword(final String password) {
+ return Base64Utils.encodeToString(password.getBytes());
+ }
+
+ private void setAdditionalProperties(final ExtraProperties properties) {
if (this.environment.containsProperty(ServiceRunner.CUSTOM_PROP_PREFIX + CassandraConnectorConstants.CONTACT_POINTS_PROP)) {
properties.setProperty(CassandraConnectorConstants.CONTACT_POINTS_PROP, this.environment.getProperty(ServiceRunner.CUSTOM_PROP_PREFIX + CassandraConnectorConstants.CONTACT_POINTS_PROP));
}
diff --git a/src/main/java/io/mifos/dev/listener/AccountingListener.java b/src/main/java/io/mifos/dev/listener/AccountingListener.java
index 46a792e..77e0cd7 100644
--- a/src/main/java/io/mifos/dev/listener/AccountingListener.java
+++ b/src/main/java/io/mifos/dev/listener/AccountingListener.java
@@ -23,6 +23,10 @@
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
+/**
+ * @author Myrle Krantz
+ */
+@SuppressWarnings("unused")
@Component
public class AccountingListener {
@@ -34,12 +38,32 @@
}
@JmsListener(
- subscription = EventConstants.DESTINATION,
- destination = EventConstants.DESTINATION,
- selector = EventConstants.SELECTOR_INITIALIZE
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_INITIALIZE,
+ subscription = EventConstants.DESTINATION
)
- public void onInitialized(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
- final String payload) {
+ public void onInitialization(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
this.eventRecorder.event(tenant, EventConstants.INITIALIZE, payload, String.class);
}
+
+ @JmsListener(
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_POST_LEDGER,
+ subscription = EventConstants.DESTINATION
+ )
+ public void onPostLedger(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
+ this.eventRecorder.event(tenant, EventConstants.POST_LEDGER, payload, String.class);
+ }
+
+ @JmsListener(
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_POST_ACCOUNT,
+ subscription = EventConstants.DESTINATION
+ )
+ public void onCreateAccount(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
+ this.eventRecorder.event(tenant, EventConstants.POST_ACCOUNT, payload, String.class);
+ }
}
diff --git a/src/main/java/io/mifos/dev/listener/CustomerListener.java b/src/main/java/io/mifos/dev/listener/CustomerListener.java
index a73b500..f667407 100644
--- a/src/main/java/io/mifos/dev/listener/CustomerListener.java
+++ b/src/main/java/io/mifos/dev/listener/CustomerListener.java
@@ -23,6 +23,7 @@
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
+@SuppressWarnings("unused")
@Component
public class CustomerListener {
diff --git a/src/main/java/io/mifos/dev/listener/IdentityListener.java b/src/main/java/io/mifos/dev/listener/IdentityListener.java
index 1848927..1c335c2 100644
--- a/src/main/java/io/mifos/dev/listener/IdentityListener.java
+++ b/src/main/java/io/mifos/dev/listener/IdentityListener.java
@@ -17,6 +17,9 @@
import io.mifos.core.lang.config.TenantHeaderFilter;
import io.mifos.core.test.listener.EventRecorder;
+import io.mifos.identity.api.v1.events.ApplicationPermissionEvent;
+import io.mifos.identity.api.v1.events.ApplicationPermissionUserEvent;
+import io.mifos.identity.api.v1.events.ApplicationSignatureEvent;
import io.mifos.identity.api.v1.events.EventConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
@@ -38,17 +41,6 @@
}
@JmsListener(
- subscription = EventConstants.DESTINATION,
- destination = EventConstants.DESTINATION,
- selector = EventConstants.SELECTOR_POST_ROLE
- )
- public void onCreateRole(
- @Header(TenantHeaderFilter.TENANT_HEADER)final String tenant,
- final String payload) throws Exception {
- eventRecorder.event(tenant, EventConstants.OPERATION_POST_ROLE, payload, String.class);
- }
-
- @JmsListener(
subscription = EventConstants.DESTINATION,
destination = EventConstants.DESTINATION,
selector = EventConstants.SELECTOR_POST_USER
@@ -69,4 +61,59 @@
final String payload) throws Exception {
eventRecorder.event(tenant, EventConstants.OPERATION_PUT_USER_PASSWORD, payload, String.class);
}
+
+ @JmsListener(
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_POST_PERMITTABLE_GROUP
+ )
+ public void onCreatePermittableGroup(
+ @Header(TenantHeaderFilter.TENANT_HEADER)final String tenant,
+ final String payload) throws Exception {
+ eventRecorder.event(tenant, EventConstants.OPERATION_POST_PERMITTABLE_GROUP, payload, String.class);
+ }
+
+ @JmsListener(
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_POST_APPLICATION_PERMISSION
+ )
+ public void onCreateApplicationPermission(
+ @Header(TenantHeaderFilter.TENANT_HEADER)final String tenant,
+ final String payload) throws Exception {
+ eventRecorder.event(tenant, EventConstants.OPERATION_POST_APPLICATION_PERMISSION, payload, ApplicationPermissionEvent.class);
+ }
+
+ @JmsListener(
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_PUT_APPLICATION_SIGNATURE
+ )
+ public void onSetApplicationSignature(
+ @Header(TenantHeaderFilter.TENANT_HEADER)final String tenant,
+ final String payload) throws Exception {
+ eventRecorder.event(tenant, EventConstants.OPERATION_PUT_APPLICATION_SIGNATURE, payload, ApplicationSignatureEvent.class);
+ }
+
+ @JmsListener(
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_PUT_APPLICATION_PERMISSION_USER_ENABLED
+ )
+ public void onPutApplicationPermissionEnabledForUser(
+ @Header(TenantHeaderFilter.TENANT_HEADER)final String tenant,
+ final String payload) throws Exception {
+ eventRecorder.event(tenant, EventConstants.OPERATION_PUT_APPLICATION_PERMISSION_USER_ENABLED, payload, ApplicationPermissionUserEvent.class);
+ }
+
+ @JmsListener(
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_POST_ROLE
+ )
+ public void onCreateRole(
+ @Header(TenantHeaderFilter.TENANT_HEADER)final String tenant,
+ final String payload) throws Exception {
+ eventRecorder.event(tenant, EventConstants.OPERATION_POST_ROLE, payload, String.class);
+ }
}
diff --git a/src/main/java/io/mifos/dev/listener/PortfolioListener.java b/src/main/java/io/mifos/dev/listener/PortfolioListener.java
index 844d22d..b21f068 100644
--- a/src/main/java/io/mifos/dev/listener/PortfolioListener.java
+++ b/src/main/java/io/mifos/dev/listener/PortfolioListener.java
@@ -23,6 +23,10 @@
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
+/**
+ * @author Myrle Krantz
+ */
+@SuppressWarnings("unused")
@Component
public class PortfolioListener {
@@ -34,12 +38,42 @@
}
@JmsListener(
- subscription = EventConstants.DESTINATION,
- destination = EventConstants.DESTINATION,
- selector = EventConstants.SELECTOR_INITIALIZE
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_INITIALIZE
)
- public void onInitialized(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
- final String payload) {
+ public void onInitialization(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
this.eventRecorder.event(tenant, EventConstants.INITIALIZE, payload, String.class);
}
-}
+
+ @JmsListener(
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_POST_PRODUCT
+ )
+ public void onCreateProduct(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
+ this.eventRecorder.event(tenant, EventConstants.POST_PRODUCT, payload, String.class);
+ }
+
+ @JmsListener(
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_PUT_PRODUCT
+ )
+ public void onChangeProduct(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
+ this.eventRecorder.event(tenant, EventConstants.PUT_PRODUCT, payload, String.class);
+ }
+
+ @JmsListener(
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_PUT_PRODUCT_ENABLE
+ )
+ public void onEnableProduct(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
+ this.eventRecorder.event(tenant, EventConstants.PUT_PRODUCT_ENABLE, payload, String.class);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/io/mifos/dev/listener/RhythmListener.java b/src/main/java/io/mifos/dev/listener/RhythmListener.java
new file mode 100644
index 0000000..54692e3
--- /dev/null
+++ b/src/main/java/io/mifos/dev/listener/RhythmListener.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * Licensed 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 io.mifos.dev.listener;
+
+import io.mifos.core.lang.config.TenantHeaderFilter;
+import io.mifos.core.test.listener.EventRecorder;
+import io.mifos.rhythm.api.v1.events.BeatEvent;
+import io.mifos.rhythm.api.v1.events.EventConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Myrle Krantz
+ */
+@SuppressWarnings("unused")
+@Component
+public class RhythmListener {
+
+ private final EventRecorder eventRecorder;
+
+ @Autowired
+ public RhythmListener(final EventRecorder eventRecorder) {
+ this.eventRecorder = eventRecorder;
+ }
+
+ @JmsListener(
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_INITIALIZE
+ )
+ public void onInitialization(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
+ this.eventRecorder.event(tenant, EventConstants.INITIALIZE, payload, String.class);
+ }
+
+ @JmsListener(
+ subscription = EventConstants.DESTINATION,
+ destination = EventConstants.DESTINATION,
+ selector = EventConstants.SELECTOR_POST_BEAT
+ )
+ public void onCreateBeat(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+ final String payload) {
+ this.eventRecorder.event(tenant, EventConstants.POST_BEAT, payload, BeatEvent.class);
+ }
+}