Merge pull request #350 from stianst/constraints

Enforce that realm name is unique in model
This commit is contained in:
Stian Thorgersen 2014-04-29 10:44:42 +01:00
commit 1fa019e9dd
21 changed files with 193 additions and 67 deletions

View file

@ -7,6 +7,8 @@ public interface AuditProvider extends AuditListener {
public EventQuery createQuery(); public EventQuery createQuery();
public void clear();
public void clear(String realmId); public void clear(String realmId);
public void clear(String realmId, long olderThan); public void clear(String realmId, long olderThan);

View file

@ -28,6 +28,12 @@ public class JpaAuditProvider implements AuditProvider {
return new JpaEventQuery(em); return new JpaEventQuery(em);
} }
@Override
public void clear() {
beginTx();
em.createQuery("delete from EventEntity").executeUpdate();
}
@Override @Override
public void clear(String realmId) { public void clear(String realmId) {
beginTx(); beginTx();

View file

@ -1,6 +1,5 @@
package org.keycloak.audit.mongo; package org.keycloak.audit.mongo;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject; import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection; import com.mongodb.DBCollection;
import com.mongodb.DBObject; import com.mongodb.DBObject;
@ -27,6 +26,11 @@ public class MongoAuditProvider implements AuditProvider {
return new MongoEventQuery(audit); return new MongoEventQuery(audit);
} }
@Override
public void clear() {
audit.remove(new BasicDBObject());
}
@Override @Override
public void clear(String realmId) { public void clear(String realmId) {
audit.remove(new BasicDBObject("realmId", realmId)); audit.remove(new BasicDBObject("realmId", realmId));

View file

@ -34,8 +34,7 @@ public abstract class AbstractAuditProviderTest {
@After @After
public void after() { public void after() {
provider.clear("realmId"); provider.clear();
provider.clear("realmId2");
provider.close(); provider.close();
factory.close(); factory.close();
} }

View file

@ -39,6 +39,4 @@ public interface ApplicationModel extends RoleContainerModel, ClientModel {
boolean isBearerOnly(); boolean isBearerOnly();
void setBearerOnly(boolean only); void setBearerOnly(boolean only);
void addScope(RoleModel role);
} }

View file

@ -245,11 +245,6 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
em.flush(); em.flush();
} }
@Override
public void addScope(RoleModel role) {
realm.addScopeMapping(this, role);
}
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == null) return false; if (o == null) return false;
if (o == this) return true; if (o == this) return true;

View file

