syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject [3/4] syncope git commit: [SYNCOPE-1143] Now connector instances require an admin realm, which is used to enforce access control on it for administrative purposes
Date Mon, 10 Jul 2017 16:36:00 GMT
http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
index f3ada03..5b7ec8e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
@@ -191,7 +191,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements
UserDAO {
             }
             if (authRealms == null || authRealms.isEmpty() || !authorized) {
                 throw new DelegatedAdministrationException(
-                        user.getRealm().getFullPath(), AnyTypeKind.USER, user.getKey());
+                        user.getRealm().getFullPath(), AnyTypeKind.USER.name(), user.getKey());
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
index 449b0f3..bd5a108 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
@@ -38,7 +38,7 @@ public abstract class AbstractAny<P extends PlainAttr<?>> extends
AbstractAnnota
 
     private static final long serialVersionUID = -2666540708092702810L;
 
-    @ManyToOne(fetch = FetchType.EAGER)
+    @ManyToOne(fetch = FetchType.EAGER, optional = false)
     private JPARealm realm;
 
     private String workflowId;

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
index c7da0ae..7678fc2 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
@@ -32,6 +32,7 @@ import javax.persistence.Enumerated;
 import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
 import javax.persistence.Lob;
+import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
@@ -41,6 +42,7 @@ import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
 import org.apache.syncope.core.persistence.api.entity.ConnInstance;
 import org.apache.syncope.core.persistence.api.entity.ConnPoolConf;
+import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.jpa.validation.entity.ConnInstanceCheck;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
@@ -57,6 +59,9 @@ public class JPAConnInstance extends AbstractGeneratedKeyEntity implements
ConnI
 
     private static final int DEFAULT_TIMEOUT = 10;
 
+    @ManyToOne(fetch = FetchType.EAGER, optional = false)
+    private JPARealm adminRealm;
+
     /**
      * URI identifying the local / remote ConnId location where the related connector bundle
is found.
      */
@@ -125,6 +130,17 @@ public class JPAConnInstance extends AbstractGeneratedKeyEntity implements
ConnI
     private JPAConnPoolConf poolConf;
 
     @Override
