[SYNCOPE-652] Preliminary work (still struggling with OpenJPA slices)
Project: http://git-wip-us.apache.org/repos/asf/syncope/repo Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/93b2e384 Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/93b2e384 Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/93b2e384 Branch: refs/heads/SYNCOPE-652 Commit: 93b2e3847782936ab1c7a1fe9c60dc55cc196252 Parents: e7c6d81 Author: Francesco Chicchiriccò <[email protected]> Authored: Fri Jul 17 12:05:06 2015 +0200 Committer: Francesco Chicchiriccò <[email protected]> Committed: Fri Jul 17 12:05:43 2015 +0200 ---------------------------------------------------------------------- .travis.yml | 3 +- .../client/lib/SyncopeClientFactoryBean.java | 32 +++-- .../syncope/common/lib/SyncopeConstants.java | 2 + .../syncope/common/lib/jaxb/package-info.java | 23 ++++ .../apache/syncope/common/lib/to/DomainTO.java | 62 +++++++++ .../syncope/common/lib/types/Entitlement.java | 10 ++ .../syncope/common/rest/api/RESTHeaders.java | 2 + .../common/rest/api/service/DomainService.java | 96 +++++++++++++ .../syncope/core/logic/AbstractLogic.java | 3 - .../syncope/core/logic/AnyTypeClassLogic.java | 36 ++--- .../apache/syncope/core/logic/AnyTypeLogic.java | 2 +- .../apache/syncope/core/logic/DomainLogic.java | 136 +++++++++++++++++++ .../apache/syncope/core/logic/GroupLogic.java | 2 +- core/misc/pom.xml | 7 +- .../core/misc/security/AuthContextUtils.java | 24 +++- .../security/SyncopeAuthenticationDetails.java | 86 ++++++++++++ .../SyncopeAuthenticationDetailsSource.java | 32 +++++ .../security/SyncopeAuthenticationProvider.java | 51 ++++--- .../misc/src/main/resources/securityContext.xml | 5 +- .../syncope/core/persistence/api/dao/DAO.java | 2 + .../core/persistence/api/dao/DomainDAO.java | 33 +++++ .../core/persistence/api/entity/Domain.java | 32 +++++ core/persistence-jpa/pom.xml | 11 +- .../core/persistence/jpa/dao/AbstractDAO.java | 12 ++ .../persistence/jpa/dao/JPAAnySearchDAO.java | 9 +- .../core/persistence/jpa/dao/JPADomainDAO.java | 57 ++++++++ .../core/persistence/jpa/dao/JPAUserDAO.java | 4 +- .../jpa/entity/AnnotatedEntityListener.java | 2 +- .../core/persistence/jpa/entity/JPADomain.java | 79 +++++++++++ .../jpa/entity/JPAEntityFactory.java | 5 +- .../jpa/slice/DomainDistributionPolicy.java | 36 +++++ .../jpa/slice/DomainFinderTargetPolicy.java | 38 ++++++ .../jpa/slice/DomainQueryTargetPolicy.java | 41 ++++++ .../jpa/validation/entity/DomainCheck.java | 41 ++++++ .../jpa/validation/entity/DomainValidator.java | 42 ++++++ .../src/main/resources/persistence.properties | 4 +- .../resources/persistenceContextEMFactory.xml | 32 ++++- .../core/persistence/jpa/inner/UserTest.java | 20 +-- .../src/test/resources/persistence.properties | 4 +- .../provisioning/api/data/DomainDataBinder.java | 31 +++++ core/provisioning-java/pom.xml | 6 + .../java/data/DomainDataBinderImpl.java | 70 ++++++++++ .../java/data/UserDataBinderImpl.java | 8 +- .../java/sync/AbstractProvisioningJob.java | 22 +-- .../syncope/core/rest/cxf/AddDomainFilter.java | 39 ++++++ .../syncope/core/rest/cxf/AddETagFilter.java | 48 +++++++ .../core/rest/cxf/service/AddETagFilter.java | 50 ------- .../rest/cxf/service/DomainServiceImpl.java | 66 +++++++++ .../src/main/resources/restCXFContext.xml | 6 +- .../activiti/ActivitiUserWorkflowAdapter.java | 10 +- fit/core-reference/pom.xml | 2 +- pom.xml | 9 +- 52 files changed, 1331 insertions(+), 154 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/.travis.yml ---------------------------------------------------------------------- diff --git a/.travis.yml b/.travis.yml index 0e6f5c4..e17fd2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ jdk: # default install is mvn install --quiet -DskipTests=true install: mvn --show-version --quiet -P all,skipTests #invoker.streamLogs: we cannot access to log files through Travis web ui, so display everything in the console -script: mvn --show-version --quiet clean install -Dinvoker.streamLogs=true +#script: mvn --show-version --quiet clean install -Dinvoker.streamLogs=true +script: mvn --show-version --quiet -PskipTests -Dinvoker.streamLogs=true notifications: webhooks: http://rovere.tirasa.net/cgi-bin/travis.cgi http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java ---------------------------------------------------------------------- diff --git a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java index 24923f1..a3a271c 100644 --- a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java +++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClientFactoryBean.java @@ -20,6 +20,7 @@ package org.apache.syncope.client.lib; import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -31,6 +32,7 @@ import org.apache.cxf.feature.LoggingFeature; import org.apache.cxf.jaxrs.provider.JAXBElementProvider; import org.apache.cxf.staxutils.DocumentDepthProperties; import org.apache.syncope.common.lib.to.AbstractPolicyTO; +import org.apache.syncope.common.rest.api.RESTHeaders; /** * Factory bean for creating instances of {@link SyncopeClient}. @@ -62,8 +64,7 @@ public class SyncopeClientFactoryBean { private JacksonJaxbJsonProvider jsonProvider; - @SuppressWarnings("rawtypes") - private JAXBElementProvider jaxbProvider; + private JAXBElementProvider<?> jaxbProvider; private RestClientExceptionMapper exceptionMapper; @@ -71,21 +72,23 @@ public class SyncopeClientFactoryBean { private ContentType contentType; + private String domain; + private RestClientFactoryBean restClientFactoryBean; protected JacksonJaxbJsonProvider defaultJsonProvider() { return new JacksonJaxbJsonProvider(); } - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected JAXBElementProvider defaultJAXBProvider() { - JAXBElementProvider defaultJAXBProvider = new JAXBElementProvider(); + @SuppressWarnings({ "rawtypes" }) + protected JAXBElementProvider<?> defaultJAXBProvider() { + JAXBElementProvider<?> defaultJAXBProvider = new JAXBElementProvider(); DocumentDepthProperties depthProperties = new DocumentDepthProperties(); depthProperties.setInnerElementCountThreshold(500); defaultJAXBProvider.setDepthProperties(depthProperties); - Map marshallerProperties = new HashMap(); + Map<String, Object> marshallerProperties = new HashMap<>(); marshallerProperties.put(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); defaultJAXBProvider.setMarshallerProperties(marshallerProperties); @@ -108,6 +111,10 @@ public class SyncopeClientFactoryBean { } defaultRestClientFactoryBean.setAddress(address); + if (StringUtils.isNotBlank(domain)) { + defaultRestClientFactoryBean.setHeaders(Collections.singletonMap(RESTHeaders.DOMAIN, domain)); + } + defaultRestClientFactoryBean.setThreadSafe(true); defaultRestClientFactoryBean.setInheritHeaders(true); @@ -134,13 +141,13 @@ public class SyncopeClientFactoryBean { this.jsonProvider = jsonProvider; } - public JAXBElementProvider getJaxbProvider() { + public JAXBElementProvider<?> getJaxbProvider() { return jaxbProvider == null ? defaultJAXBProvider() : jaxbProvider; } - public SyncopeClientFactoryBean setJaxbProvider(final JAXBElementProvider jaxbProvider) { + public SyncopeClientFactoryBean setJaxbProvider(final JAXBElementProvider<?> jaxbProvider) { this.jaxbProvider = jaxbProvider; return this; } @@ -181,6 +188,15 @@ public class SyncopeClientFactoryBean { return this; } + public String getDomain() { + return domain; + } + + public SyncopeClientFactoryBean setDomain(final String domain) { + this.domain = domain; + return this; + } + public RestClientFactoryBean getRestClientFactoryBean() { return restClientFactoryBean == null ? defaultRestClientFactoryBean() http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java ---------------------------------------------------------------------- diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java index 6538ec0..dbce5de 100644 --- a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java +++ b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeConstants.java @@ -27,6 +27,8 @@ public final class SyncopeConstants { public static final String NAMESPACE = "http://syncope.apache.org/2.0"; + public static final String MASTER_DOMAIN = "Master"; + public static final String ROOT_REALM = "/"; public static final Set<String> FULL_ADMIN_REALMS = Collections.singleton("/"); http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/package-info.java ---------------------------------------------------------------------- diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/package-info.java b/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/package-info.java new file mode 100644 index 0000000..a04b95d --- /dev/null +++ b/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/package-info.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +@XmlSchema(namespace = SyncopeConstants.NAMESPACE) +package org.apache.syncope.common.lib.jaxb; + +import javax.xml.bind.annotation.XmlSchema; +import org.apache.syncope.common.lib.SyncopeConstants; http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/common/lib/src/main/java/org/apache/syncope/common/lib/to/DomainTO.java ---------------------------------------------------------------------- diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/DomainTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/DomainTO.java new file mode 100644 index 0000000..3f05e19 --- /dev/null +++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/DomainTO.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.common.lib.to; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import org.apache.syncope.common.lib.AbstractBaseBean; +import org.apache.syncope.common.lib.types.CipherAlgorithm; + +@XmlRootElement(name = "domain") +@XmlType +public class DomainTO extends AbstractBaseBean { + + private static final long serialVersionUID = -7938075259986084934L; + + private String key; + + private String adminPwd; + + private CipherAlgorithm adminCipherAlgorithm; + + public String getKey() { + return key; + } + + public void setKey(final String key) { + this.key = key; + } + + public String getAdminPwd() { + return adminPwd; + } + + public void setAdminPwd(final String adminPwd) { + this.adminPwd = adminPwd; + } + + public CipherAlgorithm getAdminCipherAlgorithm() { + return adminCipherAlgorithm; + } + + public void setAdminCipherAlgorithm(final CipherAlgorithm adminCipherAlgorithm) { + this.adminCipherAlgorithm = adminCipherAlgorithm; + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java ---------------------------------------------------------------------- diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java index 806aaa4..85befc6 100644 --- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java +++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java @@ -28,6 +28,16 @@ public final class Entitlement { public static final String ANONYMOUS = "ANONYMOUS"; + public static final String DOMAIN_LIST = "DOMAIN_LIST"; + + public static final String DOMAIN_CREATE = "DOMAIN_CREATE"; + + public static final String DOMAIN_READ = "DOMAIN_READ"; + + public static final String DOMAIN_UPDATE = "DOMAIN_UPDATE"; + + public static final String DOMAIN_DELETE = "DOMAIN_DELETE"; + public static final String REALM_LIST = "REALM_LIST"; public static final String REALM_CREATE = "REALM_CREATE"; http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/RESTHeaders.java ---------------------------------------------------------------------- diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/RESTHeaders.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/RESTHeaders.java index 4d19e31..13b30df 100644 --- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/RESTHeaders.java +++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/RESTHeaders.java @@ -23,6 +23,8 @@ package org.apache.syncope.common.rest.api; */ public final class RESTHeaders { + public static final String DOMAIN = "X-Syncope-Domain"; + public static final String USER_KEY = "X-Syncope-User-Key"; public static final String USERNAME = "X-Syncope-Username"; http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/DomainService.java ---------------------------------------------------------------------- diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/DomainService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/DomainService.java new file mode 100644 index 0000000..4076dc1 --- /dev/null +++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/DomainService.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.common.rest.api.service; + +import java.util.List; +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.apache.cxf.jaxrs.model.wadl.Description; +import org.apache.cxf.jaxrs.model.wadl.Descriptions; +import org.apache.cxf.jaxrs.model.wadl.DocTarget; +import org.apache.syncope.common.lib.to.DomainTO; + +/** + * REST operations for domains. + */ +@Path("domains") +public interface DomainService extends JAXRSService { + + /** + * Returns a list of all domains. + * + * @return list of all domains. + */ + @GET + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + List<DomainTO> list(); + + /** + * Returns domain with matching key. + * + * @param key domain key to be read + * @return domain with matching key + */ + @GET + @Path("{key}") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + DomainTO read(@NotNull @PathParam("key") String key); + + /** + * Creates a new domain. + * + * @param domainTO domain to be created + * @return <tt>Response</tt> object featuring <tt>Location</tt> header of created domain + */ + @Descriptions({ + @Description(target = DocTarget.RESPONSE, + value = "Featuring <tt>Location</tt> header of created domain") + }) + @POST + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + Response create(@NotNull DomainTO domainTO); + + /** + * Updates the domain matching the provided key. + * + * @param domainTO domain to be stored + */ + @PUT + @Path("{key}") + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + void update(@NotNull DomainTO domainTO); + + /** + * Deletes the domain matching the provided key. + * + * @param key domain key to be deleted + */ + @DELETE + @Path("{key}") + void delete(@NotNull @PathParam("key") String key); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java index 35e806a..6aa375c 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractLogic.java @@ -31,9 +31,6 @@ import org.springframework.transaction.annotation.Transactional; */ abstract class AbstractLogic<T extends AbstractBaseBean> { - /** - * Logger. - */ protected static final Logger LOG = LoggerFactory.getLogger(AbstractLogic.class); /** http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java index 8747631..1743370 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java @@ -42,11 +42,11 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO private AnyTypeClassDataBinder binder; @Autowired - private AnyTypeClassDAO anyTypeDAO; + private AnyTypeClassDAO anyTypeClassDAO; @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_READ + "')") public AnyTypeClassTO read(final String key) { - AnyTypeClass anyType = anyTypeDAO.find(key); + AnyTypeClass anyType = anyTypeClassDAO.find(key); if (anyType == null) { LOG.error("Could not find anyType '" + key + "'"); @@ -58,7 +58,7 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_LIST + "')") public List<AnyTypeClassTO> list() { - return CollectionUtils.collect(anyTypeDAO.findAll(), new Transformer<AnyTypeClass, AnyTypeClassTO>() { + return CollectionUtils.collect(anyTypeClassDAO.findAll(), new Transformer<AnyTypeClass, AnyTypeClassTO>() { @Override public AnyTypeClassTO transform(final AnyTypeClass input) { @@ -68,35 +68,35 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO } @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_CREATE + "')") - public AnyTypeClassTO create(final AnyTypeClassTO anyTypeTO) { - return binder.getAnyTypeClassTO(anyTypeDAO.save(binder.create(anyTypeTO))); + public AnyTypeClassTO create(final AnyTypeClassTO anyTypeClassTO) { + return binder.getAnyTypeClassTO(anyTypeClassDAO.save(binder.create(anyTypeClassTO))); } @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_UPDATE + "')") - public AnyTypeClassTO update(final AnyTypeClassTO anyTypeTO) { - AnyTypeClass anyType = anyTypeDAO.find(anyTypeTO.getKey()); + public AnyTypeClassTO update(final AnyTypeClassTO anyTypeClassTO) { + AnyTypeClass anyType = anyTypeClassDAO.find(anyTypeClassTO.getKey()); if (anyType == null) { - LOG.error("Could not find anyType '" + anyTypeTO.getKey() + "'"); - throw new NotFoundException(String.valueOf(anyTypeTO.getKey())); + LOG.error("Could not find anyTypeClass '" + anyTypeClassTO.getKey() + "'"); + throw new NotFoundException(String.valueOf(anyTypeClassTO.getKey())); } - binder.update(anyType, anyTypeTO); - anyType = anyTypeDAO.save(anyType); + binder.update(anyType, anyTypeClassTO); + anyType = anyTypeClassDAO.save(anyType); return binder.getAnyTypeClassTO(anyType); } @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_DELETE + "')") public AnyTypeClassTO delete(final String key) { - AnyTypeClass anyType = anyTypeDAO.find(key); - if (anyType == null) { - LOG.error("Could not find anyType '" + key + "'"); + AnyTypeClass anyTypeClass = anyTypeClassDAO.find(key); + if (anyTypeClass == null) { + LOG.error("Could not find anyTypeClass '" + key + "'"); throw new NotFoundException(String.valueOf(key)); } - AnyTypeClassTO deleted = binder.getAnyTypeClassTO(anyType); - anyTypeDAO.delete(key); + AnyTypeClassTO deleted = binder.getAnyTypeClassTO(anyTypeClass); + anyTypeClassDAO.delete(key); return deleted; } @@ -108,7 +108,7 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO if (ArrayUtils.isNotEmpty(args)) { for (int i = 0; key == null && i < args.length; i++) { - if (args[i] instanceof Long) { + if (args[i] instanceof String) { key = (String) args[i]; } else if (args[i] instanceof AnyTypeClassTO) { key = ((AnyTypeClassTO) args[i]).getKey(); @@ -118,7 +118,7 @@ public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO if (StringUtils.isNotBlank(key)) { try { - return binder.getAnyTypeClassTO(anyTypeDAO.find(key)); + return binder.getAnyTypeClassTO(anyTypeClassDAO.find(key)); } catch (Throwable ignore) { LOG.debug("Unresolved reference", ignore); throw new UnresolvedReferenceException(ignore); http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java index b0cfa03..1ff60c7 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java @@ -116,7 +116,7 @@ public class AnyTypeLogic extends AbstractTransactionalLogic<AnyTypeTO> { if (ArrayUtils.isNotEmpty(args)) { for (int i = 0; key == null && i < args.length; i++) { - if (args[i] instanceof Long) { + if (args[i] instanceof String) { key = (String) args[i]; } else if (args[i] instanceof AnyTypeTO) { key = ((AnyTypeTO) args[i]).getKey(); http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java new file mode 100644 index 0000000..58f717d --- /dev/null +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/DomainLogic.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.logic; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Transformer; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.common.lib.to.DomainTO; +import org.apache.syncope.common.lib.types.Entitlement; +import org.apache.syncope.core.persistence.api.dao.NotFoundException; +import org.apache.syncope.core.persistence.api.dao.DomainDAO; +import org.apache.syncope.core.persistence.api.entity.Domain; +import org.apache.syncope.core.provisioning.api.data.DomainDataBinder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; + +@Component +public class DomainLogic extends AbstractTransactionalLogic<DomainTO> { + + @Autowired + private DomainDataBinder binder; + + @Autowired + private DomainDAO domainDAO; + + @PreAuthorize("hasRole('" + Entitlement.DOMAIN_READ + "') and authentication.details.domain == " + + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN") + public DomainTO read(final String key) { + Domain domain = domainDAO.find(key); + if (domain == null) { + LOG.error("Could not find domain '" + key + "'"); + + throw new NotFoundException(String.valueOf(key)); + } + + return binder.getDomainTO(domain); + } + + @PreAuthorize("hasRole('" + Entitlement.DOMAIN_LIST + "') and authentication.details.domain == " + + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN") + public List<DomainTO> list() { + return CollectionUtils.collect(domainDAO.findAll(), new Transformer<Domain, DomainTO>() { + + @Override + public DomainTO transform(final Domain input) { + return binder.getDomainTO(input); + } + }, new ArrayList<DomainTO>()); + } + + @PreAuthorize("hasRole('" + Entitlement.DOMAIN_CREATE + "') and authentication.details.domain == " + + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN") + public DomainTO create(final DomainTO domainTO) { + return binder.getDomainTO(domainDAO.save(binder.create(domainTO))); + } + + @PreAuthorize("hasRole('" + Entitlement.DOMAIN_UPDATE + "') and authentication.details.domain == " + + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN") + public DomainTO update(final DomainTO domainTO) { + Domain domain = domainDAO.find(domainTO.getKey()); + if (domain == null) { + LOG.error("Could not find domain '" + domainTO.getKey() + "'"); + throw new NotFoundException(String.valueOf(domainTO.getKey())); + } + + binder.update(domain, domainTO); + domain = domainDAO.save(domain); + + return binder.getDomainTO(domain); + } + + @PreAuthorize("hasRole('" + Entitlement.DOMAIN_DELETE + "') and authentication.details.domain == " + + "T(org.apache.syncope.common.lib.SyncopeConstants).MASTER_DOMAIN") + public DomainTO delete(final String key) { + Domain domain = domainDAO.find(key); + if (domain == null) { + LOG.error("Could not find domain '" + key + "'"); + + throw new NotFoundException(String.valueOf(key)); + } + + DomainTO deleted = binder.getDomainTO(domain); + domainDAO.delete(key); + return deleted; + } + + @Override + protected DomainTO resolveReference(final Method method, final Object... args) + throws UnresolvedReferenceException { + + String key = null; + + if (ArrayUtils.isNotEmpty(args)) { + for (int i = 0; key == null && i < args.length; i++) { + if (args[i] instanceof String) { + key = (String) args[i]; + } else if (args[i] instanceof DomainTO) { + key = ((DomainTO) args[i]).getKey(); + } + } + } + + if (StringUtils.isNotBlank(key)) { + try { + return binder.getDomainTO(domainDAO.find(key)); + } catch (Throwable ignore) { + LOG.debug("Unresolved reference", ignore); + throw new UnresolvedReferenceException(ignore); + } + } + + throw new UnresolvedReferenceException(); + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java ---------------------------------------------------------------------- diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java index ff5cd64..f476210 100644 --- a/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java +++ b/core/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java @@ -103,7 +103,7 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupMod> { @Transactional(readOnly = true) public List<GroupTO> own() { return CollectionUtils.collect( - userDAO.findAllGroups(userDAO.find(AuthContextUtils.getAuthenticatedUsername())), + userDAO.findAllGroups(userDAO.find(AuthContextUtils.getUsername())), new Transformer<Group, GroupTO>() { @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/misc/pom.xml ---------------------------------------------------------------------- diff --git a/core/misc/pom.xml b/core/misc/pom.xml index d330ad6..d9c6049 100644 --- a/core/misc/pom.xml +++ b/core/misc/pom.xml @@ -100,11 +100,16 @@ under the License. <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> </dependency> - + <dependency> <groupId>org.apache.syncope.core</groupId> <artifactId>syncope-core-provisioning-api</artifactId> <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.syncope.common</groupId> + <artifactId>syncope-common-rest-api</artifactId> + <version>${project.version}</version> </dependency> <!-- TEST --> http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthContextUtils.java ---------------------------------------------------------------------- diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthContextUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthContextUtils.java index 6eebf01..980201a 100644 --- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthContextUtils.java +++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/AuthContextUtils.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.syncope.common.lib.SyncopeConstants; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -32,24 +33,25 @@ import org.springframework.security.core.userdetails.User; public final class AuthContextUtils { - public static String getAuthenticatedUsername() { + public static String getUsername() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); return authentication == null ? SyncopeConstants.UNAUTHENTICATED : authentication.getName(); } - public static void updateAuthenticatedUsername(final String newUsername) { + public static void updateUsername(final String newUsername) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - Authentication newAuth = new UsernamePasswordAuthenticationToken( + UsernamePasswordAuthenticationToken newAuth = new UsernamePasswordAuthenticationToken( new User(newUsername, "FAKE_PASSWORD", auth.getAuthorities()), auth.getCredentials(), auth.getAuthorities()); + newAuth.setDetails(auth.getDetails()); SecurityContextHolder.getContext().setAuthentication(newAuth); } public static Map<String, Set<String>> getAuthorizations() { Map<String, Set<String>> result = null; - final SecurityContext ctx = SecurityContextHolder.getContext(); + SecurityContext ctx = SecurityContextHolder.getContext(); if (ctx != null && ctx.getAuthentication() != null && ctx.getAuthentication().getAuthorities() != null) { result = new HashMap<>(); for (GrantedAuthority authority : ctx.getAuthentication().getAuthorities()) { @@ -64,6 +66,20 @@ public final class AuthContextUtils { return MapUtils.emptyIfNull(result); } + public static String getDomain() { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + + + String domainKey = auth != null && auth.getDetails() instanceof SyncopeAuthenticationDetails + ? SyncopeAuthenticationDetails.class.cast(auth.getDetails()).getDomain() + : null; + if (StringUtils.isBlank(domainKey)) { + domainKey = SyncopeConstants.MASTER_DOMAIN; + } + + return domainKey; + } + /** * Private default constructor, for static-only classes. */ http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetails.java ---------------------------------------------------------------------- diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetails.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetails.java new file mode 100644 index 0000000..68b27f4 --- /dev/null +++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetails.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.misc.security; + +import java.io.Serializable; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.apache.syncope.common.rest.api.RESTHeaders; + +public class SyncopeAuthenticationDetails implements Serializable { + + private static final long serialVersionUID = -5899959397393502897L; + + private final String remoteAddress; + + private final String sessionId; + + private String domain; + + public SyncopeAuthenticationDetails(final HttpServletRequest request) { + this.remoteAddress = request.getRemoteAddr(); + + HttpSession session = request.getSession(false); + this.sessionId = session == null ? null : session.getId(); + + this.domain = request.getHeader(RESTHeaders.DOMAIN); + } + + public SyncopeAuthenticationDetails(final String domain) { + this.remoteAddress = null; + this.sessionId = null; + this.domain = domain; + } + + public String getRemoteAddress() { + return remoteAddress; + } + + public String getSessionId() { + return sessionId; + } + + public String getDomain() { + return domain; + } + + public void setDomain(final String domain) { + this.domain = domain; + } + + @Override + public boolean equals(final Object obj) { + return EqualsBuilder.reflectionEquals(this, obj); + } + + @Override + public int hashCode() { + return HashCodeBuilder.reflectionHashCode(this); + } + + @Override + public String toString() { + return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE); + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetailsSource.java ---------------------------------------------------------------------- diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetailsSource.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetailsSource.java new file mode 100644 index 0000000..b943edf --- /dev/null +++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationDetailsSource.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.misc.security; + +import javax.servlet.http.HttpServletRequest; +import org.springframework.security.authentication.AuthenticationDetailsSource; + +public class SyncopeAuthenticationDetailsSource + implements AuthenticationDetailsSource<HttpServletRequest, SyncopeAuthenticationDetails> { + + @Override + public SyncopeAuthenticationDetails buildDetails(final HttpServletRequest context) { + return new SyncopeAuthenticationDetails(context); + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java ---------------------------------------------------------------------- diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java index 80d2b48..01abb93 100644 --- a/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java +++ b/core/misc/src/main/java/org/apache/syncope/core/misc/security/SyncopeAuthenticationProvider.java @@ -23,14 +23,14 @@ import java.util.Iterator; import java.util.Set; import javax.annotation.Resource; import org.apache.commons.collections4.SetUtils; -import org.apache.syncope.common.lib.types.AnyTypeKind; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.common.lib.types.AuditElements; import org.apache.syncope.common.lib.types.AuditElements.Result; import org.apache.syncope.common.lib.types.CipherAlgorithm; import org.apache.syncope.core.persistence.api.dao.ConfDAO; import org.apache.syncope.core.persistence.api.dao.PolicyDAO; import org.apache.syncope.core.persistence.api.dao.UserDAO; -import org.apache.syncope.core.persistence.api.entity.AnyUtils; import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory; import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource; import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr; @@ -39,7 +39,10 @@ import org.apache.syncope.core.provisioning.api.ConnectorFactory; import org.apache.syncope.core.misc.AuditManager; import org.apache.syncope.core.misc.MappingUtils; import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO; +import org.apache.syncope.core.persistence.api.dao.DomainDAO; +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.Domain; import org.apache.syncope.core.persistence.api.entity.Realm; import org.identityconnectors.framework.common.objects.Uid; import org.slf4j.Logger; @@ -57,15 +60,15 @@ import org.springframework.transaction.annotation.Transactional; @Configurable public class SyncopeAuthenticationProvider implements AuthenticationProvider { - /** - * Logger. - */ protected static final Logger LOG = LoggerFactory.getLogger(SyncopeAuthenticationProvider.class); @Autowired protected AuditManager auditManager; @Autowired + protected DomainDAO domainDAO; + + @Autowired protected ConfDAO confDAO; @Autowired @@ -131,18 +134,36 @@ public class SyncopeAuthenticationProvider implements AuthenticationProvider { @Transactional(noRollbackFor = { BadCredentialsException.class, DisabledException.class }) public Authentication authenticate(final Authentication authentication) { boolean authenticated = false; - User user = null; - String username = authentication.getName(); - if (anonymousUser.equals(username)) { + String domainKey = authentication.getDetails() instanceof SyncopeAuthenticationDetails + ? SyncopeAuthenticationDetails.class.cast(authentication.getDetails()).getDomain() + : null; + if (StringUtils.isBlank(domainKey)) { + domainKey = SyncopeConstants.MASTER_DOMAIN; + } + SyncopeAuthenticationDetails.class.cast(authentication.getDetails()).setDomain(domainKey); + + if (anonymousUser.equals(authentication.getName())) { authenticated = authentication.getCredentials().toString().equals(anonymousKey); - } else if (adminUser.equals(username)) { - authenticated = encryptor.verify( - authentication.getCredentials().toString(), - CipherAlgorithm.valueOf(adminPasswordAlgorithm), - adminPassword); + } else if (adminUser.equals(authentication.getName())) { + if (SyncopeConstants.MASTER_DOMAIN.equals(domainKey)) { + authenticated = encryptor.verify( + authentication.getCredentials().toString(), + CipherAlgorithm.valueOf(adminPasswordAlgorithm), + adminPassword); + } else { + Domain domain = domainDAO.find(domainKey); + if (domain == null) { + throw new NotFoundException("Could not find domain " + domainKey); + } + + authenticated = encryptor.verify( + authentication.getCredentials().toString(), + domain.getAdminCipherAlgorithm(), + domain.getAdminPwd()); + } } else { - user = userDAO.find(username); + User user = userDAO.find(authentication.getName()); if (user != null) { if (user.isSuspended() != null && user.isSuspended()) { @@ -166,7 +187,6 @@ public class SyncopeAuthenticationProvider implements AuthenticationProvider { authentication.getPrincipal(), null, userDetailsService.loadUserByUsername(authentication.getPrincipal().toString()).getAuthorities()); - token.setDetails(authentication.getDetails()); auditManager.audit( @@ -257,7 +277,6 @@ public class SyncopeAuthenticationProvider implements AuthenticationProvider { boolean authenticated = encryptor.verify(password, user.getCipherAlgorithm(), user.getPassword()); LOG.debug("{} authenticated on internal storage: {}", user.getUsername(), authenticated); - AnyUtils attrUtils = attrUtilsFactory.getInstance(AnyTypeKind.USER); for (Iterator<? extends ExternalResource> itor = getPassthroughResources(user).iterator(); itor.hasNext() && !authenticated;) { http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/misc/src/main/resources/securityContext.xml ---------------------------------------------------------------------- diff --git a/core/misc/src/main/resources/securityContext.xml b/core/misc/src/main/resources/securityContext.xml index 00ced82..57b1980 100644 --- a/core/misc/src/main/resources/securityContext.xml +++ b/core/misc/src/main/resources/securityContext.xml @@ -49,9 +49,12 @@ under the License. <constructor-arg ref="securityContextRepository"/> </bean> + <bean id="syncopeAuthenticationDetailsSource" + class="org.apache.syncope.core.misc.security.SyncopeAuthenticationDetailsSource"/> + <security:http security-context-repository-ref="securityContextRepository" realm="Apache Syncope authentication" use-expressions="false" disable-url-rewriting="false"> - <security:http-basic/> + <security:http-basic authentication-details-source-ref="syncopeAuthenticationDetailsSource"/> <security:anonymous username="${anonymousUser}"/> <security:intercept-url pattern="/**"/> http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DAO.java index 4452890..eb00a0d 100644 --- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DAO.java +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DAO.java @@ -22,6 +22,8 @@ import org.apache.syncope.core.persistence.api.entity.Entity; public interface DAO<E extends Entity<KEY>, KEY> { + String getDomain(E entity); + void refresh(E entity); void detach(E entity); http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DomainDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DomainDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DomainDAO.java new file mode 100644 index 0000000..ece1b16 --- /dev/null +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/DomainDAO.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.persistence.api.dao; + +import java.util.List; +import org.apache.syncope.core.persistence.api.entity.Domain; + +public interface DomainDAO extends DAO<Domain, String> { + + Domain find(String key); + + List<Domain> findAll(); + + Domain save(Domain domain); + + void delete(String key); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Domain.java ---------------------------------------------------------------------- diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Domain.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Domain.java new file mode 100644 index 0000000..7c496f0 --- /dev/null +++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Domain.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.persistence.api.entity; + +import org.apache.syncope.common.lib.types.CipherAlgorithm; + +public interface Domain extends Entity<String> { + + void setKey(String name); + + String getAdminPwd(); + + CipherAlgorithm getAdminCipherAlgorithm(); + + void setPassword(String password, CipherAlgorithm cipherAlgoritm); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/pom.xml ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/pom.xml b/core/persistence-jpa/pom.xml index d48ef77..0ab9e82 100644 --- a/core/persistence-jpa/pom.xml +++ b/core/persistence-jpa/pom.xml @@ -55,7 +55,11 @@ under the License. <groupId>org.apache.openjpa</groupId> <artifactId>openjpa-persistence-jdbc</artifactId> </dependency> - + <dependency> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa-slice</artifactId> + </dependency> + <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> @@ -105,6 +109,11 @@ under the License. </dependency> <!-- TEST --> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java index a4ff529..c2d5ae6 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractDAO.java @@ -25,6 +25,8 @@ import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContextType; import org.apache.commons.lang3.StringUtils; +import org.apache.openjpa.slice.SlicePersistence; +import org.apache.syncope.common.lib.SyncopeConstants; import org.apache.syncope.core.persistence.api.dao.DAO; import org.apache.syncope.core.persistence.api.dao.search.OrderByClause; import org.apache.syncope.core.persistence.api.entity.Entity; @@ -93,6 +95,16 @@ public abstract class AbstractDAO<E extends Entity<KEY>, KEY> implements DAO<E, } @Override + public String getDomain(final E entity) { + try { + return SlicePersistence.getSlice(entity); + } catch (Exception e) { + LOG.debug("While fetching slice for {}", entity, e); + return SyncopeConstants.MASTER_DOMAIN; + } + } + + @Override public void refresh(final E entity) { entityManager.refresh(entity); } http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java index b8ab75d..e0eae6a 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java @@ -387,12 +387,9 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?, ?, ?>, Long> implements List<T> result = new ArrayList<>(); for (Object anyKey : query.getResultList()) { - long actualKey; - if (anyKey instanceof Object[]) { - actualKey = ((Number) ((Object[]) anyKey)[0]).longValue(); - } else { - actualKey = ((Number) anyKey).longValue(); - } + long actualKey = anyKey instanceof Object[] + ? ((Number) ((Object[]) anyKey)[0]).longValue() + : ((Number) anyKey).longValue(); T any = typeKind == AnyTypeKind.USER ? (T) userDAO.find(actualKey) http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java new file mode 100644 index 0000000..37a4cd2 --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADomainDAO.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.persistence.jpa.dao; + +import java.util.List; +import javax.persistence.TypedQuery; +import org.apache.syncope.core.persistence.api.dao.DomainDAO; +import org.apache.syncope.core.persistence.api.entity.Domain; +import org.apache.syncope.core.persistence.jpa.entity.JPADomain; +import org.springframework.stereotype.Repository; + +@Repository +public class JPADomainDAO extends AbstractDAO<Domain, String> implements DomainDAO { + + @Override + public Domain find(final String key) { + return entityManager.find(JPADomain.class, key); + } + + @Override + public List<Domain> findAll() { + TypedQuery<Domain> query = entityManager.createQuery( + "SELECT e FROM " + JPADomain.class.getSimpleName() + " e ", Domain.class); + return query.getResultList(); + } + + @Override + public Domain save(final Domain anyTypeClass) { + return entityManager.merge(anyTypeClass); + } + + @Override + public void delete(final String key) { + Domain domain = find(key); + if (domain == null) { + return; + } + + entityManager.remove(domain); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/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 7045ddc..3b413c0 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 @@ -74,8 +74,8 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO { protected void securityChecks(final User user) { // Allows anonymous (during self-registration) and self (during self-update) to read own user, // otherwise goes through security checks to see if required entitlements are owned - if (!AuthContextUtils.getAuthenticatedUsername().equals(anonymousUser) - && !AuthContextUtils.getAuthenticatedUsername().equals(user.getUsername())) { + if (!AuthContextUtils.getUsername().equals(anonymousUser) + && !AuthContextUtils.getUsername().equals(user.getUsername())) { Set<String> authRealms = AuthContextUtils.getAuthorizations().get(Entitlement.USER_READ); boolean authorized = CollectionUtils.exists(authRealms, new Predicate<String>() { http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java index 8a9547e..4e8044d 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java @@ -33,7 +33,7 @@ public class AnnotatedEntityListener { @PrePersist @PreUpdate public void setSysInfo(final AnnotatedEntity<?> entity) { - final String username = AuthContextUtils.getAuthenticatedUsername(); + final String username = AuthContextUtils.getUsername(); LOG.debug("Set system properties for '{}'", entity); final Date now = new Date(); http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java new file mode 100644 index 0000000..3e9169e --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADomain.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.persistence.jpa.entity; + +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Id; +import javax.persistence.Table; +import org.apache.syncope.common.lib.types.CipherAlgorithm; +import org.apache.syncope.core.misc.security.Encryptor; +import org.apache.syncope.core.persistence.api.entity.Domain; +import org.apache.syncope.core.persistence.jpa.validation.entity.DomainCheck; + +@Entity +@Table(name = JPADomain.TABLE) +@DomainCheck +public class JPADomain extends AbstractEntity<String> implements Domain { + + private static final long serialVersionUID = -5891241943464285840L; + + public static final String TABLE = "SyncopeDomain"; + + @Id + private String name; + + private String adminPwd; + + @Enumerated(EnumType.STRING) + private CipherAlgorithm adminCipherAlgorithm; + + @Override + public String getKey() { + return name; + } + + @Override + public void setKey(final String name) { + this.name = name; + } + + @Override + public String getAdminPwd() { + return adminPwd; + } + + @Override + public CipherAlgorithm getAdminCipherAlgorithm() { + return adminCipherAlgorithm; + } + + @Override + public void setPassword(final String password, final CipherAlgorithm cipherAlgoritm) { + try { + this.adminPwd = Encryptor.getInstance().encode(password, cipherAlgoritm); + this.adminCipherAlgorithm = cipherAlgoritm; + } catch (Exception e) { + LOG.error("Could not encode password", e); + this.adminPwd = null; + } + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java index ad6304e..41d3f74 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java @@ -27,6 +27,7 @@ import org.apache.syncope.core.persistence.api.entity.AnyTypeClass; 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.DerSchema; +import org.apache.syncope.core.persistence.api.entity.Domain; import org.apache.syncope.core.persistence.api.entity.user.DynRoleMembership; import org.apache.syncope.core.persistence.api.entity.Entity; import org.apache.syncope.core.persistence.api.entity.EntityFactory; @@ -129,7 +130,9 @@ public class JPAEntityFactory implements EntityFactory { public <KEY, T extends Entity<KEY>> T newEntity(final Class<T> reference) { T result; - if (reference.equals(Realm.class)) { + if (reference.equals(Domain.class)) { + result = (T) new JPADomain(); + } else if (reference.equals(Realm.class)) { result = (T) new JPARealm(); } else if (reference.equals(AccountPolicy.class)) { result = (T) new JPAAccountPolicy(); http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainDistributionPolicy.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainDistributionPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainDistributionPolicy.java new file mode 100644 index 0000000..2e61b06 --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainDistributionPolicy.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.persistence.jpa.slice; + +import java.util.List; +import org.apache.openjpa.slice.DistributionPolicy; +import org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.core.misc.security.AuthContextUtils; +import org.apache.syncope.core.persistence.api.entity.Domain; + +public class DomainDistributionPolicy implements DistributionPolicy { + + @Override + public String distribute(final Object pc, final List<String> slices, final Object context) { + return (pc instanceof Domain) + ? SyncopeConstants.MASTER_DOMAIN + : AuthContextUtils.getDomain(); + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainFinderTargetPolicy.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainFinderTargetPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainFinderTargetPolicy.java new file mode 100644 index 0000000..c6cad6e --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainFinderTargetPolicy.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.persistence.jpa.slice; + +import java.util.List; +import org.apache.openjpa.slice.FinderTargetPolicy; +import org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.core.misc.security.AuthContextUtils; +import org.apache.syncope.core.persistence.jpa.entity.JPADomain; + +public class DomainFinderTargetPolicy implements FinderTargetPolicy { + + @Override + public String[] getTargets(final Class<?> cls, final Object oid, final List<String> slices, final Object context) { + return new String[] { + JPADomain.class.equals(cls) + ? SyncopeConstants.MASTER_DOMAIN + : AuthContextUtils.getDomain() + }; + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainQueryTargetPolicy.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainQueryTargetPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainQueryTargetPolicy.java new file mode 100644 index 0000000..193ef2b --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/slice/DomainQueryTargetPolicy.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.persistence.jpa.slice; + +import java.util.List; +import java.util.Map; +import org.apache.openjpa.slice.QueryTargetPolicy; +import org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.core.misc.security.AuthContextUtils; +import org.apache.syncope.core.persistence.jpa.entity.JPADomain; + +public class DomainQueryTargetPolicy implements QueryTargetPolicy { + + @Override + public String[] getTargets(final String query, final Map<Object, Object> params, final String language, + final List<String> slices, final Object context) { + + return new String[] { + query.contains(JPADomain.class.getSimpleName()) + ? SyncopeConstants.MASTER_DOMAIN + : AuthContextUtils.getDomain() + }; + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainCheck.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainCheck.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainCheck.java new file mode 100644 index 0000000..f40c37e --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainCheck.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.persistence.jpa.validation.entity; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = DomainValidator.class) +@Documented +public @interface DomainCheck { + + String message() default "{org.apache.syncope.core.persistence.validation.domain}"; + + Class<?>[] groups() default {}; + + Class<? extends Payload>[] payload() default {}; +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java new file mode 100644 index 0000000..2e585e4 --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.core.persistence.jpa.validation.entity; + +import javax.validation.ConstraintValidatorContext; +import org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.common.lib.types.EntityViolationType; +import org.apache.syncope.core.persistence.api.entity.Domain; + +public class DomainValidator extends AbstractValidator<DomainCheck, Domain> { + + @Override + public boolean isValid(final Domain object, final ConstraintValidatorContext context) { + context.disableDefaultConstraintViolation(); + + boolean isValid = !SyncopeConstants.MASTER_DOMAIN.equals(object.getKey()); + + if (!isValid) { + context.buildConstraintViolationWithTemplate( + getTemplate(EntityViolationType.InvalidName, "Reserved: " + SyncopeConstants.MASTER_DOMAIN)). + addPropertyNode("name").addConstraintViolation(); + } + + return isValid; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/resources/persistence.properties ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/resources/persistence.properties b/core/persistence-jpa/src/main/resources/persistence.properties index 5afa1a6..054808d 100644 --- a/core/persistence-jpa/src/main/resources/persistence.properties +++ b/core/persistence-jpa/src/main/resources/persistence.properties @@ -22,8 +22,8 @@ jpa.password=syncope jpa.dialect=org.apache.openjpa.jdbc.sql.PostgresDictionary jpa.pool.validationQuery=SELECT 1 jpa.orm=META-INF/spring-orm.xml -#note: other connection pool settings can also be configured here, see persistenceContext.xml +# note: other connection pool settings can also be configured here, see persistenceContext.xml quartz.jobstore=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate quartz.sql=tables_postgres.sql audit.sql=audit.sql -database.schema= +database.schema= \ No newline at end of file http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml b/core/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml index 3b3b86b..d3a7e45 100644 --- a/core/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml +++ b/core/persistence-jpa/src/main/resources/persistenceContextEMFactory.xml @@ -21,7 +21,7 @@ under the License. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - + <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="packagesToScan" value="org.apache.syncope.core.persistence.jpa.entity"/> @@ -47,19 +47,41 @@ under the License. </property> <property name="jpaPropertyMap"> <map> + <entry key="openjpa.Log" value="DefaultLevel=INFO, Runtime=TRACE, Tool=TRACE, SQL=TRACE"/> + <!--<entry key="openjpa.Log" value="SQL=TRACE"/> <entry key="openjpa.ConnectionFactoryProperties" value="PrintParameters=true, PrettyPrint=true, PrettyPrintLineLength=80"/>--> - + <entry key="openjpa.NontransactionalWrite" value="false"/> <entry key="openjpa.AutoDetach" value="close, commit, nontx-read, rollback"/> <entry key="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)"/> - <entry key="openjpa.jdbc.MappingDefaults" value="ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict"/> - + <entry key="openjpa.jdbc.MappingDefaults" + value="ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict"/> + <entry key="openjpa.DataCache" value="true"/> - <entry key="openjpa.QueryCache" value="true"/> + <entry key="openjpa.QueryCache" value="false"/> + <entry key="openjpa.QueryCompilationCache" value="false"/> <entry key="openjpa.RemoteCommitProvider" value="sjvm"/> + + <entry key="openjpa.BrokerFactory" value="slice"/> + <entry key="openjpa.BrokerImpl" value="org.apache.openjpa.slice.DistributedBrokerImpl"/> + <entry key="openjpa.slice.Lenient" value="false"/> + + <entry key="openjpa.slice.DistributionPolicy" + value="org.apache.syncope.core.persistence.jpa.slice.DomainDistributionPolicy"/> + <entry key="openjpa.slice.QueryTargetPolicy" + value="org.apache.syncope.core.persistence.jpa.slice.DomainQueryTargetPolicy"/> + <entry key="openjpa.slice.FinderTargetPolicy" + value="org.apache.syncope.core.persistence.jpa.slice.DomainFinderTargetPolicy"/> + + <entry key="openjpa.slice.Names" value="Master"/> + <entry key="openjpa.slice.Master" value="Master"/> + <entry key="openjpa.slice.Lenient" value="false"/> + + <entry key="openjpa.slice.Master.ConnectionFactory" value-ref="dataSource"/> + <entry key="openjpa.slice.Master.jdbc.DBDictionary" value="${jpa.dialect}"/> </map> </property> </bean> http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java index 587f31d..1077239 100644 --- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java +++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java @@ -54,7 +54,7 @@ public class UserTest extends AbstractTest { @Test public void findAll() { List<User> list = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 1, 100); - assertEquals("did not get expected number of users ", 5, list.size()); + assertEquals("did not get expected number of users", 5, list.size()); } @Test @@ -68,25 +68,29 @@ public class UserTest extends AbstractTest { public void findAllByPageAndSize() { // get first page List<User> list = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 1, 2); - assertEquals("did not get expected number of users ", 2, list.size()); + assertEquals("did not get expected number of users", 2, list.size()); + + System.out.println("SSSSSSSSSSSSSSSSSS\n" + userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, -1, -1)); + System.out.println("SSSSSSSSSSSSSSSSSS\n" + userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 1,2)); + System.out.println("SSSSSSSSSSSSSSSSSS\n" + userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 2,2)); // get second page list = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 2, 2); - assertEquals("did not get expected number of users ", 2, list.size()); + assertEquals("did not get expected number of users", 2, list.size()); // get second page with uncomplete set list = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 2, 3); - assertEquals("did not get expected number of users ", 2, list.size()); + assertEquals("did not get expected number of users", 2, list.size()); // get unexistent page list = userDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, 3, 2); - assertEquals("did not get expected number of users ", 1, list.size()); + assertEquals("did not get expected number of users", 1, list.size()); } @Test public void findByDerAttributeValue() { final List<User> list = userDAO.findByDerAttrValue("cn", "Vivaldi, Antonio"); - assertEquals("did not get expected number of users ", 1, list.size()); + assertEquals("did not get expected number of users", 1, list.size()); } @Test(expected = IllegalArgumentException.class) @@ -105,7 +109,7 @@ public class UserTest extends AbstractTest { fullnameValue.setStringValue("Gioacchino Rossini"); final List<User> list = userDAO.findByAttrValue("fullname", fullnameValue); - assertEquals("did not get expected number of users ", 1, list.size()); + assertEquals("did not get expected number of users", 1, list.size()); } @Test @@ -114,7 +118,7 @@ public class UserTest extends AbstractTest { coolValue.setBooleanValue(true); final List<User> list = userDAO.findByAttrValue("cool", coolValue); - assertEquals("did not get expected number of users ", 1, list.size()); + assertEquals("did not get expected number of users", 1, list.size()); } @Test http://git-wip-us.apache.org/repos/asf/syncope/blob/93b2e384/core/persistence-jpa/src/test/resources/persistence.properties ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/test/resources/persistence.properties b/core/persistence-jpa/src/test/resources/persistence.properties index 92b0cbc..6993a0b 100644 --- a/core/persistence-jpa/src/test/resources/persistence.properties +++ b/core/persistence-jpa/src/test/resources/persistence.properties @@ -22,9 +22,9 @@ jpa.password= jpa.dialect=org.apache.openjpa.jdbc.sql.H2Dictionary jpa.pool.validationQuery=SELECT 1 jpa.orm=META-INF/spring-orm.xml -#note: other connection pool settings can also be configured here, see persistenceContext.xml +# note: other connection pool settings can also be configured here, see persistenceContext.xml quartz.jobstore=org.quartz.impl.jdbcjobstore.StdJDBCDelegate quartz.scheduler.idleWaitTime=5000 quartz.sql=tables_h2.sql audit.sql=audit.sql -database.schema= +database.schema= \ No newline at end of file