@ -4,6 +4,7 @@ import org.hibernate.exception.ConstraintViolationException;
import org.keycloak.models.ModelException; import org.keycloak.models.ModelException;
import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.ModelDuplicateException;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -33,6 +34,8 @@ public class PersistenceExceptionConverter implements InvocationHandler {
Throwable c = e.getCause(); Throwable c = e.getCause();
if (c.getCause() != null && c.getCause() instanceof ConstraintViolationException) { if (c.getCause() != null && c.getCause() instanceof ConstraintViolationException) {
throw new ModelDuplicateException(c); throw new ModelDuplicateException(c);
} if (c instanceof EntityExistsException) {
throw new ModelDuplicateException(c);
} else { } else {
throw new ModelException(c); throw new ModelException(c);
} }

View file

@ -35,7 +35,7 @@ public class RealmEntity {
@Id @Id
protected String id; protected String id;
//@Column(unique = true) @Column(unique = true)
protected String name; protected String name;
protected boolean enabled; protected boolean enabled;

View file

@ -179,17 +179,21 @@ public class MongoStoreImpl implements MongoStore {
try { try {
dbCollection.insert(dbObject); dbCollection.insert(dbObject);
} catch (MongoException e) { } catch (MongoException e) {
if (e instanceof MongoException.DuplicateKey) { throw convertException(e);
throw new ModelDuplicateException(e);
} else {
throw new ModelException(e);
}
} }
// Treat object as created in this transaction (It is already submited to transaction) // Treat object as created in this transaction (It is already submited to transaction)
context.addCreatedEntity(entity); context.addCreatedEntity(entity);
} }
public static ModelException convertException(MongoException e) {
if (e instanceof MongoException.DuplicateKey) {
return new ModelDuplicateException(e);
} else {
return new ModelException(e);
}
}
@Override @Override
public void updateEntity(final MongoIdentifiableEntity entity, MongoStoreInvocationContext context) { public void updateEntity(final MongoIdentifiableEntity entity, MongoStoreInvocationContext context) {
MongoTask fullUpdateTask = new MongoTask() { MongoTask fullUpdateTask = new MongoTask() {

View file

@ -123,6 +123,7 @@ public class ApplicationAdapter extends ClientAdapter<ApplicationEntity> impleme
roleEntity.setApplicationId(getId()); roleEntity.setApplicationId(getId());
getMongoStore().insertEntity(roleEntity, invocationContext); getMongoStore().insertEntity(roleEntity, invocationContext);
return new RoleAdapter(getRealm(), roleEntity, this, invocationContext); return new RoleAdapter(getRealm(), roleEntity, this, invocationContext);
} }
@ -159,11 +160,6 @@ public class ApplicationAdapter extends ClientAdapter<ApplicationEntity> impleme
return result; return result;
} }
@Override
public void addScope(RoleModel role) {
getMongoStore().pushItemToList(getMongoEntity(), "scopeIds", role.getId(), true, invocationContext);
}
@Override @Override
public Set<RoleModel> getApplicationScopeMappings(ClientModel client) { public Set<RoleModel> getApplicationScopeMappings(ClientModel client) {
Set<RoleModel> result = new HashSet<RoleModel>(); Set<RoleModel> result = new HashSet<RoleModel>();

View file

@ -46,10 +46,6 @@ public class MongoKeycloakSession implements KeycloakSession {
@Override @Override
public RealmModel createRealm(String id, String name) { public RealmModel createRealm(String id, String name) {
if (getRealm(id) != null) {
throw new IllegalStateException("Realm with id '" + id + "' already exists");
}
RealmEntity newRealm = new RealmEntity(); RealmEntity newRealm = new RealmEntity();
newRealm.setId(id); newRealm.setId(id);
newRealm.setName(name); newRealm.setName(name);

View file

@ -1,7 +1,9 @@
package org.keycloak.models.mongo.keycloak.adapters; package org.keycloak.models.mongo.keycloak.adapters;
import com.mongodb.MongoException;
import org.keycloak.models.KeycloakTransaction; import org.keycloak.models.KeycloakTransaction;
import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext; import org.keycloak.models.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.mongo.impl.MongoStoreImpl;
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -35,7 +37,11 @@ public class MongoKeycloakTransaction implements KeycloakTransaction {
throw new IllegalStateException("Can't commit as transaction marked for rollback"); throw new IllegalStateException("Can't commit as transaction marked for rollback");
} }
try {
invocationContext.commit(); invocationContext.commit();
} catch (MongoException e) {
throw MongoStoreImpl.convertException(e);
}
} }
@Override @Override

View file

@ -541,6 +541,7 @@ public class RealmAdapter extends AbstractMongoAdapter<RealmEntity> implements R
roleEntity.setRealmId(getId()); roleEntity.setRealmId(getId());
getMongoStore().insertEntity(roleEntity, invocationContext); getMongoStore().insertEntity(roleEntity, invocationContext);
return new RoleAdapter(this, roleEntity, this, invocationContext); return new RoleAdapter(this, roleEntity, this, invocationContext);
} }

View file

@ -23,7 +23,7 @@ import java.util.Set;
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/ */
@MongoCollection(collectionName = "realms") @MongoCollection(collectionName = "realms")
//@MongoIndex(fields = { "name" }, unique = true) @MongoIndex(fields = { "name" }, unique = true)
public class RealmEntity extends AbstractMongoIdentifiableEntity implements MongoEntity { public class RealmEntity extends AbstractMongoIdentifiableEntity implements MongoEntity {
private String name; private String name;
@ -422,5 +422,8 @@ public class RealmEntity extends AbstractMongoIdentifiableEntity implements Mong
// Remove all applications of this realm // Remove all applications of this realm
context.getMongoStore().removeEntities(ApplicationEntity.class, query, context); context.getMongoStore().removeEntities(ApplicationEntity.class, query, context);
// Remove all clients of this realm
context.getMongoStore().removeEntities(OAuthClientEntity.class, query, context);
} }
} }