+    public Realm getAdminRealm() {
+        return adminRealm;
+    }
+
+    @Override
+    public void setAdminRealm(final Realm adminRealm) {
+        checkType(adminRealm, JPARealm.class);
+        this.adminRealm = (JPARealm) adminRealm;
+    }
+
+    @Override
     public String getLocation() {
         return location;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ConnInstanceTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ConnInstanceTest.java
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ConnInstanceTest.java
index b8eb01a..5020adb 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ConnInstanceTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ConnInstanceTest.java
@@ -23,18 +23,30 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.File;
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.ConnConfPropSchema;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.core.persistence.api.dao.ConnInstanceDAO;
 import org.apache.syncope.core.persistence.api.entity.ConnInstance;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
+import org.apache.syncope.core.spring.security.SyncopeAuthenticationDetails;
+import org.apache.syncope.core.spring.security.SyncopeGrantedAuthority;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.transaction.annotation.Transactional;
 
 @Transactional("Master")
@@ -45,21 +57,44 @@ public class ConnInstanceTest extends AbstractTest {
 
     @Test
     public void findAll() {
-        List<ConnInstance> connectors = connInstanceDAO.findAll();
-        assertNotNull(connectors);
-        assertFalse(connectors.isEmpty());
+        List<GrantedAuthority> authorities = CollectionUtils.collect(StandardEntitlement.values(),
+                new Transformer<String, GrantedAuthority>() {
+
+            @Override
+            public GrantedAuthority transform(final String entitlement) {
+                return new SyncopeGrantedAuthority(entitlement, SyncopeConstants.ROOT_REALM);
+            }
+        }, new ArrayList<GrantedAuthority>());
+
+        UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
+                new org.springframework.security.core.userdetails.User(
+                        "admin", "FAKE_PASSWORD", authorities), "FAKE_PASSWORD", authorities);
+        auth.setDetails(new SyncopeAuthenticationDetails("Master"));
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        try {
+            List<ConnInstance> connectors = connInstanceDAO.findAll();
+            assertNotNull(connectors);
+            assertFalse(connectors.isEmpty());
+        } finally {
+            SecurityContextHolder.getContext().setAuthentication(null);
+        }
     }
 
     @Test
     public void findById() {
-        ConnInstance connectorInstance = connInstanceDAO.find("88a7a819-dab5-46b4-9b90-0b9769eabdb8");
-
-        assertNotNull("findById did not work", connectorInstance);
-
+        ConnInstance connInstance = connInstanceDAO.find("88a7a819-dab5-46b4-9b90-0b9769eabdb8");
+        assertNotNull(connInstance);
         assertEquals("invalid connector name",
-                "net.tirasa.connid.bundles.soap.WebServiceConnector", connectorInstance.getConnectorName());
-
-        assertEquals("invalid bundle name", "net.tirasa.connid.bundles.soap", connectorInstance.getBundleName());
+                "net.tirasa.connid.bundles.soap.WebServiceConnector", connInstance.getConnectorName());
+        assertEquals("invalid bundle name", "net.tirasa.connid.bundles.soap", connInstance.getBundleName());
+
+        try {
+            connInstanceDAO.authFind("88a7a819-dab5-46b4-9b90-0b9769eabdb8");
+            fail();
+        } catch (DelegatedAdministrationException e) {
+            assertNotNull(e);
+        }
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
index 3fcf4ae..03b516d 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
@@ -39,6 +39,7 @@ import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
 import org.identityconnectors.framework.common.objects.ObjectClass;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -74,6 +75,13 @@ public class ResourceTest extends AbstractTest {
                 return "7f55b09c-b573-41dc-a9eb-ccd80bd3ea7a".equals(item.getKey());
             }
         }));
+
+        try {
+            resourceDAO.authFind("ws-target-resource-1");
+            fail();
+        } catch (DelegatedAdministrationException e) {
+            assertNotNull(e);
+        }
     }
 
     @Test
@@ -91,13 +99,6 @@ public class ResourceTest extends AbstractTest {
     }
 
     @Test
