I can create a secure, multi-tenant web app with Grails by :
- setup spring security plugin,
- setup Multi-tenant plugin (via multi-tenant install and multi-tenant-spring-security)
-
update config.groovy :
tenant {
mode = “multiTenant”
resolver.type = “springSecurity”
} -
add : Integer userTenntId in User domain
- add a domain class for tenant Organization
- associate the tenants with Organization
- Edit BootStrap.groovy.
Everything works fine in multi-tenant mode, but how to use mode = “singleTenant” ?
This configuration sound not working :
tenant {
mode = “singleTenant”
resolver.type = “springSecurity”
}
Edit :
I try this config :
tenant {
mode = "singleTenant"
resolver.type = "springSecurity"
datasourceResolver.type = "config"
dataSourceTenantMap {
t1 = "jdbc:hsqldb:file:custFoo"
t2 = "jdbc:hsqldb:file:custBar"
}
}
But I get :
ERROR errors.GrailsExceptionResolver - Executing action [list] of controller [org.example.TicketController] caused exception: java.lang.StackOverflowError
and :
Caused by: java.lang.StackOverflowError
at org.grails.multitenant.springsecurity.SpringSecurityCurrentTenant.getTenantIdFromSpringSecurity(SpringSecurityCurrentTenant.groovy:50)
at org.grails.multitenant.springsecurity.SpringSecurityCurrentTenant.this$2$getTenantIdFromSpringSecurity(SpringSecurityCurrentTenant.groovy)
at org.grails.multitenant.springsecurity.SpringSecurityCurrentTenant$this$2$getTenantIdFromSpringSecurity.callCurrent(Unknown Source)
at org.grails.multitenant.springsecurity.SpringSecurityCurrentTenant.get(SpringSecurityCurrentTenant.groovy:41)
at com.infusion.tenant.spring.TenantBeanContainer.getBean(TenantBeanContainer.java:53)
at com.infusion.tenant.spring.TenantMethodInterceptor.invoke(TenantMethodInterceptor.java:32)
at $Proxy14.getConnection(Unknown Source)
I’m still testing the multi tenant plugin (core) in singleTenant mode but it’s already running altho not tested throughlly.
Here are the steps:
1- install spring security plugin, run grails s2-quickstart to set up the roles
2- Install multi-tenant-ehcache plugin and change your cache.provider_class in Datasource.groovy to:
cache.provider_class = ‘grails.plugin.multitenant.ehcache.cache.MultiTenantEhCacheProvider’
3- Install multi tenant (core) plugin and set up the datasource resolver plus the dns resolver i did it in a static way. Plus altho in the plugin doc says we can configure the dataSoruceTenantMap like this:
dataSourceTenantMap {
t1 = “jdbc:mysql://localhost/ets_dev1”
t2 = “jdbc:mysql://localhost/ets_dev2”
}
didnt worked for me so i used the jndi option through grails.naming.entries in the config:
/** Config.groovy **/
grails.naming.entries = [
“jdbc/lh_dev1”: [
type: “javax.sql.DataSource”,
auth: “Container”,
description: “My data source”,
driverClassName: “com.mysql.jdbc.Driver”,
url: “jdbc:mysql://localhost:3306/lh_dev1”,
username: “xxx”,
password: “xxx”,
maxActive: “100”,
maxIdle: “30”,
maxWait: “10000”
],
“jdbc/lh_dev2”: [
type: “javax.sql.DataSource”,
auth: “Container”,
description: “My data source”,
driverClassName: “com.mysql.jdbc.Driver”,
url: “jdbc:mysql://localhost:3306/lh_dev2”,
username: “xxx”,
password: “xxx”,
maxActive: “100”,
maxIdle: “30”,
maxWait: “10000”
]
]
//MultiTenant plugin configuration
tenant{
At this point you will have 2 domains linked with 2 diferent databases once u click for example:
http://lh_dev1:8080/myProject –> it will open your project db
lh_dev1
http://lh_dev2:8080/myProject –> it will open your project db
lh_dev2
each tenant (client) has his own database.
4- Install multi-tenant-spring-security plugin and follow this steps(note i didnt implemented the security plugin yet once i do i will post the results):
In Config.groovy, your tenant resolver property should look like this:
You will also need to add the following field to your Spring-Security User Domain Class
Integer userTenantId
Final Issues –>
Every time we fire up grails he will only do a create/update on the default database all the others will remain clean since i still dont know how to solve this problem so i simple exported the default database structure to all my other tenants database.
Finally i didnt do the @MultiTenant Annoation on the domains because i’m working with diferent database didnt saw the point of injecting the tenantid since every db has his own personal records.