View file

@ -6,11 +6,15 @@ import java.io.InputStream;
import java.util.Set; import java.util.Set;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel; import org.keycloak.models.RoleModel;
import org.keycloak.models.Config;
import org.keycloak.provider.ProviderSession; import org.keycloak.provider.ProviderSession;
import org.keycloak.provider.ProviderSessionFactory; import org.keycloak.provider.ProviderSessionFactory;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
@ -24,23 +28,41 @@ import org.keycloak.util.JsonSerialization;
*/ */
public class AbstractModelTest { public class AbstractModelTest {
protected KeycloakSessionFactory factory; protected static KeycloakSessionFactory factory;
protected static ProviderSessionFactory providerSessionFactory;
protected KeycloakSession identitySession; protected KeycloakSession identitySession;
protected RealmManager realmManager; protected RealmManager realmManager;
protected ProviderSessionFactory providerSessionFactory;
protected ProviderSession providerSession; protected ProviderSession providerSession;
@BeforeClass
public static void beforeClass() {
factory = KeycloakApplication.createSessionFactory();
providerSessionFactory = KeycloakApplication.createProviderSessionFactory();
KeycloakSession identitySession = factory.createSession();
try {
identitySession.getTransaction().begin();
new ApplianceBootstrap().bootstrap(identitySession, "/auth");
identitySession.getTransaction().commit();
} finally {
identitySession.close();
}
}
@AfterClass
public static void afterClass() {
providerSessionFactory.close();
factory.close();
}
@Before @Before
public void before() throws Exception { public void before() throws Exception {
factory = KeycloakApplication.createSessionFactory();
identitySession = factory.createSession(); identitySession = factory.createSession();
identitySession.getTransaction().begin(); identitySession.getTransaction().begin();
realmManager = new RealmManager(identitySession); realmManager = new RealmManager(identitySession);
providerSessionFactory = KeycloakApplication.createProviderSessionFactory();
providerSession = providerSessionFactory.createSession(); providerSession = providerSessionFactory.createSession();
new ApplianceBootstrap().bootstrap(identitySession, "/auth");
} }
@After @After
@ -48,12 +70,35 @@ public class AbstractModelTest {
identitySession.getTransaction().commit(); identitySession.getTransaction().commit();
providerSession.close(); providerSession.close();
identitySession.close(); identitySession.close();
providerSessionFactory.close();
factory.close(); identitySession = factory.createSession();
try {
identitySession.getTransaction().begin();
RealmManager rm = new RealmManager(identitySession);
for (RealmModel realm : identitySession.getRealms()) {
if (!realm.getName().equals(Config.getAdminRealm())) {
rm.removeRealm(realm);
}
}
identitySession.getTransaction().commit();
} finally {
identitySession.close();
}
} }
protected void commit() { protected void commit() {
commit(false);
}
protected void commit(boolean rollback) {
if (rollback) {
identitySession.getTransaction().rollback();
} else {
identitySession.getTransaction().commit(); identitySession.getTransaction().commit();
}
identitySession.close(); identitySession.close();
identitySession = factory.createSession(); identitySession = factory.createSession();
identitySession.getTransaction().begin(); identitySession.getTransaction().begin();
@ -68,8 +113,6 @@ public class AbstractModelTest {
os.write(c); os.write(c);
} }
byte[] bytes = os.toByteArray(); byte[] bytes = os.toByteArray();
System.out.println(new String(bytes));
return JsonSerialization.readValue(bytes, RealmRepresentation.class); return JsonSerialization.readValue(bytes, RealmRepresentation.class);
} }

