support schema per tenant multi-tenancy. basic auth security filter is extended to detect tenant-id header on request, verify tenant id is valid and then use provided credentials to authenticate user details against users on the tenant specific schema.
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
|
||||
/* remove column org_id */
|
||||
ALTER TABLE `mifosngprovider`.`portfolio_client` DROP FOREIGN KEY `FKCE00CAB354DF2770` ;ALTER TABLE `mifosngprovider`.`portfolio_client` DROP COLUMN `org_id` , DROP INDEX `org_id` , ADD INDEX `external_id` (`external_id` ASC) , DROP INDEX `FKCE00CAB354DF2770` ;
|
||||
ALTER TABLE `portfolio_client` DROP FOREIGN KEY `FKCE00CAB354DF2770`;
|
||||
ALTER TABLE `portfolio_client`
|
||||
DROP COLUMN `org_id` ,
|
||||
DROP INDEX `org_id` ,
|
||||
ADD INDEX `external_id` (`external_id` ASC) ,
|
||||
DROP INDEX `FKCE00CAB354DF2770`;
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
-- create fund table
|
||||
DROP TABLE IF EXISTS `mifosngprovider`.`org_fund`;
|
||||
DROP TABLE IF EXISTS `org_fund`;
|
||||
CREATE TABLE `org_fund` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`org_id` bigint(20) NOT NULL,
|
||||
@@ -21,13 +21,13 @@ CREATE TABLE `org_fund` (
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
-- example of dropping fund column/index/foreign key
|
||||
-- alter table `mifosngprovider`.`portfolio_product_loan`
|
||||
-- alter table `portfolio_product_loan`
|
||||
-- DROP FOREIGN KEY `FKA6A8A7D77240145`,
|
||||
-- DROP INDEX `FKA6A8A7D77240145`,
|
||||
-- drop column `fund_id`;
|
||||
|
||||
-- associate fund table with loan products making it fund optional at database level
|
||||
alter table `mifosngprovider`.`portfolio_product_loan`
|
||||
alter table `portfolio_product_loan`
|
||||
add column `fund_id` bigint(20) DEFAULT NULL,
|
||||
add KEY `FKA6A8A7D77240145` (`fund_id`),
|
||||
add CONSTRAINT `FKA6A8A7D77240145` FOREIGN KEY (`fund_id`) REFERENCES `org_fund` (`id`);
|
||||
@@ -1,11 +1,11 @@
|
||||
-- example of dropping fund column/index/foreign key
|
||||
-- alter table `mifosngprovider`.`portfolio_loan`
|
||||
-- alter table `portfolio_loan`
|
||||
-- DROP FOREIGN KEY `FK7C885877240145`,
|
||||
-- DROP INDEX `FK7C885877240145`,
|
||||
-- drop column `fund_id`;
|
||||
|
||||
-- associate fund table with loans making fund optional at database level
|
||||
alter table `mifosngprovider`.`portfolio_loan`
|
||||
alter table `portfolio_loan`
|
||||
add column `fund_id` bigint(20) DEFAULT NULL,
|
||||
add KEY `FK7C885877240145` (`fund_id`),
|
||||
add CONSTRAINT `FK7C885877240145` FOREIGN KEY (`fund_id`) REFERENCES `org_fund` (`id`);
|
||||
@@ -1,5 +1,5 @@
|
||||
-- create fund table
|
||||
DROP TABLE IF EXISTS `mifosngprovider`.`portfolio_office_monetary_transfers`;
|
||||
DROP TABLE IF EXISTS `portfolio_office_monetary_transfers`;
|
||||
CREATE TABLE `portfolio_office_monetary_transfers` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`from_office_id` bigint(20) DEFAULT NULL,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-- create office transaction table
|
||||
DROP TABLE IF EXISTS `mifosngprovider`.`portfolio_office_monetary_transfers`;
|
||||
DROP TABLE IF EXISTS `mifosngprovider`.`portfolio_office_transaction`;
|
||||
DROP TABLE IF EXISTS `portfolio_office_monetary_transfers`;
|
||||
DROP TABLE IF EXISTS `portfolio_office_transaction`;
|
||||
CREATE TABLE `portfolio_office_transaction` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`from_office_id` bigint(20) DEFAULT NULL,
|
||||
|
||||
@@ -14,19 +14,16 @@ buildscript {
|
||||
apply plugin: 'war'
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'tomcat'
|
||||
//apply plugin: 'jdepend'
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_1_6
|
||||
targetCompatibility = JavaVersion.VERSION_1_6
|
||||
|
||||
springVersion = '3.1.1.RELEASE'
|
||||
springSecurityOauthVersion = '1.0.0.M6'
|
||||
springSecurityVersion = '3.1.0.RELEASE'
|
||||
hibernateValidatorVersion = '4.2.0.Final'
|
||||
hibernateCoreVersion = '4.1.0.Final'
|
||||
jerseyVersion = '1.12'
|
||||
hibernateValidatorVersion = '4.3.0.Final'
|
||||
hibernateCoreVersion = '4.1.3.Final'
|
||||
jerseyVersion = '1.13'
|
||||
springDataJpaVersion = '1.0.3.RELEASE'
|
||||
springDatamongoDbVersion = '1.0.0.M4'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
@@ -59,7 +56,7 @@ configurations {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def tomcatVersion = '7.0.27'
|
||||
def tomcatVersion = '7.0.29'
|
||||
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
|
||||
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
|
||||
tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
|
||||
@@ -72,17 +69,13 @@ dependencies {
|
||||
)
|
||||
|
||||
compile(
|
||||
[group: 'javax.servlet', name: 'jstl', version: '1.2'],
|
||||
|
||||
[group: 'org.springframework', name: 'spring-core', version: springVersion],
|
||||
[group: 'org.springframework', name: 'spring-aspects', version: springVersion],
|
||||
[group: 'org.springframework', name: 'spring-web', version: springVersion],
|
||||
[group: 'org.springframework', name: 'spring-webmvc', version: springVersion],
|
||||
[group: 'org.springframework.security', name: 'spring-security-core', version: springSecurityVersion],
|
||||
[group: 'org.springframework.security', name: 'spring-security-web', version: springSecurityVersion],
|
||||
[group: 'org.springframework.security', name: 'spring-security-config', version: springSecurityVersion],
|
||||
[group: 'org.springframework.security', name: 'spring-security-taglibs', version: springSecurityVersion],
|
||||
[group: 'org.aspectj', name: 'aspectjrt', version: '1.6.11.RELEASE'],
|
||||
[group: 'org.aspectj', name: 'aspectjrt', version: '1.6.12.RELEASE'],
|
||||
|
||||
[group: 'javax.validation', name: 'validation-api', version: '1.0.0.GA'],
|
||||
[group: 'org.hibernate', name: 'hibernate-validator', version: hibernateValidatorVersion],
|
||||
@@ -105,13 +98,14 @@ dependencies {
|
||||
[group: 'org.apache.commons', name: 'commons-email', version: '1.2'],
|
||||
[group: 'commons-lang', name: 'commons-lang', version: '2.4'],
|
||||
|
||||
[group: 'org.slf4j', name: 'slf4j-api', version: '1.6.4'],
|
||||
[group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.6.4'],
|
||||
[group: 'org.slf4j', name: 'slf4j-api', version: '1.6.6'],
|
||||
[group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.6.6'],
|
||||
|
||||
[group: 'ch.qos.logback', name: 'logback-core', version: '1.0.1'],
|
||||
[group: 'ch.qos.logback', name: 'logback-classic', version: '1.0.0'],
|
||||
[group: 'ch.qos.logback', name: 'logback-core', version: '1.0.6'],
|
||||
[group: 'ch.qos.logback', name: 'logback-classic', version: '1.0.6'],
|
||||
|
||||
[group: 'mysql', name: 'mysql-connector-java', version: '5.1.18'],
|
||||
[group: 'mysql', name: 'mysql-connector-java', version: '5.1.21'],
|
||||
[group: 'org.apache.tomcat', name: 'tomcat-jdbc', version: '7.0.29'],
|
||||
|
||||
[group: 'pentaho-reporting-engine', name: 'pentaho-reporting-engine-classic-core', version: '3.8.3-GA'],
|
||||
[group: 'pentaho-reporting-engine', name: 'pentaho-reporting-engine-classic-extensions', version: '3.8.3-GA'],
|
||||
|
||||
+3
-3
@@ -27,6 +27,7 @@ import org.mifosng.platform.api.data.ResultsetDataRow;
|
||||
import org.mifosng.platform.exceptions.AdditionalFieldsNotFoundException;
|
||||
import org.mifosng.platform.exceptions.PlatformDataIntegrityException;
|
||||
import org.mifosng.platform.exceptions.ReportNotFoundException;
|
||||
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
|
||||
import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
|
||||
import org.pentaho.reporting.engine.classic.core.MasterReport;
|
||||
import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
|
||||
@@ -46,15 +47,14 @@ import org.springframework.stereotype.Service;
|
||||
public class ReadExtraDataAndReportingServiceImpl implements
|
||||
ReadExtraDataAndReportingService {
|
||||
|
||||
private final static Logger logger = LoggerFactory
|
||||
.getLogger(ReadExtraDataAndReportingServiceImpl.class);
|
||||
private final static Logger logger = LoggerFactory.getLogger(ReadExtraDataAndReportingServiceImpl.class);
|
||||
|
||||
private final DataSource dataSource;
|
||||
private final String reportingMetaDataDB;
|
||||
private Boolean noPentaho = false;
|
||||
|
||||
@Autowired
|
||||
public ReadExtraDataAndReportingServiceImpl(final DataSource dataSource) {
|
||||
public ReadExtraDataAndReportingServiceImpl(final TenantAwareRoutingDataSource dataSource) {
|
||||
// kick off pentaho reports server
|
||||
ClassicEngineBoot.getInstance().start();
|
||||
noPentaho = false;
|
||||
|
||||
+5
-6
@@ -6,8 +6,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
@@ -23,33 +21,34 @@ import org.mifosng.platform.client.domain.NoteEnumerations;
|
||||
import org.mifosng.platform.exceptions.ClientNotFoundException;
|
||||
import org.mifosng.platform.exceptions.NoteNotFoundException;
|
||||
import org.mifosng.platform.infrastructure.JdbcSupport;
|
||||
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
|
||||
import org.mifosng.platform.organisation.service.OfficeReadPlatformService;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.mifosng.platform.user.domain.AppUser;
|
||||
import org.mifosng.platform.user.service.AppUserReadPlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ClientReadPlatformServiceImpl implements ClientReadPlatformService {
|
||||
|
||||
private final SimpleJdbcTemplate jdbcTemplate;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
private final OfficeReadPlatformService officeReadPlatformService;
|
||||
private final AppUserReadPlatformService appUserReadPlatformService;
|
||||
|
||||
@Autowired
|
||||
public ClientReadPlatformServiceImpl(final PlatformSecurityContext context,
|
||||
final DataSource dataSource,
|
||||
final TenantAwareRoutingDataSource dataSource,
|
||||
final OfficeReadPlatformService officeReadPlatformService,
|
||||
final AppUserReadPlatformService appUserReadPlatformService) {
|
||||
this.context = context;
|
||||
this.officeReadPlatformService = officeReadPlatformService;
|
||||
this.appUserReadPlatformService = appUserReadPlatformService;
|
||||
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
private String generateOfficeIdInClause(List<OfficeData> offices) {
|
||||
|
||||
+5
-6
@@ -4,27 +4,26 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.mifosng.platform.api.data.CurrencyData;
|
||||
import org.mifosng.platform.infrastructure.JdbcSupport;
|
||||
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.mifosng.platform.user.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class CurrencyReadPlatformServiceImpl implements CurrencyReadPlatformService {
|
||||
|
||||
private final SimpleJdbcTemplate jdbcTemplate;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
|
||||
@Autowired
|
||||
public CurrencyReadPlatformServiceImpl(final PlatformSecurityContext context, final DataSource dataSource) {
|
||||
public CurrencyReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
|
||||
this.context = context;
|
||||
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-6
@@ -4,29 +4,28 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.mifosng.platform.api.data.FundData;
|
||||
import org.mifosng.platform.exceptions.FundNotFoundException;
|
||||
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.mifosng.platform.user.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class FundReadPlatformServiceImpl implements FundReadPlatformService {
|
||||
|
||||
private final SimpleJdbcTemplate jdbcTemplate;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
|
||||
@Autowired
|
||||
public FundReadPlatformServiceImpl(final PlatformSecurityContext context,
|
||||
final DataSource dataSource) {
|
||||
final TenantAwareRoutingDataSource dataSource) {
|
||||
this.context = context;
|
||||
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
private static final class FundMapper implements RowMapper<FundData> {
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* A service for getting hold of the appropriate {@link DataSource} connection pool for the given tenant.
|
||||
*/
|
||||
public interface DataSourcePerTenantService {
|
||||
|
||||
DataSource retrieveTenantAwareDataSource();
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
/**
|
||||
* {@link RuntimeException} thrown when an invalid tenant identifier is used in request to platform.
|
||||
*
|
||||
* @see CustomRequestHeaderAuthenticationFilter
|
||||
*/
|
||||
public class InvalidTenantIdentiferException extends RuntimeException {
|
||||
|
||||
public InvalidTenantIdentiferException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class JdbcTenantDetailsService implements TenantDetailsService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
public JdbcTenantDetailsService(@Qualifier("tenantDataSourceJndi") final DataSource dataSource) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MifosPlatformTenant loadTenantById(final String tenantIdentifier) {
|
||||
|
||||
try {
|
||||
TenantMapper rm = new TenantMapper();
|
||||
String sql = "select id, name, schema_name as schemaName from tenants t where t.identifier like ?";
|
||||
|
||||
return this.jdbcTemplate.queryForObject(sql, rm, new Object[] {tenantIdentifier});
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
throw new InvalidTenantIdentiferException("The tenant identifier: " + tenantIdentifier + " is not valid.");
|
||||
}
|
||||
}
|
||||
|
||||
private static final class TenantMapper implements RowMapper<MifosPlatformTenant> {
|
||||
|
||||
@Override
|
||||
public MifosPlatformTenant mapRow(final ResultSet rs, final int rowNum) throws SQLException {
|
||||
|
||||
Long id = rs.getLong("id");
|
||||
String name = rs.getString("name");
|
||||
String schemaName = rs.getString("schemaName");
|
||||
|
||||
return new MifosPlatformTenant(id, name, schemaName);
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
public class MifosPlatformTenant {
|
||||
|
||||
private final Long id;
|
||||
private final String name;
|
||||
private final String schemaName;
|
||||
|
||||
public MifosPlatformTenant(Long id, String name, String schemaName) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.schemaName = schemaName;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSchemaName() {
|
||||
return schemaName;
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class TenantAwareBasicAuthenticationFilter extends BasicAuthenticationFilter {
|
||||
|
||||
@Autowired
|
||||
private TenantDetailsService tenantDetailsService;
|
||||
|
||||
private String tenantRequestHeader = "X-Mifos-Platform-TenantId";
|
||||
private boolean exceptionIfHeaderMissing = true;
|
||||
|
||||
public TenantAwareBasicAuthenticationFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) {
|
||||
super(authenticationManager, authenticationEntryPoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
final String tenantId = request.getHeader(tenantRequestHeader);
|
||||
|
||||
if (tenantId == null && exceptionIfHeaderMissing) {
|
||||
throw new PreAuthenticatedCredentialsNotFoundException(tenantRequestHeader + " header not found in request.");
|
||||
}
|
||||
|
||||
// check tenants database for tenantId
|
||||
MifosPlatformTenant tenant = this.tenantDetailsService.loadTenantById(tenantId);
|
||||
|
||||
ThreadLocalContextUtil.setTenant(tenant);
|
||||
|
||||
super.doFilter(req, res, chain);
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.datasource.AbstractDataSource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Service(value="tenantAwareDataSource")
|
||||
public class TenantAwareRoutingDataSource extends AbstractDataSource {
|
||||
|
||||
@Autowired
|
||||
private DataSourcePerTenantService dataSourcePerTenantService;
|
||||
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
return determineTargetDataSource().getConnection();
|
||||
}
|
||||
|
||||
private DataSource determineTargetDataSource() {
|
||||
return dataSourcePerTenantService.retrieveTenantAwareDataSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection getConnection(String username, String password) throws SQLException {
|
||||
return determineTargetDataSource().getConnection(username, password);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
public interface TenantDetailsService {
|
||||
|
||||
MifosPlatformTenant loadTenantById(String tenantId);
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ThreadLocalContextUtil {
|
||||
|
||||
private static final ThreadLocal<MifosPlatformTenant> contextHolder = new ThreadLocal<MifosPlatformTenant>();
|
||||
|
||||
public static void setTenant(final MifosPlatformTenant tenant) {
|
||||
Assert.notNull(tenant, "tenant cannot be null");
|
||||
contextHolder.set(tenant);
|
||||
}
|
||||
|
||||
public static MifosPlatformTenant getTenant() {
|
||||
return contextHolder.get();
|
||||
}
|
||||
|
||||
public static void clearTenant() {
|
||||
contextHolder.remove();
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
package org.mifosng.platform.infrastructure;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.tomcat.jdbc.pool.PoolConfiguration;
|
||||
import org.apache.tomcat.jdbc.pool.PoolProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class TomcatJdbcDataSourcePerTenantService implements DataSourcePerTenantService {
|
||||
|
||||
private final Map<Long, DataSource> tenantToDataSourceMap = new ConcurrentHashMap<Long, DataSource>(1);
|
||||
private final DataSource tenantDataSource;
|
||||
|
||||
@Autowired
|
||||
public TomcatJdbcDataSourcePerTenantService(final @Qualifier("tenantDataSourceJndi") DataSource tenantDataSource) {
|
||||
this.tenantDataSource = tenantDataSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSource retrieveTenantAwareDataSource() {
|
||||
|
||||
// default to tenant database datasource
|
||||
DataSource tenantDataSource = this.tenantDataSource;
|
||||
|
||||
MifosPlatformTenant tenant = ThreadLocalContextUtil.getTenant();
|
||||
if (tenant != null) {
|
||||
// if tenant information available switch to appropriate datasource for that tenant.
|
||||
if (this.tenantToDataSourceMap.containsKey(tenant.getId())) {
|
||||
tenantDataSource = this.tenantToDataSourceMap.get(tenant.getId());
|
||||
} else {
|
||||
tenantDataSource = createNewDataSourceFor(tenant);
|
||||
this.tenantToDataSourceMap.put(tenant.getId(), tenantDataSource);
|
||||
}
|
||||
}
|
||||
|
||||
return tenantDataSource;
|
||||
}
|
||||
|
||||
private DataSource createNewDataSourceFor(final MifosPlatformTenant tenant) {
|
||||
// see http://www.tomcatexpert.com/blog/2010/04/01/configuring-jdbc-pool-high-concurrency
|
||||
PoolConfiguration poolConfiguration = new PoolProperties();
|
||||
poolConfiguration.setDriverClassName("com.mysql.jdbc.Driver");
|
||||
poolConfiguration.setName(tenant.getSchemaName() + "_pool");
|
||||
poolConfiguration.setUrl("jdbc:mysql://localhost:3306/" + tenant.getSchemaName());
|
||||
poolConfiguration.setUsername("root");
|
||||
poolConfiguration.setPassword("mysql");
|
||||
|
||||
poolConfiguration.setInitialSize(5);
|
||||
poolConfiguration.setMaxActive(5);
|
||||
poolConfiguration.setMinIdle(1);
|
||||
poolConfiguration.setMaxIdle(4);
|
||||
|
||||
poolConfiguration.setSuspectTimeout(60);
|
||||
poolConfiguration.setTimeBetweenEvictionRunsMillis(30000);
|
||||
poolConfiguration.setMinEvictableIdleTimeMillis(60000);
|
||||
|
||||
poolConfiguration.setTestOnBorrow(true);
|
||||
poolConfiguration.setValidationQuery("SELECT 1");
|
||||
poolConfiguration.setValidationInterval(30000);
|
||||
|
||||
poolConfiguration.setRemoveAbandoned(true);
|
||||
poolConfiguration.setRemoveAbandonedTimeout(60);
|
||||
poolConfiguration.setLogAbandoned(true);
|
||||
poolConfiguration.setAbandonWhenPercentageFull(50);
|
||||
|
||||
poolConfiguration.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
|
||||
+ "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport");
|
||||
|
||||
return new org.apache.tomcat.jdbc.pool.DataSource(poolConfiguration);
|
||||
}
|
||||
}
|
||||
+5
-6
@@ -6,8 +6,6 @@ import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.mifosng.platform.api.data.CurrencyData;
|
||||
import org.mifosng.platform.api.data.EnumOptionData;
|
||||
@@ -19,6 +17,7 @@ import org.mifosng.platform.currency.service.CurrencyReadPlatformService;
|
||||
import org.mifosng.platform.exceptions.LoanProductNotFoundException;
|
||||
import org.mifosng.platform.fund.service.FundReadPlatformService;
|
||||
import org.mifosng.platform.infrastructure.JdbcSupport;
|
||||
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
|
||||
import org.mifosng.platform.loan.domain.AmortizationMethod;
|
||||
import org.mifosng.platform.loan.domain.InterestCalculationPeriodMethod;
|
||||
import org.mifosng.platform.loan.domain.InterestMethod;
|
||||
@@ -27,8 +26,8 @@ import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.mifosng.platform.user.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@@ -37,7 +36,7 @@ public class LoanProductReadPlatformServiceImpl implements
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final CurrencyReadPlatformService currencyReadPlatformService;
|
||||
private final SimpleJdbcTemplate jdbcTemplate;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final LoanDropdownReadPlatformService dropdownReadPlatformService;
|
||||
private final FundReadPlatformService fundReadPlatformService;
|
||||
|
||||
@@ -47,12 +46,12 @@ public class LoanProductReadPlatformServiceImpl implements
|
||||
final CurrencyReadPlatformService currencyReadPlatformService,
|
||||
final FundReadPlatformService fundReadPlatformService,
|
||||
final LoanDropdownReadPlatformService dropdownReadPlatformService,
|
||||
final DataSource dataSource) {
|
||||
final TenantAwareRoutingDataSource dataSource) {
|
||||
this.context = context;
|
||||
this.currencyReadPlatformService = currencyReadPlatformService;
|
||||
this.fundReadPlatformService = fundReadPlatformService;
|
||||
this.dropdownReadPlatformService = dropdownReadPlatformService;
|
||||
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-7
@@ -6,33 +6,31 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.mifosng.platform.api.data.OfficeData;
|
||||
import org.mifosng.platform.api.data.OfficeLookup;
|
||||
import org.mifosng.platform.exceptions.OfficeNotFoundException;
|
||||
import org.mifosng.platform.infrastructure.JdbcSupport;
|
||||
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.mifosng.platform.user.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class OfficeReadPlatformServiceImpl implements OfficeReadPlatformService {
|
||||
|
||||
private final SimpleJdbcTemplate jdbcTemplate;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
private final static String nameDecoratedBaseOnHierarchy = "concat(substring('........................................', 1, ((LENGTH(o.hierarchy) - LENGTH(REPLACE(o.hierarchy, '.', '')) - 1) * 4)), o.name)";
|
||||
|
||||
@Autowired
|
||||
public OfficeReadPlatformServiceImpl(final PlatformSecurityContext context,
|
||||
final DataSource dataSource) {
|
||||
public OfficeReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
|
||||
this.context = context;
|
||||
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
private static final class OfficeMapper implements RowMapper<OfficeData> {
|
||||
|
||||
+3
-1
@@ -7,11 +7,13 @@ import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Used in securityContext.xml as implementation of spring security's {@link UserDetailsService}.
|
||||
*/
|
||||
public class PlatformUserDetailsServiceImpl implements PlatformUserDetailsService {
|
||||
@Service(value="userDetailsService")
|
||||
public class TenantAwareJpaPlatformUserDetailsService implements PlatformUserDetailsService {
|
||||
|
||||
@Autowired
|
||||
private PlatformUserRepository platformUserRepository;
|
||||
+5
-6
@@ -9,42 +9,41 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.mifosng.platform.api.data.AppUserData;
|
||||
import org.mifosng.platform.api.data.OfficeData;
|
||||
import org.mifosng.platform.api.data.OfficeLookup;
|
||||
import org.mifosng.platform.api.data.RoleData;
|
||||
import org.mifosng.platform.exceptions.UserNotFoundException;
|
||||
import org.mifosng.platform.infrastructure.JdbcSupport;
|
||||
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
|
||||
import org.mifosng.platform.organisation.service.OfficeReadPlatformService;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.mifosng.platform.user.domain.AppUser;
|
||||
import org.mifosng.platform.user.domain.AppUserRepository;
|
||||
import org.mifosng.platform.user.domain.Role;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AppUserReadPlatformServiceImpl implements AppUserReadPlatformService {
|
||||
|
||||
private final SimpleJdbcTemplate jdbcTemplate;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
private final OfficeReadPlatformService officeReadPlatformService;
|
||||
private final RoleReadPlatformService roleReadPlatformService;
|
||||
private final AppUserRepository appUserRepository;
|
||||
|
||||
@Autowired
|
||||
public AppUserReadPlatformServiceImpl(final PlatformSecurityContext context, final DataSource dataSource,
|
||||
public AppUserReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource,
|
||||
final OfficeReadPlatformService officeReadPlatformService, final RoleReadPlatformService roleReadPlatformService,
|
||||
final AppUserRepository appUserRepository) {
|
||||
this.context = context;
|
||||
this.officeReadPlatformService = officeReadPlatformService;
|
||||
this.roleReadPlatformService = roleReadPlatformService;
|
||||
this.appUserRepository = appUserRepository;
|
||||
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-6
@@ -4,27 +4,26 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.mifosng.platform.api.data.PermissionData;
|
||||
import org.mifosng.platform.infrastructure.JdbcSupport;
|
||||
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.mifosng.platform.user.domain.AppUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PermissionReadPlatformServiceImpl implements PermissionReadPlatformService {
|
||||
|
||||
private final SimpleJdbcTemplate jdbcTemplate;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
|
||||
@Autowired
|
||||
public PermissionReadPlatformServiceImpl(final PlatformSecurityContext context, final DataSource dataSource) {
|
||||
public PermissionReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
|
||||
this.context = context;
|
||||
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-6
@@ -6,32 +6,31 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.mifosng.platform.api.data.RoleData;
|
||||
import org.mifosng.platform.exceptions.RoleNotFoundException;
|
||||
import org.mifosng.platform.infrastructure.JdbcSupport;
|
||||
import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource;
|
||||
import org.mifosng.platform.security.PlatformSecurityContext;
|
||||
import org.mifosng.platform.user.domain.AppUser;
|
||||
import org.mifosng.platform.user.domain.Role;
|
||||
import org.mifosng.platform.user.domain.RoleRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class RoleReadPlatformServiceImpl implements RoleReadPlatformService {
|
||||
|
||||
private final SimpleJdbcTemplate jdbcTemplate;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final PlatformSecurityContext context;
|
||||
private final RoleRepository roleRepository;
|
||||
|
||||
@Autowired
|
||||
public RoleReadPlatformServiceImpl(final PlatformSecurityContext context, final DataSource dataSource, final RoleRepository roleRepository) {
|
||||
public RoleReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource, final RoleRepository roleRepository) {
|
||||
this.context = context;
|
||||
this.roleRepository = roleRepository;
|
||||
this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
||||
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
||||
|
||||
<persistence-unit name="jpa-pu" transaction-type="RESOURCE_LOCAL">
|
||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||
<properties>
|
||||
@@ -7,7 +10,7 @@
|
||||
<!--
|
||||
<property name="hibernate.hbm2ddl.auto" value="update"/>
|
||||
-->
|
||||
<property name="hibernate.jdbc.batch_size" value="200"/>
|
||||
<property name="hibernate.jdbc.batch_size" value="100"/>
|
||||
<property name="hibernate.order_inserts" value="true"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
|
||||
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
|
||||
xmlns:sec="http://www.springframework.org/schema/security"
|
||||
xmlns:tx="http://www.springframework.org/schema/tx"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
|
||||
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
|
||||
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
@@ -17,8 +15,8 @@
|
||||
|
||||
<tx:annotation-driven />
|
||||
|
||||
<context:component-scan base-package="org.mifosng.platform.rest, org.mifosng.platform.security, org.mifosng.platform.infrastructure,
|
||||
org.mifosng.platform.*.domain, org.mifosng.platform, org.mifosng.demo">
|
||||
<context:component-scan base-package="org.mifosng.platform.security, org.mifosng.platform.infrastructure,
|
||||
org.mifosng.platform.*.domain, org.mifosng.platform">
|
||||
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation" />
|
||||
</context:component-scan>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
|
||||
|
||||
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
|
||||
<property name="dataSource" ref="dataSource" />
|
||||
<property name="dataSource" ref="tenantAwareDataSource" />
|
||||
<property name="persistenceUnitName" value="jpa-pu" />
|
||||
<property name="jpaVendorAdapter">
|
||||
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
|
||||
@@ -23,14 +23,5 @@
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory" />
|
||||
</bean>
|
||||
|
||||
<jee:jndi-lookup jndi-name="java:comp/env/jdbc/mifosng" id="dataSource" />
|
||||
|
||||
<!--
|
||||
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
|
||||
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
|
||||
<property name="url" value="jdbc:mysql://localhost:3306/mifosngprovider" />
|
||||
<property name="username" value="root" />
|
||||
<property name="password" value="mysql" />
|
||||
</bean>
|
||||
-->
|
||||
<jee:jndi-lookup jndi-name="java:comp/env/jdbc/mifosplatform-tenants" id="tenantDataSourceJndi" />
|
||||
</beans>
|
||||
@@ -7,15 +7,25 @@
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
|
||||
|
||||
<http create-session="stateless" use-expressions="true" pattern="/api/**" realm="Mifos Platform API">
|
||||
<intercept-url pattern="/api/*/authentication" access="permitAll" method="POST" requires-channel="https" />
|
||||
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" method="GET" requires-channel="https" />
|
||||
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" method="POST" requires-channel="https"/>
|
||||
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" method="PUT" requires-channel="https"/>
|
||||
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" method="DELETE" requires-channel="https"/>
|
||||
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" method="HEAD" requires-channel="https"/>
|
||||
<http-basic />
|
||||
<http create-session="stateless" use-expressions="true" pattern="/api/**" entry-point-ref="basicAuthenticationEntryPoint">
|
||||
<intercept-url pattern="/api/*/authentication" access="permitAll" method="POST" requires-channel="http" />
|
||||
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" method="GET" requires-channel="http" />
|
||||
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" method="POST" requires-channel="http"/>
|
||||
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" method="PUT" requires-channel="http"/>
|
||||
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" method="DELETE" requires-channel="http"/>
|
||||
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" method="HEAD" requires-channel="http"/>
|
||||
|
||||
<custom-filter after="SECURITY_CONTEXT_FILTER" ref="basicAuthenticationProcessingFilter" />
|
||||
</http>
|
||||
|
||||
<beans:bean id="basicAuthenticationEntryPoint" class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
|
||||
<beans:property name="realmName" value="Mifos Platform API" />
|
||||
</beans:bean>
|
||||
|
||||
<beans:bean id="basicAuthenticationProcessingFilter" class="org.mifosng.platform.infrastructure.TenantAwareBasicAuthenticationFilter">
|
||||
<beans:constructor-arg ref="authenticationManager" />
|
||||
<beans:constructor-arg ref="basicAuthenticationEntryPoint" />
|
||||
</beans:bean>
|
||||
|
||||
<beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
|
||||
<beans:constructor-arg value="256"/>
|
||||
@@ -25,8 +35,6 @@
|
||||
<beans:property name="userPropertyToUse" value="id"/>
|
||||
</beans:bean>
|
||||
|
||||
<beans:bean id="userDetailsService" class="org.mifosng.platform.security.PlatformUserDetailsServiceImpl" />
|
||||
|
||||
<beans:bean id="customAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
|
||||
<beans:property name="userDetailsService" ref="userDetailsService" />
|
||||
<beans:property name="passwordEncoder" ref="passwordEncoder" />
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</appender>
|
||||
|
||||
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>${catalina.base}/logs/mifosng-provider.log</file>
|
||||
<file>${catalina.home}/logs/mifos-platform.log</file>
|
||||
<append>true</append>
|
||||
<!-- encoders are assigned the type
|
||||
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Context>
|
||||
<ResourceLink name="jdbc/mifosng" global="jdbc/mifosng" type="javax.sql.DataSource" />
|
||||
<ResourceLink name="jdbc/mifosplatform-tenants" global="jdbc/mifosplatform-tenants" type="javax.sql.DataSource" />
|
||||
</Context>
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
|
||||
http://www.springframework.org/schema/webflow-config
|
||||
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<!-- The controllers are autodetected POJOs labeled with the @Controller annotation. -->
|
||||
<context:component-scan base-package="org.mifosng.platform.security, org.mifosng.platform.infrastructure" use-default-filters="false">
|
||||
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
|
||||
</context:component-scan>
|
||||
|
||||
<bean id="mvcConversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
|
||||
|
||||
<!-- Turns on support for mapping requests to Spring MVC @Controller methods (DefaultAnnotationHandler is added to list of handlers)
|
||||
Also registers default Formatters and Validators for use across all @Controllers -->
|
||||
<mvc:annotation-driven conversion-service="mvcConversionService"/>
|
||||
|
||||
<mvc:default-servlet-handler />
|
||||
|
||||
<mvc:resources location="/WEB-INF/static/" mapping="/resources/**" cache-period="31556926"/>
|
||||
|
||||
<mvc:view-controller path="/index" view-name="index"/>
|
||||
<mvc:view-controller path="/home" view-name="home"/>
|
||||
<mvc:view-controller path="/login" view-name="login"/>
|
||||
<mvc:view-controller path="/logout" view-name="logout"/>
|
||||
|
||||
<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
|
||||
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||
<property name="prefix" value="/WEB-INF/views/"/>
|
||||
<property name="suffix" value=".jsp"/>
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -5,12 +5,12 @@
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
id="mifosng-platform-provider" version="2.5">
|
||||
|
||||
<display-name>MifosNg - Platform</display-name>
|
||||
<display-name>Mifos Platform</display-name>
|
||||
<description>A provider of microfinance services which applications can consume once authenticated and authorized.</description>
|
||||
|
||||
<context-param>
|
||||
<param-name>webAppRootKey</param-name>
|
||||
<param-value>mifosngserver.root</param-value>
|
||||
<param-value>mifosplatform.root</param-value>
|
||||
</context-param>
|
||||
|
||||
<context-param>
|
||||
@@ -28,26 +28,10 @@
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!--
|
||||
<filter>
|
||||
<filter-name>filterChainProxy</filter-name>
|
||||
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>filterChainProxy</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
-->
|
||||
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
|
||||
<listener>
|
||||
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
|
||||
</listener>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>jersey-serlvet</servlet-name>
|
||||
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
|
||||
@@ -77,30 +61,4 @@
|
||||
<servlet-name>jersey-serlvet</servlet-name>
|
||||
<url-pattern>/api/v1/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>dispatcher</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/spring/webmvc-config.xml</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>dispatcher</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<jsp-config>
|
||||
<jsp-property-group>
|
||||
<url-pattern>*.jsp</url-pattern>
|
||||
<trim-directive-whitespaces>true</trim-directive-whitespaces>
|
||||
</jsp-property-group>
|
||||
</jsp-config>
|
||||
|
||||
<session-config>
|
||||
<session-timeout>20</session-timeout>
|
||||
</session-config>
|
||||
</web-app>
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Context>
|
||||
<Resource type="javax.sql.DataSource"
|
||||
name="jdbc/mifosng"
|
||||
name="jdbc/mifosplatform-tenants"
|
||||
driverClassName="com.mysql.jdbc.Driver"
|
||||
url="jdbc:mysql://localhost:3306/mifosngprovider"
|
||||
url="jdbc:mysql://localhost:3306/mifosplatform-tenants"
|
||||
username="root"
|
||||
password="mysql"
|
||||
validationQuery="select 1"
|
||||
|
||||
Reference in New Issue
Block a user