-    public void findAllByPriority() {
-        List<ExternalResource> resources = resourceDAO.findAllByPriority();
-        assertNotNull(resources);
-        assertFalse(resources.isEmpty());
-    }
-
-    @Test
     public void getConnObjectKey() {
         ExternalResource resource = resourceDAO.find("ws-target-resource-2");
         assertNotNull(resource);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 83bacf0..717535f 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -274,6 +274,18 @@ under the License.
   <SyncopeRole_entitlements entitlement="USER_SEARCH" role_id="Search for realm evenTwo"/>
   <SyncopeRole_Realm role_id="Search for realm evenTwo" realm_id="0679e069-7355-4b20-bd11-a5a0a5453c7c"/>
 
+  <SyncopeRole id="Connector and Resource for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="CONNECTOR_READ" role_id="Connector and Resource
for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="CONNECTOR_UPDATE" role_id="Connector and Resource
for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="CONNECTOR_DELETE" role_id="Connector and Resource
for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="CONNECTOR_LIST" role_id="Connector and Resource
for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="RESOURCE_READ" role_id="Connector and Resource
for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="RESOURCE_UPDATE" role_id="Connector and Resource
for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="RESOURCE_DELETE" role_id="Connector and Resource
for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="RESOURCE_LIST" role_id="Connector and Resource
for realm evenTwo"/>
+  <SyncopeRole_Realm role_id="Connector and Resource for realm evenTwo"
+                     realm_id="0679e069-7355-4b20-bd11-a5a0a5453c7c"/>
+
   <SyncopeUser id="1417acbe-cbf6-4277-9372-e75e04f97000" workflowId="4" status="active"
                password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
                realm_id="c5b75db1-fce7-470f-b780-3b9934d82a9d"
@@ -303,6 +315,7 @@ under the License.
                username="puccini" creator="admin" lastModifier="admin" 
                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"/>
   <SyncopeUser_SyncopeRole user_id="823074dc-d280-436d-a7dd-07399fae48ec" role_id="Search
for realm evenTwo"/>
+  <SyncopeUser_SyncopeRole user_id="823074dc-d280-436d-a7dd-07399fae48ec" role_id="Connector
and Resource for realm evenTwo"/>
   
   <SyncopeGroup id="37d15e4c-cdc1-460b-a591-8505c8133806" name="root"
                 realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
@@ -614,6 +627,7 @@ under the License.
   <GPlainAttrValue attribute_id="22690472-ed3f-4972-8979-4c9251fab044" id="e16765e6-f806-469e-ae34-1ddf56f2102a"
stringValue="r13"/>
 
   <ConnInstance id="88a7a819-dab5-46b4-9b90-0b9769eabdb8" displayName="ConnInstance100"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                 location="${connid.location}"
                 bundleName="net.tirasa.connid.bundles.soap"
                 connectorName="net.tirasa.connid.bundles.soap.WebServiceConnector"
@@ -625,6 +639,7 @@ under the License.
   <ConnInstance_capabilities connInstance_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8" capability="SEARCH"/>
 
   <ConnInstance id="5aa5b8be-7521-481a-9651-c557aea078c1" displayName="H2"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                 location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
                 bundleName="net.tirasa.connid.bundles.db.table"
                 connectorName="net.tirasa.connid.bundles.db.table.DatabaseTableConnector"
@@ -638,6 +653,7 @@ under the License.
   <ConnInstance_capabilities connInstance_id="5aa5b8be-7521-481a-9651-c557aea078c1" capability="SYNC"/>
 
   <ConnInstance id="5ffbb4ac-a8c3-4b44-b699-11b398a1ba08" displayName="ConnInstance102"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                 location="${connid.location}"
                 bundleName="net.tirasa.connid.bundles.soap"
                 connectorName="net.tirasa.connid.bundles.soap.WebServiceConnector"
@@ -650,6 +666,7 @@ under the License.
   <ConnInstance_capabilities connInstance_id="5ffbb4ac-a8c3-4b44-b699-11b398a1ba08" capability="SEARCH"/>
 
   <ConnInstance id="fcf9f2b0-f7d6-42c9-84a6-61b28255a42b" displayName="ConnInstance103"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                 location="${connid.location}"
                 bundleName="net.tirasa.connid.bundles.soap"
                 connectorName="net.tirasa.connid.bundles.soap.WebServiceConnector"
@@ -657,6 +674,7 @@ under the License.
                 jsonConf='[{"schema":{"name":"endpoint","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["http://localhost:${cargo.servlet.port}/syncope-fit-build-tools/cxf/soap/provisioning"]},{"schema":{"name":"servicename","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["net.tirasa.connid.bundles.soap.provisioning.interfaces.Provisioning"]}]'/>
 
   <ConnInstance id="6c2acf1b-b052-46f0-8c56-7a8ad6905edf" displayName="CSVDir"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                 location="${connid.location}"
                 bundleName="net.tirasa.connid.bundles.csvdir"
                 connectorName="net.tirasa.connid.bundles.csvdir.CSVDirConnector"
@@ -668,7 +686,9 @@ under the License.
   <ConnInstance_capabilities connInstance_id="6c2acf1b-b052-46f0-8c56-7a8ad6905edf" capability="SEARCH"/>
   <ConnInstance_capabilities connInstance_id="6c2acf1b-b052-46f0-8c56-7a8ad6905edf" capability="SYNC"/>
     
-  <ConnInstance id="74141a3b-0762-4720-a4aa-fc3e374ef3ef" bundleName="net.tirasa.connid.bundles.ldap"
displayName="ApacheDS"
+  <ConnInstance id="74141a3b-0762-4720-a4aa-fc3e374ef3ef"
+                bundleName="net.tirasa.connid.bundles.ldap" displayName="ApacheDS"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                 location="${connid.location}"
                 connectorName="net.tirasa.connid.bundles.ldap.LdapConnector"
                 version="${connid.ldap.version}" 
@@ -679,6 +699,7 @@ under the License.
   <ConnInstance_capabilities connInstance_id="74141a3b-0762-4720-a4aa-fc3e374ef3ef" capability="SEARCH"/>
   
   <ConnInstance id="a28abd9b-9f4a-4ef6-a7a8-d19ad2a8f29d" displayName="H2-test2"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                 location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
                 bundleName="net.tirasa.connid.bundles.db.table"
                 connectorName="net.tirasa.connid.bundles.db.table.DatabaseTableConnector"
@@ -690,6 +711,7 @@ under the License.
   <ConnInstance_capabilities connInstance_id="a28abd9b-9f4a-4ef6-a7a8-d19ad2a8f29d" capability="SYNC"/>
   
   <ConnInstance id="be24b061-019d-4e3e-baf0-0a6d0a45cb9c" bundleName="net.tirasa.connid.bundles.db.table"

+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                 location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
                 connectorName="net.tirasa.connid.bundles.db.table.DatabaseTableConnector"

                 displayName="H2-testpull" version="${connid.database.version}"
@@ -700,6 +722,7 @@ under the License.
   <ConnInstance_capabilities connInstance_id="be24b061-019d-4e3e-baf0-0a6d0a45cb9c" capability="SEARCH"/>
   
   <ConnInstance id="a6d017fd-a705-4507-bb7c-6ab6a6745997" bundleName="net.tirasa.connid.bundles.db.scriptedsql"

+                adminRealm_id="0679e069-7355-4b20-bd11-a5a0a5453c7c"
                 location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
                 connectorName="net.tirasa.connid.bundles.db.scriptedsql.ScriptedSQLConnector"
                 displayName="Scripted SQL" version="${connid.database.version}"
@@ -711,6 +734,7 @@ under the License.
   <ConnInstance_capabilities connInstance_id="a6d017fd-a705-4507-bb7c-6ab6a6745997" capability="SYNC"/>
   
   <ConnInstance id="44c02549-19c3-483c-8025-4919c3283c37" bundlename="net.tirasa.connid.bundles.rest"
+                adminRealm_id="0679e069-7355-4b20-bd11-a5a0a5453c7c"
                 location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
                 connectorname="net.tirasa.connid.bundles.rest.RESTConnector"
                 displayname="REST" version="${connid.rest.version}"

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/TwoContent.xml b/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
index d4949d8..4fd3db7 100644
--- a/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
@@ -185,6 +185,7 @@ we are happy to inform you that the password request was successfully
executed f
   <Notification_events notification_id="71769807-7f74-4dc3-ba61-e4a7a00eb8ad" event="[CUSTOM]:[]:[]:[confirmPasswordReset]:[SUCCESS]"/>
 
   <ConnInstance id="b7ea96c3-c633-488b-98a0-b52ac35850f7" bundleName="net.tirasa.connid.bundles.ldap"
displayName="LDAP"
+                adminRealm_id="ea696a4f-e77a-4ef1-be67-8f8093bc8686"
                 location="${connid.location}"
                 connectorName="net.tirasa.connid.bundles.ldap.LdapConnector"
                 version="${connid.ldap.version}" 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/utils/RealmUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/utils/RealmUtils.java
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/utils/RealmUtils.java
index 49810c7..a21e1de 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/utils/RealmUtils.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/utils/RealmUtils.java
@@ -21,6 +21,9 @@ package org.apache.syncope.core.provisioning.api.utils;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 
 public final class RealmUtils {
 
@@ -57,6 +60,50 @@ public final class RealmUtils {
         return normalized;
     }
 
+    private static class StartsWithPredicate implements Predicate<String> {
+
+        private final Collection<String> targets;
+
+        StartsWithPredicate(final Collection<String> targets) {
+            this.targets = targets;
+        }
+
+        @Override
+        public boolean evaluate(final String realm) {
+            return IterableUtils.matchesAny(targets, new Predicate<String>() {
+
+                @Override
+                public boolean evaluate(final String target) {
+                    return realm.startsWith(target);
+                }
+            });
+        }
+
+    }
+
+    public static class DynRealmsPredicate implements Predicate<String> {
+
+        @Override
+        public boolean evaluate(final String realm) {
+            return !realm.startsWith("/");
+        }
+    }
+
+    public static Set<String> getEffective(final Set<String> allowedRealms, final
String requestedRealm) {
+        Set<String> allowed = RealmUtils.normalize(allowedRealms);
+        Set<String> requested = new HashSet<>();
+        requested.add(requestedRealm);
+
+        Set<String> effective = new HashSet<>();
+        CollectionUtils.select(requested, new StartsWithPredicate(allowed), effective);
+        CollectionUtils.select(allowed, new StartsWithPredicate(requested), effective);
+
+        // includes dynamic realms
+        CollectionUtils.select(allowedRealms, new DynRealmsPredicate(), effective);
+
+        return effective;
+    }
+
     private RealmUtils() {
         // empty constructor for static utility class 
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorManager.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorManager.java
index e63eb2c..901acc2 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorManager.java
@@ -90,6 +90,7 @@ public class ConnectorManager implements ConnectorRegistry, ConnectorFactory,
Sy
         }
 
         ConnInstance override = entityFactory.newEntity(ConnInstance.class);
+        override.setAdminRealm(connInstance.getAdminRealm());
         override.setConnectorName(connInstance.getConnectorName());
         override.setDisplayName(connInstance.getDisplayName());
         override.setBundleName(connInstance.getBundleName());

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConnInstanceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConnInstanceDataBinderImpl.java
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConnInstanceDataBinderImpl.java
index ba4d62d..06a8021 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConnInstanceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConnInstanceDataBinderImpl.java
@@ -24,8 +24,6 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
-import org.apache.commons.collections4.IterableUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
@@ -37,9 +35,11 @@ import org.apache.syncope.core.persistence.api.dao.ConfDAO;
 import org.apache.syncope.core.persistence.api.dao.ConnInstanceDAO;
 import org.apache.syncope.core.persistence.api.dao.ConnInstanceHistoryConfDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.entity.ConnInstance;
 import org.apache.syncope.core.persistence.api.entity.ConnInstanceHistoryConf;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.provisioning.api.ConnIdBundleManager;
 import org.apache.syncope.core.provisioning.api.utils.ConnPoolConfUtils;
 import org.identityconnectors.framework.api.ConfigurationProperties;
@@ -54,7 +54,7 @@ import org.springframework.stereotype.Component;
 @Component
 public class ConnInstanceDataBinderImpl implements ConnInstanceDataBinder {
 
-    private static final String[] IGNORE_PROPERTIES = { "poolConf", "location" };
+    private static final String[] IGNORE_PROPERTIES = { "poolConf", "location", "adminRealm"
};
 
     @Autowired
     private ConnIdBundleManager connIdBundleManager;
@@ -66,6 +66,9 @@ public class ConnInstanceDataBinderImpl implements ConnInstanceDataBinder
{
     private ConnInstanceHistoryConfDAO connInstanceHistoryConfDAO;
 
     @Autowired
+    private RealmDAO realmDAO;
+
+    @Autowired
     private ConfDAO confDAO;
 
     @Autowired
@@ -98,6 +101,12 @@ public class ConnInstanceDataBinderImpl implements ConnInstanceDataBinder
{
         ConnInstance connInstance = entityFactory.newEntity(ConnInstance.class);
 
         BeanUtils.copyProperties(connInstanceTO, connInstance, IGNORE_PROPERTIES);
+        if (connInstanceTO.getAdminRealm() != null) {
+            connInstance.setAdminRealm(realmDAO.findByFullPath(connInstanceTO.getAdminRealm()));
+        }
+        if (connInstance.getAdminRealm() == null) {
+            sce.getElements().add("Invalid or null realm specified: " + connInstanceTO.getAdminRealm());
+        }
         if (connInstanceTO.getLocation() != null) {
             connInstance.setLocation(connInstanceTO.getLocation());
         }
@@ -116,7 +125,7 @@ public class ConnInstanceDataBinderImpl implements ConnInstanceDataBinder
{
 
     @Override
     public ConnInstance update(final ConnInstanceTO connInstanceTO) {
-        ConnInstance connInstance = connInstanceDAO.find(connInstanceTO.getKey());
+        ConnInstance connInstance = connInstanceDAO.authFind(connInstanceTO.getKey());
         if (connInstance == null) {
             throw new NotFoundException("Connector '" + connInstanceTO.getKey() + "'");
         }
@@ -143,6 +152,16 @@ public class ConnInstanceDataBinderImpl implements ConnInstanceDataBinder
{
         connInstance.getCapabilities().clear();
         connInstance.getCapabilities().addAll(connInstanceTO.getCapabilities());
 
+        if (connInstanceTO.getAdminRealm() != null) {
+            Realm realm = realmDAO.findByFullPath(connInstanceTO.getAdminRealm());
+            if (realm == null) {
+                SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
+                sce.getElements().add("Invalid or null realm specified: " + connInstanceTO.getAdminRealm());
+                throw sce;
+            }
+            connInstance.setAdminRealm(realm);
+        }
+
         if (connInstanceTO.getLocation() != null) {
             connInstance.setLocation(connInstanceTO.getLocation());
         }
@@ -181,9 +200,9 @@ public class ConnInstanceDataBinderImpl implements ConnInstanceDataBinder
{
         try {
             connInstance = connInstanceDAO.save(connInstance);
         } catch (Exception e) {
-            SyncopeClientException ex = SyncopeClientException.build(ClientExceptionType.InvalidConnInstance);
-            ex.getElements().add(e.getMessage());
-            throw ex;
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidConnInstance);
+            sce.getElements().add(e.getMessage());
+            throw sce;
         }
 
         return connInstance;
@@ -220,25 +239,18 @@ public class ConnInstanceDataBinderImpl implements ConnInstanceDataBinder
{
 
         Pair<URI, ConnectorInfo> info = connIdBundleManager.getConnectorInfo(connInstance);
         BeanUtils.copyProperties(connInstance, connInstanceTO, IGNORE_PROPERTIES);
+        connInstanceTO.setAdminRealm(connInstance.getAdminRealm().getFullPath());
         connInstanceTO.setLocation(info.getLeft().toASCIIString());
         // refresh stored properties in the given connInstance with direct information from
underlying connector
         ConfigurationProperties properties = connIdBundleManager.getConfigurationProperties(info.getRight());
         for (final String propName : properties.getPropertyNames()) {
             ConnConfPropSchema schema = build(properties.getProperty(propName));
 
-            ConnConfProperty property = IterableUtils.find(connInstanceTO.getConf(),
-                    new Predicate<ConnConfProperty>() {
-
-                @Override
-                public boolean evaluate(final ConnConfProperty candidate) {
-                    return propName.equals(candidate.getSchema().getName());
-                }
-            });
+            ConnConfProperty property = connInstanceTO.getConf(propName);
             if (property == null) {
                 property = new ConnConfProperty();
                 connInstanceTO.getConf().add(property);
             }
-
             property.setSchema(schema);
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/core/spring/src/main/java/org/apache/syncope/core/spring/security/DelegatedAdministrationException.java
----------------------------------------------------------------------
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DelegatedAdministrationException.java
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DelegatedAdministrationException.java
index 0ee414a..392ce41 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DelegatedAdministrationException.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DelegatedAdministrationException.java
@@ -24,7 +24,7 @@ public class DelegatedAdministrationException extends RuntimeException {
 
     private static final long serialVersionUID = 7540587364235915081L;
 
-    public DelegatedAdministrationException(final String realm, final AnyTypeKind type, final
String key) {
+    public DelegatedAdministrationException(final String realm, final String type, final
String key) {
         super("Missing entitlement or realm administration under " + realm + " for "
                 + (key == null
                         ? "new " + type

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConnectorITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConnectorITCase.java
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConnectorITCase.java
index c5190b3..5bed533 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConnectorITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConnectorITCase.java
@@ -38,12 +38,15 @@ import java.util.Set;
 import java.util.UUID;
 import javax.ws.rs.core.Response;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.ConnBundleTO;
 import org.apache.syncope.common.lib.to.ConnIdObjectClassTO;
 import org.apache.syncope.common.lib.to.ConnInstanceHistoryConfTO;
@@ -54,6 +57,7 @@ import org.apache.syncope.common.lib.to.MappingTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ConnConfPropSchema;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
@@ -117,6 +121,7 @@ public class ConnectorITCase extends AbstractITCase {
     @Test
     public void create() {
         ConnInstanceTO connectorTO = new ConnInstanceTO();
+        connectorTO.setAdminRealm(SyncopeConstants.ROOT_REALM);
         connectorTO.setLocation(connectorService.read(
                 "88a7a819-dab5-46b4-9b90-0b9769eabdb8", Locale.ENGLISH.getLanguage()).getLocation());
         connectorTO.setVersion(connIdSoapVersion);
@@ -217,6 +222,7 @@ public class ConnectorITCase extends AbstractITCase {
     @Test
     public void update() {
         ConnInstanceTO connectorTO = new ConnInstanceTO();
+        connectorTO.setAdminRealm(SyncopeConstants.ROOT_REALM);
 
         // set connector instance key
         connectorTO.setKey("fcf9f2b0-f7d6-42c9-84a6-61b28255a42b");
@@ -358,6 +364,7 @@ public class ConnectorITCase extends AbstractITCase {
     @Test
     public void validate() {
         ConnInstanceTO connectorTO = new ConnInstanceTO();
+        connectorTO.setAdminRealm(SyncopeConstants.ROOT_REALM);
         connectorTO.setLocation(connectorServerLocation);
         connectorTO.setVersion(connIdDbVersion);
         connectorTO.setConnectorName("net.tirasa.connid.bundles.db.table.DatabaseTableConnector");
@@ -519,6 +526,52 @@ public class ConnectorITCase extends AbstractITCase {
     }
 
     @Test
+    public void authorizations() {
+        SyncopeClient puccini = clientFactory.create("puccini", ADMIN_PWD);
+        ConnectorService pcs = puccini.getService(ConnectorService.class);
+
+        // 1. list connectors: get only the ones allowed
+        List<ConnInstanceTO> connInstances = pcs.list(null);
+        assertEquals(2, connInstances.size());
+
+        assertTrue(IterableUtils.matchesAll(connInstances, new Predicate<ConnInstanceTO>()
{
+
+            @Override
+            public boolean evaluate(final ConnInstanceTO object) {
+                return "a6d017fd-a705-4507-bb7c-6ab6a6745997".equals(object.getKey())
+                        || "44c02549-19c3-483c-8025-4919c3283c37".equals(object.getKey());
+            }
+        }));
+
+        // 2. attempt to read a connector with a different admin realm: fail
+        try {
+            pcs.read("88a7a819-dab5-46b4-9b90-0b9769eabdb8", null);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
+        }
+
+        // 3. read and upate a connector in the realm for which entitlements are owned: succeed
+        try {
+            ConnInstanceTO scriptedsql = pcs.read("a6d017fd-a705-4507-bb7c-6ab6a6745997",
null);
+            ConnConfProperty reloadScriptOnExecution = scriptedsql.getConf("reloadScriptOnExecution");
+            assertEquals("true", reloadScriptOnExecution.getValues().get(0).toString());
+
+            reloadScriptOnExecution.getValues().set(0, "false");
+            pcs.update(scriptedsql);
+
+            scriptedsql = pcs.read(scriptedsql.getKey(), null);
+            reloadScriptOnExecution = scriptedsql.getConf("reloadScriptOnExecution");
+            assertEquals("false", reloadScriptOnExecution.getValues().get(0).toString());
+        } finally {
+            ConnInstanceTO scriptedsql = connectorService.read("a6d017fd-a705-4507-bb7c-6ab6a6745997",
null);
+            ConnConfProperty reloadScriptOnExecution = scriptedsql.getConf("reloadScriptOnExecution");
+            reloadScriptOnExecution.getValues().set(0, "true");
+            connectorService.update(scriptedsql);
+        }
+    }
+
+    @Test
     public void issueSYNCOPE10() {
         // ----------------------------------
         // Copy resource and connector in order to create new objects.
@@ -616,6 +669,7 @@ public class ConnectorITCase extends AbstractITCase {
         // Create a new connector
         // ----------------------------------------
         ConnInstanceTO connectorTO = new ConnInstanceTO();
+        connectorTO.setAdminRealm(SyncopeConstants.ROOT_REALM);
 
         connectorTO.setLocation(connectorService.read(
                 "88a7a819-dab5-46b4-9b90-0b9769eabdb8", Locale.ENGLISH.getLanguage()).getLocation());

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
index 9017a9b..36286e0 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
@@ -31,6 +31,7 @@ import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.io.IOUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AbstractTaskTO;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.AttrTO;
@@ -166,6 +167,7 @@ public class MigrationITCase extends AbstractTaskITCase {
 
     private String setupConnector() {
         ConnInstanceTO connInstanceTO = new ConnInstanceTO();
+        connInstanceTO.setAdminRealm(SyncopeConstants.ROOT_REALM);
         connInstanceTO.setLocation(connectorServerLocation);
         connInstanceTO.setConnectorName("net.tirasa.connid.bundles.db.scriptedsql.ScriptedSQLConnector");
         connInstanceTO.setBundleName("net.tirasa.connid.bundles.db.scriptedsql");

http://git-wip-us.apache.org/repos/asf/syncope/blob/9779e13e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
index 751ce0e..8f881de 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
@@ -39,6 +39,7 @@ import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.client.console.commons.ConnIdSpecialName;
 import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
+import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
@@ -610,6 +611,36 @@ public class ResourceITCase extends AbstractITCase {
     }
 
     @Test
+    public void authorizations() {
+        SyncopeClient puccini = clientFactory.create("puccini", ADMIN_PWD);
+        ResourceService prs = puccini.getService(ResourceService.class);
+
+        // 1. attempt to read a resource for a connector with a different admin realm: fail
+        try {
+            prs.read(RESOURCE_NAME_WS1);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.DelegatedAdministration, e.getType());
+        }
+
+        // 2. read and upate a resource for a connector in the realm for which entitlements
are owned: succeed
+        try {
+            ResourceTO scriptedsql = prs.read(RESOURCE_NAME_DBSCRIPTED);
+            assertEquals(TraceLevel.ALL, scriptedsql.getCreateTraceLevel());
+
+            scriptedsql.setCreateTraceLevel(TraceLevel.FAILURES);
+            prs.update(scriptedsql);
+
+            scriptedsql = prs.read(RESOURCE_NAME_DBSCRIPTED);
+            assertEquals(TraceLevel.FAILURES, scriptedsql.getCreateTraceLevel());
+        } finally {
+            ResourceTO scriptedsql = resourceService.read(RESOURCE_NAME_DBSCRIPTED);
+            scriptedsql.setCreateTraceLevel(TraceLevel.ALL);
+            resourceService.update(scriptedsql);
+        }
+    }
+
+    @Test
     public void issueSYNCOPE323() {
         ResourceTO actual = resourceService.read(RESOURCE_NAME_TESTDB);
         assertNotNull(actual);


Mime
View raw message