View file

@ -6,6 +6,7 @@ import org.junit.Test;
import org.junit.runners.MethodSorters; import org.junit.runners.MethodSorters;
import org.keycloak.models.ApplicationModel; import org.keycloak.models.ApplicationModel;
import org.keycloak.models.Constants; import org.keycloak.models.Constants;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.OAuthClientModel; import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RequiredCredentialModel;
@ -44,7 +45,6 @@ public class AdapterTest extends AbstractModelTest {
realmModel.setUpdateProfileOnInitialSocialLogin(true); realmModel.setUpdateProfileOnInitialSocialLogin(true);
realmModel.addDefaultRole("foo"); realmModel.addDefaultRole("foo");
System.out.println(realmModel.getId());
realmModel = realmManager.getRealm(realmModel.getId()); realmModel = realmManager.getRealm(realmModel.getId());
Assert.assertNotNull(realmModel); Assert.assertNotNull(realmModel);
Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100); Assert.assertEquals(realmModel.getAccessCodeLifespan(), 100);
@ -302,7 +302,7 @@ public class AdapterTest extends AbstractModelTest {
} }
String[] usernames = users.toArray(new String[users.size()]); String[] usernames = users.toArray(new String[users.size()]);
Arrays.sort(usernames); Arrays.sort(usernames);
Assert.assertArrayEquals(new String[] { "doublefirst", "doublelast"}, usernames); Assert.assertArrayEquals(new String[]{"doublefirst", "doublelast"}, usernames);
} }
{ {
@ -472,5 +472,67 @@ public class AdapterTest extends AbstractModelTest {
Assert.assertFalse(realmModel.hasRole(user, appBarRole)); Assert.assertFalse(realmModel.hasRole(user, appBarRole));
} }
// TODO: test scopes @Test
public void testScopes() throws Exception {
test1CreateRealm();
RoleModel realmRole = realmModel.addRole("realm");
ApplicationModel app1 = realmModel.addApplication("app1");
RoleModel appRole = app1.addRole("app");
ApplicationModel app2 = realmModel.addApplication("app2");
realmModel.addScopeMapping(app2, realmRole);
realmModel.addScopeMapping(app2, appRole);
OAuthClientModel client = realmModel.addOAuthClient("client");
realmModel.addScopeMapping(client, realmRole);
realmModel.addScopeMapping(client, appRole);
commit();
realmModel = identitySession.getRealmByName("JUGGLER");
app1 = realmModel.getApplicationByName("app1");
app2 = realmModel.getApplicationByName("app2");
client = realmModel.getOAuthClient("client");
Set<RoleModel> scopeMappings = realmModel.getScopeMappings(app2);
Assert.assertEquals(2, scopeMappings.size());
Assert.assertTrue(scopeMappings.contains(realmModel.getRole("realm")));
Assert.assertTrue(scopeMappings.contains(app1.getRole("app")));
scopeMappings = realmModel.getScopeMappings(client);
Assert.assertEquals(2, scopeMappings.size());
Assert.assertTrue(scopeMappings.contains(realmModel.getRole("realm")));
Assert.assertTrue(scopeMappings.contains(app1.getRole("app")));
}
@Test
public void testRealmNameCollisions() throws Exception {
test1CreateRealm();
commit();
// Try to create realm with duplicate name
try {
test1CreateRealm();
commit();
Assert.fail("Expected exception");
} catch (ModelDuplicateException e) {
}
commit(true);
// Ty to rename realm to duplicate name
realmModel = realmManager.createRealm("JUGGLER2");
commit();
realmModel = realmManager.getRealmByName("JUGGLER2");
try {
realmModel.setName("JUGGLER");
commit();
Assert.fail("Expected exception");
} catch (ModelDuplicateException e) {
}
commit(true);
}
} }

View file

@ -7,8 +7,10 @@ import javax.ws.rs.core.MultivaluedMap;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder; import org.junit.FixMethodOrder;
import org.junit.Test; import org.junit.Test;
import org.junit.runners.MethodSorters; import org.junit.runners.MethodSorters;
@ -29,22 +31,38 @@ import org.keycloak.authentication.AuthenticationProviderManager;
@FixMethodOrder(MethodSorters.NAME_ASCENDING) @FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class AuthProvidersLDAPTest extends AbstractModelTest { public class AuthProvidersLDAPTest extends AbstractModelTest {
private static LDAPEmbeddedServer embeddedServer;
private RealmModel realm; private RealmModel realm;
private AuthenticationManager am; private AuthenticationManager am;
private LDAPEmbeddedServer embeddedServer;
@Before @BeforeClass
@Override public static void beforeClass() {
public void before() throws Exception { AbstractModelTest.beforeClass();
super.before();
try { try {
this.embeddedServer = new LDAPEmbeddedServer(); embeddedServer = new LDAPEmbeddedServer();
this.embeddedServer.setup(); embeddedServer.setup();
this.embeddedServer.importLDIF("ldap/users.ldif"); embeddedServer.importLDIF("ldap/users.ldif");
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Error starting Embedded LDAP server.", e); throw new RuntimeException("Error starting Embedded LDAP server.", e);
} }
}
@AfterClass
public static void afterClass() {
AbstractModelTest.afterClass();
try {
embeddedServer.tearDown();
} catch (Exception e) {
throw new RuntimeException("Error starting Embedded LDAP server.", e);
}
}
@Before
public void before() throws Exception {
super.before();
// Create realm and configure ldap // Create realm and configure ldap
realm = realmManager.createRealm("realm"); realm = realmManager.createRealm("realm");
@ -55,17 +73,6 @@ public class AuthProvidersLDAPTest extends AbstractModelTest {
am = new AuthenticationManager(providerSession); am = new AuthenticationManager(providerSession);
} }
@After
@Override
public void after() throws Exception {
super.after();
try {
this.embeddedServer.tearDown();
} catch (Exception e) {
throw new RuntimeException("Error starting Embedded LDAP server.", e);
}
}
@Test @Test
public void testLdapAuthentication() { public void testLdapAuthentication() {
MultivaluedMap<String, String> formData = AuthProvidersExternalModelTest.createFormData("john", "password"); MultivaluedMap<String, String> formData = AuthProvidersExternalModelTest.createFormData("john", "password");

View file

@ -70,6 +70,7 @@ public class ModelTest extends AbstractModelTest {
private RealmModel importExport(RealmModel src, String copyName) { private RealmModel importExport(RealmModel src, String copyName) {
RealmRepresentation representation = ModelToRepresentation.toRepresentation(src); RealmRepresentation representation = ModelToRepresentation.toRepresentation(src);
representation.setRealm(copyName);
RealmModel copy = realmManager.createRealm(copyName); RealmModel copy = realmManager.createRealm(copyName);
realmManager.importRealm(representation, copy); realmManager.importRealm(representation, copy);
return realmManager.getRealm(copy.getId()); return realmManager.getRealm(copy.getId());

View file

@ -22,8 +22,8 @@ public class MultipleRealmsTest extends AbstractModelTest {
@Override @Override
public void before() throws Exception { public void before() throws Exception {
super.before(); super.before();
realm1 = identitySession.createRealm("id1", "realm1"); realm1 = realmManager.createRealm("id1", "realm1");
realm2 = identitySession.createRealm("id2", "realm2"); realm2 = realmManager.createRealm("id2", "realm2");
createObjects(realm1); createObjects(realm1);
createObjects(realm2); createObjects(realm2);
@ -93,7 +93,7 @@ public class MultipleRealmsTest extends AbstractModelTest {
realm.addRole("role2"); realm.addRole("role2");
app1.addRole("app1Role1"); app1.addRole("app1Role1");
app1.addScope(realm.getRole("role1")); realm.addScopeMapping(app1, realm.getRole("role1"));
realm.addOAuthClient("cl1"); realm.addOAuthClient("cl1");
} }

View file

@ -71,7 +71,7 @@ public class ApplianceBootstrap {
RoleModel adminRole = realm.getRole(AdminRoles.ADMIN); RoleModel adminRole = realm.getRole(AdminRoles.ADMIN);
adminConsole.addScope(adminRole); realm.addScopeMapping(adminConsole, adminRole);
UserModel adminUser = realm.addUser("admin"); UserModel adminUser = realm.addUser("admin");
adminUser.setEnabled(true); adminUser.setEnabled(true);

View file

@ -87,14 +87,14 @@ public class CompositeRoleTest {
final ApplicationModel realmComposite1Application = new ApplicationManager(manager).createApplication(realm, "REALM_COMPOSITE_1_APPLICATION"); final ApplicationModel realmComposite1Application = new ApplicationManager(manager).createApplication(realm, "REALM_COMPOSITE_1_APPLICATION");
realmComposite1Application.setEnabled(true); realmComposite1Application.setEnabled(true);
realmComposite1Application.addScope(realmComposite1); realm.addScopeMapping(realmComposite1Application, realmComposite1);
realmComposite1Application.setBaseUrl("http://localhost:8081/app"); realmComposite1Application.setBaseUrl("http://localhost:8081/app");
realmComposite1Application.setManagementUrl("http://localhost:8081/app/logout"); realmComposite1Application.setManagementUrl("http://localhost:8081/app/logout");
realmComposite1Application.setSecret("password"); realmComposite1Application.setSecret("password");
final ApplicationModel realmRole1Application = new ApplicationManager(manager).createApplication(realm, "REALM_ROLE_1_APPLICATION"); final ApplicationModel realmRole1Application = new ApplicationManager(manager).createApplication(realm, "REALM_ROLE_1_APPLICATION");
realmRole1Application.setEnabled(true); realmRole1Application.setEnabled(true);
realmRole1Application.addScope(realmRole1); realm.addScopeMapping(realmRole1Application, realmRole1);
realmRole1Application.setBaseUrl("http://localhost:8081/app"); realmRole1Application.setBaseUrl("http://localhost:8081/app");
realmRole1Application.setManagementUrl("http://localhost:8081/app/logout"); realmRole1Application.setManagementUrl("http://localhost:8081/app/logout");
realmRole1Application.setSecret("password"); realmRole1Application.setSecret("password");
@ -127,7 +127,7 @@ public class CompositeRoleTest {
appCompositeApplication.setManagementUrl("http://localhost:8081/app/logout"); appCompositeApplication.setManagementUrl("http://localhost:8081/app/logout");
appCompositeApplication.setSecret("password"); appCompositeApplication.setSecret("password");
final RoleModel appCompositeRole = appCompositeApplication.addRole("APP_COMPOSITE_ROLE"); final RoleModel appCompositeRole = appCompositeApplication.addRole("APP_COMPOSITE_ROLE");
appCompositeApplication.addScope(appRole2); realm.addScopeMapping(appCompositeApplication, appRole2);
appCompositeRole.addCompositeRole(realmRole1); appCompositeRole.addCompositeRole(realmRole1);
appCompositeRole.addCompositeRole(realmRole2); appCompositeRole.addCompositeRole(realmRole2);
appCompositeRole.addCompositeRole(realmRole3); appCompositeRole.addCompositeRole(realmRole3);