http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportDAO.java index 793411d..6de5ffb 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportDAO.java @@ -32,12 +32,13 @@ import org.springframework.transaction.annotation.Transactional; @Repository public class JPAReportDAO extends AbstractDAO<Report, Long> implements ReportDAO { - @Override @Transactional(readOnly = true) + @Override public Report find(final Long key) { - return entityManager.find(JPAReport.class, key); + return entityManager().find(JPAReport.class, key); } + @Transactional(readOnly = true) @Override public List<Report> findAll() { return findAll(-1, -1, Collections.<OrderByClause>emptyList()); @@ -45,7 +46,7 @@ public class JPAReportDAO extends AbstractDAO<Report, Long> implements ReportDAO @Override public List<Report> findAll(final int page, final int itemsPerPage, final List<OrderByClause> orderByClauses) { - final TypedQuery<Report> query = entityManager.createQuery( + final TypedQuery<Report> query = entityManager().createQuery( "SELECT e FROM " + JPAReport.class.getSimpleName() + " e " + toOrderByStatement(Report.class, "e", orderByClauses), Report.class); @@ -62,14 +63,14 @@ public class JPAReportDAO extends AbstractDAO<Report, Long> implements ReportDAO @Override public int count() { - Query countQuery = entityManager.createNativeQuery("SELECT COUNT(id) FROM " + JPAReport.TABLE); + Query countQuery = entityManager().createNativeQuery("SELECT COUNT(id) FROM " + JPAReport.TABLE); return ((Number) countQuery.getSingleResult()).intValue(); } @Override @Transactional(rollbackFor = Throwable.class) public Report save(final Report report) { - return entityManager.merge(report); + return entityManager().merge(report); } @Override @@ -84,6 +85,6 @@ public class JPAReportDAO extends AbstractDAO<Report, Long> implements ReportDAO @Override public void delete(final Report report) { - entityManager.remove(report); + entityManager().remove(report); } }
http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java index 95f57df..cf9e781 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportExecDAO.java @@ -32,11 +32,11 @@ public class JPAReportExecDAO extends AbstractDAO<ReportExec, Long> implements R @Override public ReportExec find(final Long key) { - return entityManager.find(JPAReportExec.class, key); + return entityManager().find(JPAReportExec.class, key); } private ReportExec findLatest(final Report report, final String field) { - TypedQuery<ReportExec> query = entityManager.createQuery( + TypedQuery<ReportExec> query = entityManager().createQuery( "SELECT e FROM " + JPAReportExec.class.getSimpleName() + " e " + "WHERE e.report=:report ORDER BY e." + field + " DESC", ReportExec.class); query.setParameter("report", report); @@ -60,7 +60,7 @@ public class JPAReportExecDAO extends AbstractDAO<ReportExec, Long> implements R @Override public List<ReportExec> findAll() { - TypedQuery<ReportExec> query = entityManager.createQuery( + TypedQuery<ReportExec> query = entityManager().createQuery( "SELECT e FROM " + JPAReportExec.class.getSimpleName() + " e", ReportExec.class); return query.getResultList(); } @@ -75,7 +75,7 @@ public class JPAReportExecDAO extends AbstractDAO<ReportExec, Long> implements R @Override @Transactional(rollbackFor = Throwable.class) public ReportExec save(final ReportExec execution) { - return entityManager.merge(execution); + return entityManager().merge(execution); } @Override @@ -94,6 +94,6 @@ public class JPAReportExecDAO extends AbstractDAO<ReportExec, Long> implements R execution.getReport().removeExec(execution); } - entityManager.remove(execution); + entityManager().remove(execution); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java index 5f600b6..6fb5ec3 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java @@ -43,12 +43,12 @@ public class JPARoleDAO extends AbstractDAO<Role, Long> implements RoleDAO { @Override public Role find(final Long key) { - return entityManager.find(JPARole.class, key); + return entityManager().find(JPARole.class, key); } @Override public Role find(final String name) { - TypedQuery<Role> query = entityManager.createQuery( + TypedQuery<Role> query = entityManager().createQuery( "SELECT e FROM " + JPARole.class.getSimpleName() + " e WHERE e.name=:name", Role.class); query.setParameter("name", name); @@ -64,7 +64,7 @@ public class JPARoleDAO extends AbstractDAO<Role, Long> implements RoleDAO { @Override public List<Role> findByRealm(final Realm realm) { - TypedQuery<Role> query = entityManager.createQuery( + TypedQuery<Role> query = entityManager().createQuery( "SELECT e FROM " + JPARole.class.getSimpleName() + " e WHERE :realm MEMBER OF e.realms", Role.class); query.setParameter("realm", realm); return query.getResultList(); @@ -72,7 +72,7 @@ public class JPARoleDAO extends AbstractDAO<Role, Long> implements RoleDAO { @Override public List<Role> findAll() { - TypedQuery<Role> query = entityManager.createQuery( + TypedQuery<Role> query = entityManager().createQuery( "SELECT e FROM " + JPARole.class.getSimpleName() + " e ", Role.class); return query.getResultList(); } @@ -90,12 +90,12 @@ public class JPARoleDAO extends AbstractDAO<Role, Long> implements RoleDAO { } } - return entityManager.merge(role); + return entityManager().merge(role); } @Override public void delete(final Role role) { - entityManager.remove(role); + entityManager().remove(role); } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASecurityQuestionDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASecurityQuestionDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASecurityQuestionDAO.java index 5c242d6..7028080 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASecurityQuestionDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASecurityQuestionDAO.java @@ -36,19 +36,19 @@ public class JPASecurityQuestionDAO extends AbstractDAO<SecurityQuestion, Long> @Override public SecurityQuestion find(final Long key) { - return entityManager.find(JPASecurityQuestion.class, key); + return entityManager().find(JPASecurityQuestion.class, key); } @Override public List<SecurityQuestion> findAll() { - final TypedQuery<SecurityQuestion> query = entityManager.createQuery( + final TypedQuery<SecurityQuestion> query = entityManager().createQuery( "SELECT e FROM " + JPASecurityQuestion.class.getSimpleName() + " e ", SecurityQuestion.class); return query.getResultList(); } @Override public SecurityQuestion save(final SecurityQuestion securityQuestion) { - return entityManager.merge(securityQuestion); + return entityManager().merge(securityQuestion); } @Override @@ -64,7 +64,7 @@ public class JPASecurityQuestionDAO extends AbstractDAO<SecurityQuestion, Long> userDAO.save(user); } - entityManager.remove(securityQuestion); + entityManager().remove(securityQuestion); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java index ff93071..a70f65e 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java @@ -75,7 +75,7 @@ public class JPATaskDAO extends AbstractDAO<Task, Long> implements TaskDAO { @SuppressWarnings("unchecked") @Override public <T extends Task> T find(final Long key) { - return (T) entityManager.find(JPATask.class, key); + return (T) entityManager().find(JPATask.class, key); } private <T extends Task> StringBuilder buildfindAllQuery(final TaskType type) { @@ -96,7 +96,7 @@ public class JPATaskDAO extends AbstractDAO<Task, Long> implements TaskDAO { } queryString.append("ORDER BY e.id DESC"); - Query query = entityManager.createQuery(queryString.toString()); + Query query = entityManager().createQuery(queryString.toString()); query.setParameter("type", type); return query.getResultList(); } @@ -106,13 +106,14 @@ public class JPATaskDAO extends AbstractDAO<Task, Long> implements TaskDAO { public <T extends Task> List<T> findAll(final ExternalResource resource, final TaskType type) { StringBuilder queryString = buildfindAllQuery(type).append("AND e.resource=:resource ORDER BY e.id DESC"); - final Query query = entityManager.createQuery(queryString.toString()); + final Query query = entityManager().createQuery(queryString.toString()); query.setParameter("type", type); query.setParameter("resource", resource); return query.getResultList(); } + @Transactional(readOnly = true) @Override public <T extends Task> List<T> findAll(final TaskType type) { return findAll(-1, -1, Collections.<OrderByClause>emptyList(), type); @@ -128,7 +129,7 @@ public class JPATaskDAO extends AbstractDAO<Task, Long> implements TaskDAO { ? "ORDER BY e.id DESC" : toOrderByStatement(getEntityReference(type), "e", orderByClauses)); - Query query = entityManager.createQuery(queryString.toString()); + Query query = entityManager().createQuery(queryString.toString()); query.setParameter("type", type); query.setFirstResult(itemsPerPage * (page <= 0 @@ -144,7 +145,7 @@ public class JPATaskDAO extends AbstractDAO<Task, Long> implements TaskDAO { @Override public int count(final TaskType type) { - Query countQuery = entityManager.createNativeQuery("SELECT COUNT(id) FROM Task WHERE TYPE=?1"); + Query countQuery = entityManager().createNativeQuery("SELECT COUNT(id) FROM Task WHERE TYPE=?1"); countQuery.setParameter(1, type.name()); return ((Number) countQuery.getSingleResult()).intValue(); } @@ -152,7 +153,7 @@ public class JPATaskDAO extends AbstractDAO<Task, Long> implements TaskDAO { @Transactional(rollbackFor = { Throwable.class }) @Override public <T extends Task> T save(final T task) { - return entityManager.merge(task); + return entityManager().merge(task); } @Override @@ -167,7 +168,7 @@ public class JPATaskDAO extends AbstractDAO<Task, Long> implements TaskDAO { @Override public void delete(final Task task) { - entityManager.remove(task); + entityManager().remove(task); } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskExecDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskExecDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskExecDAO.java index 5d840da..38155ff 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskExecDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskExecDAO.java @@ -38,11 +38,11 @@ public class JPATaskExecDAO extends AbstractDAO<TaskExec, Long> implements TaskE @Override public TaskExec find(final Long key) { - return entityManager.find(JPATaskExec.class, key); + return entityManager().find(JPATaskExec.class, key); } private <T extends Task> TaskExec findLatest(final T task, final String field) { - TypedQuery<TaskExec> query = entityManager.createQuery( + TypedQuery<TaskExec> query = entityManager().createQuery( "SELECT e FROM " + JPATaskExec.class.getSimpleName() + " e " + "WHERE e.task=:task " + "ORDER BY e." + field + " DESC", TaskExec.class); @@ -71,13 +71,13 @@ public class JPATaskExecDAO extends AbstractDAO<TaskExec, Long> implements TaskE append(" e WHERE e.task IN (").append("SELECT t FROM "). append(taskDAO.getEntityReference(type).getSimpleName()).append(" t)"); - TypedQuery<TaskExec> query = entityManager.createQuery(queryString.toString(), TaskExec.class); + TypedQuery<TaskExec> query = entityManager().createQuery(queryString.toString(), TaskExec.class); return query.getResultList(); } @Override public TaskExec save(final TaskExec execution) { - return entityManager.merge(execution); + return entityManager().merge(execution); } /** @@ -111,6 +111,6 @@ public class JPATaskExecDAO extends AbstractDAO<TaskExec, Long> implements TaskE execution.getTask().removeExec(execution); } - entityManager.remove(execution); + entityManager().remove(execution); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/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 3b413c0..50564f2 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 @@ -29,8 +29,17 @@ import javax.persistence.TypedQuery; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.Predicate; import org.apache.commons.collections4.Transformer; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.syncope.common.lib.types.AccountPolicySpec; import org.apache.syncope.common.lib.types.AnyTypeKind; import org.apache.syncope.common.lib.types.Entitlement; +import org.apache.syncope.common.lib.types.EntityViolationType; +import org.apache.syncope.common.lib.types.PasswordPolicySpec; +import org.apache.syncope.core.misc.policy.AccountPolicyEnforcer; +import org.apache.syncope.core.misc.policy.AccountPolicyException; +import org.apache.syncope.core.misc.policy.PasswordPolicyEnforcer; +import org.apache.syncope.core.misc.policy.PolicyEvaluator; import org.apache.syncope.core.persistence.api.dao.NotFoundException; import org.apache.syncope.core.persistence.api.dao.GroupDAO; import org.apache.syncope.core.persistence.api.dao.UserDAO; @@ -40,14 +49,21 @@ import org.apache.syncope.core.persistence.api.entity.user.User; import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser; import org.apache.syncope.core.misc.security.AuthContextUtils; import org.apache.syncope.core.misc.security.UnauthorizedException; +import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException; +import org.apache.syncope.core.persistence.api.dao.RealmDAO; import org.apache.syncope.core.persistence.api.dao.RoleDAO; +import org.apache.syncope.core.persistence.api.entity.AccountPolicy; import org.apache.syncope.core.persistence.api.entity.AnyUtils; +import org.apache.syncope.core.persistence.api.entity.PasswordPolicy; +import org.apache.syncope.core.persistence.api.entity.Policy; +import org.apache.syncope.core.persistence.api.entity.Realm; import org.apache.syncope.core.persistence.api.entity.Role; import org.apache.syncope.core.persistence.api.entity.group.Group; import org.apache.syncope.core.persistence.api.entity.user.UMembership; import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory; import org.apache.syncope.core.persistence.jpa.entity.user.JPADynRoleMembership; import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDynGroupMembership; +import org.apache.syncope.core.provisioning.api.UserSuspender; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Propagation; @@ -57,14 +73,32 @@ import org.springframework.transaction.annotation.Transactional; public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO { @Autowired + private RealmDAO realmDAO; + + @Autowired private GroupDAO groupDAO; @Autowired private RoleDAO roleDAO; + @Resource(name = "adminUser") + private String adminUser; + @Resource(name = "anonymousUser") private String anonymousUser; + @Autowired + private PolicyEvaluator evaluator; + + @Autowired + private PasswordPolicyEnforcer ppEnforcer; + + @Autowired + private AccountPolicyEnforcer apEnforcer; + + @Autowired(required = false) + private UserSuspender suspender; + @Override protected AnyUtils init() { return new JPAAnyUtilsFactory().getInstance(AnyTypeKind.USER); @@ -110,7 +144,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO { @Override public User find(final String username) { - TypedQuery<User> query = entityManager.createQuery("SELECT e FROM " + JPAUser.class.getSimpleName() + TypedQuery<User> query = entityManager().createQuery("SELECT e FROM " + JPAUser.class.getSimpleName() + " e WHERE e.username = :username", User.class); query.setParameter("username", username); @@ -126,7 +160,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO { @Override public User findByToken(final String token) { - TypedQuery<User> query = entityManager.createQuery("SELECT e FROM " + JPAUser.class.getSimpleName() + TypedQuery<User> query = entityManager().createQuery("SELECT e FROM " + JPAUser.class.getSimpleName() + " e WHERE e.token LIKE :token", User.class); query.setParameter("token", token); @@ -142,16 +176,151 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO { @Override public List<User> findBySecurityQuestion(final SecurityQuestion securityQuestion) { - TypedQuery<User> query = entityManager.createQuery("SELECT e FROM " + JPAUser.class.getSimpleName() + TypedQuery<User> query = entityManager().createQuery("SELECT e FROM " + JPAUser.class.getSimpleName() + " e WHERE e.securityQuestion = :securityQuestion", User.class); query.setParameter("securityQuestion", securityQuestion); return query.getResultList(); } + private List<PasswordPolicy> getPasswordPolicies(final User user) { + List<PasswordPolicy> policies = new ArrayList<>(); + + PasswordPolicy policy; + + // add resource policies + for (ExternalResource resource : findAllResources(user)) { + policy = resource.getPasswordPolicy(); + if (policy != null) { + policies.add(policy); + } + } + + // add realm policies + for (Realm realm : realmDAO.findAncestors(user.getRealm())) { + policy = realm.getPasswordPolicy(); + if (policy != null) { + policies.add(policy); + } + } + + return policies; + } + + private List<AccountPolicy> getAccountPolicies(final User user) { + List<AccountPolicy> policies = new ArrayList<>(); + + AccountPolicy policy; + + // add resource policies + for (ExternalResource resource : findAllResources(user)) { + policy = resource.getAccountPolicy(); + if (policy != null) { + policies.add(policy); + } + } + + // add realm policies + for (Realm realm : realmDAO.findAncestors(user.getRealm())) { + policy = realm.getAccountPolicy(); + if (policy != null) { + policies.add(policy); + } + } + + return policies; + } + + private Pair<Boolean, Boolean> enforcePolicies(final User user) { + // ------------------------------ + // Verify password policies + // ------------------------------ + LOG.debug("Password Policy enforcement"); + + try { + int maxPPSpecHistory = 0; + for (Policy policy : getPasswordPolicies(user)) { + // evaluate policy + PasswordPolicySpec ppSpec = evaluator.evaluate(policy, user); + // enforce policy + ppEnforcer.enforce(ppSpec, policy.getType(), user); + + if (ppSpec.getHistoryLength() > maxPPSpecHistory) { + maxPPSpecHistory = ppSpec.getHistoryLength(); + } + } + + // update user's password history with encrypted password + if (maxPPSpecHistory > 0 && user.getPassword() != null) { + user.getPasswordHistory().add(user.getPassword()); + } + // keep only the last maxPPSpecHistory items in user's password history + if (maxPPSpecHistory < user.getPasswordHistory().size()) { + for (int i = 0; i < user.getPasswordHistory().size() - maxPPSpecHistory; i++) { + user.getPasswordHistory().remove(i); + } + } + } catch (Exception e) { + LOG.error("Invalid password for {}", user, e); + throw new InvalidEntityException(User.class, EntityViolationType.InvalidPassword, e.getMessage()); + } finally { + // password has been validated, let's remove its clear version + user.removeClearPassword(); + } + + // ------------------------------ + // Verify account policies + // ------------------------------ + LOG.debug("Account Policy enforcement"); + + boolean suspend = false; + boolean propagateSuspension = false; + try { + if (adminUser.equals(user.getUsername()) || anonymousUser.equals(user.getUsername())) { + throw new AccountPolicyException("Not allowed: " + user.getUsername()); + } + + // invalid username + for (Policy policy : getAccountPolicies(user)) { + // evaluate policy + AccountPolicySpec apSpec = evaluator.evaluate(policy, user); + + // enforce policy + suspend |= apEnforcer.enforce(apSpec, policy.getType(), user); + propagateSuspension |= apSpec.isPropagateSuspension(); + } + } catch (Exception e) { + LOG.error("Invalid username for {}", user, e); + throw new InvalidEntityException(User.class, EntityViolationType.InvalidUsername, e.getMessage()); + } + + return ImmutablePair.of(suspend, propagateSuspension); + } + @Override public User save(final User user) { + // 1. save clear password value before save + String clearPwd = user.getClearPassword(); + + // 2. save and flush to trigger entity validation User merged = super.save(user); + entityManager().flush(); + + // 3. set back the sole clear password value + JPAUser.class.cast(merged).setClearPassword(clearPwd); + + // 4. enforce password and account policies + Pair<Boolean, Boolean> enforceSuspend = null; + try { + enforceSuspend = enforcePolicies(merged); + } catch (InvalidEntityException e) { + entityManager().remove(merged); + throw e; + } + + if (suspender != null && enforceSuspend.getKey()) { + suspender.suspend(user, enforceSuspend.getValue()); + } roleDAO.refreshDynMemberships(merged); groupDAO.refreshDynMemberships(merged); @@ -168,13 +337,13 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO { group.getUDynMembership().remove(user); } - entityManager.remove(user); + entityManager().remove(user); } @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Override public List<Role> findDynRoleMemberships(final User user) { - TypedQuery<Role> query = entityManager.createQuery( + TypedQuery<Role> query = entityManager().createQuery( "SELECT e.role FROM " + JPADynRoleMembership.class.getSimpleName() + " e WHERE :user MEMBER OF e.users", Role.class); query.setParameter("user", user); @@ -185,7 +354,7 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO { @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Override public List<Group> findDynGroupMemberships(final User user) { - TypedQuery<Group> query = entityManager.createQuery( + TypedQuery<Group> query = entityManager().createQuery( "SELECT e.group FROM " + JPAUDynGroupMembership.class.getSimpleName() + " e WHERE :user MEMBER OF e.users", Group.class); query.setParameter("user", user); http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirAttrDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirAttrDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirAttrDAO.java index 3ef6791..2c8b99f 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirAttrDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirAttrDAO.java @@ -49,19 +49,19 @@ public class JPAVirAttrDAO extends AbstractDAO<VirAttr<?>, Long> implements VirA @Override public <T extends VirAttr<?>> T find(final Long key, final Class<T> reference) { - return reference.cast(entityManager.find(getJPAEntityReference(reference), key)); + return reference.cast(entityManager().find(getJPAEntityReference(reference), key)); } @Override public <T extends VirAttr<?>> List<T> findAll(final Class<T> reference) { - TypedQuery<T> query = entityManager.createQuery( + TypedQuery<T> query = entityManager().createQuery( "SELECT e FROM " + getJPAEntityReference(reference).getSimpleName() + " e", reference); return query.getResultList(); } @Override public <T extends VirAttr<?>> T save(final T virAttr) { - return entityManager.merge(virAttr); + return entityManager().merge(virAttr); } @Override @@ -81,6 +81,6 @@ public class JPAVirAttrDAO extends AbstractDAO<VirAttr<?>, Long> implements VirA ((Any<?, ?, T>) virAttr.getOwner()).remove(virAttr); } - entityManager.remove(virAttr); + entityManager().remove(virAttr); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java index dae6afc..46a06f6 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java @@ -45,7 +45,7 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V @Override public VirSchema find(final String key) { - return entityManager.find(JPAVirSchema.class, key); + return entityManager().find(JPAVirSchema.class, key); } @Override @@ -54,7 +54,7 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V append(JPAVirSchema.class.getSimpleName()). append(" e WHERE e.anyTypeClass=:anyTypeClass"); - TypedQuery<VirSchema> query = entityManager.createQuery(queryString.toString(), VirSchema.class); + TypedQuery<VirSchema> query = entityManager().createQuery(queryString.toString(), VirSchema.class); query.setParameter("anyTypeClass", anyTypeClass); return query.getResultList(); @@ -62,7 +62,7 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V @Override public List<VirSchema> findAll() { - TypedQuery<VirSchema> query = entityManager.createQuery( + TypedQuery<VirSchema> query = entityManager().createQuery( "SELECT e FROM " + JPAVirSchema.class.getSimpleName() + " e", VirSchema.class); return query.getResultList(); } @@ -73,7 +73,7 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V append(((JPAVirAttrDAO) virAttrDAO).getJPAEntityReference(reference).getSimpleName()). append(" e WHERE e.schema=:schema"); - TypedQuery<T> query = entityManager.createQuery(queryString.toString(), reference); + TypedQuery<T> query = entityManager().createQuery(queryString.toString(), reference); query.setParameter("schema", schema); return query.getResultList(); @@ -81,7 +81,7 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V @Override public VirSchema save(final VirSchema virSchema) { - return entityManager.merge(virSchema); + return entityManager().merge(virSchema); } @Override @@ -106,6 +106,6 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V schema.getAnyTypeClass().remove(schema); } - entityManager.remove(schema); + entityManager().remove(schema); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java index 06bebdb..2913dc6 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java @@ -125,7 +125,7 @@ public class JPAGroup extends AbstractAny<GPlainAttr, GDerAttr, GVirAttr> implem @Override public AnyType getType() { - return ApplicationContextProvider.getApplicationContext().getBean(AnyTypeDAO.class).findGroup(); + return ApplicationContextProvider.getBeanFactory().getBean(AnyTypeDAO.class).findGroup(); } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractProvisioningTask.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractProvisioningTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractProvisioningTask.java index 9723f1d..463408e 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractProvisioningTask.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractProvisioningTask.java @@ -80,15 +80,15 @@ public abstract class AbstractProvisioningTask extends JPASchedTask implements P @Enumerated(EnumType.STRING) protected MatchingRule matchingRule; - public AbstractProvisioningTask(final TaskType type, final String jobClassName) { + public AbstractProvisioningTask(final TaskType type, final String jobDelegateClassName) { super(); this.type = type; - super.setJobClassName(jobClassName); + super.setJobDelegateClassName(jobDelegateClassName); } @Override - public void setJobClassName(final String jobClassName) { + public void setJobDelegateClassName(final String jobClassName) { // fixed to SyncJob, cannot be changed } http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java index 0592a9d..190cc0f 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java @@ -37,7 +37,6 @@ import org.apache.syncope.common.lib.types.TaskType; import org.apache.syncope.core.persistence.api.entity.AnyType; import org.apache.syncope.core.persistence.api.entity.task.AnyFilter; import org.apache.syncope.core.persistence.api.entity.task.PushTask; -import org.apache.syncope.core.provisioning.api.job.PushJob; @Entity @DiscriminatorValue("PushTask") @@ -59,7 +58,7 @@ public class JPAPushTask extends AbstractProvisioningTask implements PushTask { * Default constructor. */ public JPAPushTask() { - super(TaskType.PUSH, PushJob.class.getName()); + super(TaskType.PUSH, null); } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java index 5703380..4f650ba 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java @@ -34,8 +34,7 @@ public class JPASchedTask extends JPATask implements SchedTask { protected String cronExpression; - @NotNull - protected String jobClassName; + protected String jobDelegateClassName; @NotNull protected String name; @@ -58,13 +57,13 @@ public class JPASchedTask extends JPATask implements SchedTask { } @Override - public String getJobClassName() { - return jobClassName; + public String getJobDelegateClassName() { + return jobDelegateClassName; } @Override - public void setJobClassName(final String jobClassName) { - this.jobClassName = jobClassName; + public void setJobDelegateClassName(final String jobDelegateClassName) { + this.jobDelegateClassName = jobDelegateClassName; } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java index 41eb4ea..f2da581 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java @@ -40,7 +40,6 @@ import org.apache.commons.collections4.Predicate; import org.apache.syncope.common.lib.types.TaskType; import org.apache.syncope.core.persistence.api.entity.AnyType; import org.apache.syncope.core.persistence.api.entity.task.SyncTask; -import org.apache.syncope.core.provisioning.api.job.SyncJob; import org.apache.syncope.core.persistence.api.entity.Realm; import org.apache.syncope.core.persistence.api.entity.task.AnyTemplate; import org.apache.syncope.core.persistence.jpa.entity.JPARealm; @@ -73,7 +72,7 @@ public class JPASyncTask extends AbstractProvisioningTask implements SyncTask { * Default constructor. */ public JPASyncTask() { - super(TaskType.SYNCHRONIZATION, SyncJob.class.getName()); + super(TaskType.SYNCHRONIZATION, null); } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java index 88c86fb..1f153da 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java @@ -55,7 +55,6 @@ import org.apache.syncope.core.persistence.api.entity.user.UDerAttr; import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr; import org.apache.syncope.core.persistence.api.entity.user.UVirAttr; import org.apache.syncope.core.persistence.api.entity.user.User; -import org.apache.syncope.core.persistence.jpa.validation.entity.UserCheck; import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResource; import org.apache.syncope.core.persistence.jpa.entity.JPASecurityQuestion; import org.apache.syncope.core.misc.security.Encryptor; @@ -75,7 +74,6 @@ import org.apache.syncope.core.persistence.jpa.entity.JPARole; @Entity @Table(name = JPAUser.TABLE) @Cacheable -@UserCheck public class JPAUser extends AbstractAny<UPlainAttr, UDerAttr, UVirAttr> implements User { private static final long serialVersionUID = -3905046855521446823L; @@ -212,7 +210,7 @@ public class JPAUser extends AbstractAny<UPlainAttr, UDerAttr, UVirAttr> impleme @Override public AnyType getType() { - return ApplicationContextProvider.getApplicationContext().getBean(AnyTypeDAO.class).findUser(); + return ApplicationContextProvider.getBeanFactory().getBean(AnyTypeDAO.class).findUser(); } @Override @@ -252,9 +250,13 @@ public class JPAUser extends AbstractAny<UPlainAttr, UDerAttr, UVirAttr> impleme return clearPassword; } + public void setClearPassword(final String clearPassword) { + this.clearPassword = clearPassword; + } + @Override public void removeClearPassword() { - clearPassword = null; + setClearPassword(null); } @Override http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/CommonEntityManagerFactoryConf.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/CommonEntityManagerFactoryConf.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/CommonEntityManagerFactoryConf.java new file mode 100644 index 0000000..3e44864 --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/CommonEntityManagerFactoryConf.java @@ -0,0 +1,107 @@ +/* + * 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.spring; + +import java.util.HashMap; +import java.util.Map; +import javax.persistence.ValidationMode; +import javax.sql.DataSource; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.core.persistence.api.DomainsHolder; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor; + +/** + * Container for common configuration options among all EntityManagerFactory entities (one for each domain). + * <br/> + * Acts as a commodity place for fetching each domain's {@link DataSource}.. + */ +public class CommonEntityManagerFactoryConf implements DomainsHolder, InitializingBean, ApplicationContextAware { + + private ApplicationContext ctx; + + private final Map<String, DataSource> domains = new HashMap<>(); + + private String[] packagesToScan; + + private ValidationMode validationMode; + + private PersistenceUnitPostProcessor[] postProcessors; + + private final Map<String, Object> jpaPropertyMap = new HashMap<>(); + + @Override + public void setApplicationContext(final ApplicationContext ctx) throws BeansException { + this.ctx = ctx; + } + + @Override + public void afterPropertiesSet() { + for (Map.Entry<String, DataSource> entry : ctx.getBeansOfType(DataSource.class).entrySet()) { + if (!entry.getKey().startsWith("local")) { + this.domains.put( + StringUtils.substringBefore(entry.getKey(), DataSource.class.getSimpleName()), + entry.getValue()); + } + } + } + + @Override + public Map<String, DataSource> getDomains() { + return domains; + } + + public String[] getPackagesToScan() { + return packagesToScan; + } + + public void setPackagesToScan(final String... packagesToScan) { + this.packagesToScan = packagesToScan; + } + + public ValidationMode getValidationMode() { + return validationMode; + } + + public void setValidationMode(final ValidationMode validationMode) { + this.validationMode = validationMode; + } + + public PersistenceUnitPostProcessor[] getPersistenceUnitPostProcessors() { + return postProcessors; + } + + public void setPersistenceUnitPostProcessors(final PersistenceUnitPostProcessor... postProcessors) { + this.postProcessors = postProcessors; + } + + public Map<String, ?> getJpaPropertyMap() { + return jpaPropertyMap; + } + + public void setJpaPropertyMap(final Map<String, ?> jpaProperties) { + if (jpaProperties != null) { + this.jpaPropertyMap.putAll(jpaProperties); + } + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainEntityManagerFactoryBean.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainEntityManagerFactoryBean.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainEntityManagerFactoryBean.java new file mode 100644 index 0000000..a959f96 --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainEntityManagerFactoryBean.java @@ -0,0 +1,45 @@ +/* + * 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.spring; + +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; + +/** + * Extension of {@link LocalContainerEntityManagerFactoryBean} relying on {@link CommonEntityManagerFactoryConf} for + * common configuration options. + */ +public class DomainEntityManagerFactoryBean extends LocalContainerEntityManagerFactoryBean { + + private static final long serialVersionUID = 49152547930966545L; + + public void setCommonEntityManagerFactoryConf(final CommonEntityManagerFactoryConf commonEMFConf) { + super.setJpaPropertyMap(commonEMFConf.getJpaPropertyMap()); + + if (commonEMFConf.getPackagesToScan() != null) { + super.setPackagesToScan(commonEMFConf.getPackagesToScan()); + } + + super.setValidationMode(commonEMFConf.getValidationMode()); + + if (commonEMFConf.getPersistenceUnitPostProcessors() != null) { + super.setPersistenceUnitPostProcessors(commonEMFConf.getPersistenceUnitPostProcessors()); + } + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainTransactionInterceptor.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainTransactionInterceptor.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainTransactionInterceptor.java new file mode 100644 index 0000000..42779ed --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/DomainTransactionInterceptor.java @@ -0,0 +1,70 @@ +/* + * 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.spring; + +import java.lang.reflect.Method; +import org.aopalliance.intercept.MethodInvocation; +import org.apache.syncope.core.misc.security.AuthContextUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.transaction.interceptor.DefaultTransactionAttribute; +import org.springframework.transaction.interceptor.TransactionAttribute; +import org.springframework.transaction.interceptor.TransactionAttributeSource; +import org.springframework.transaction.interceptor.TransactionInterceptor; + +/** + * Extends the standard {@link TransactionInterceptor} by dynamically setting the appropriate + * {@link TransactionAttribute} qualifier according to the authentication domain of the caller - retrieved via + * {@link AuthContextUtils#getDomain()}. + */ +public class DomainTransactionInterceptor extends TransactionInterceptor { + + private static final long serialVersionUID = 5113728988680448551L; + + private static final Logger LOG = LoggerFactory.getLogger(DomainTransactionInterceptor.class); + + @Override + public TransactionAttributeSource getTransactionAttributeSource() { + final TransactionAttributeSource origTxAttrSource = super.getTransactionAttributeSource(); + + return new TransactionAttributeSource() { + + @Override + public TransactionAttribute getTransactionAttribute(final Method method, final Class<?> targetClass) { + TransactionAttribute txAttr = origTxAttrSource.getTransactionAttribute(method, targetClass); + + if (txAttr instanceof DefaultTransactionAttribute) { + ((DefaultTransactionAttribute) txAttr).setQualifier(AuthContextUtils.getDomain()); + } + + return txAttr; + } + }; + } + + @Override + public Object invoke(final MethodInvocation invocation) throws Throwable { + try { + return super.invoke(invocation); + } catch (Throwable e) { + LOG.debug("Error during {} invocation", invocation.getMethod(), e); + throw e; + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/SpringComponentReplacer.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/SpringComponentReplacer.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/SpringComponentReplacer.java new file mode 100644 index 0000000..e983426 --- /dev/null +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/spring/SpringComponentReplacer.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.spring; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.stereotype.Component; +import org.springframework.transaction.interceptor.TransactionInterceptor; + +/** + * Hack for dynamically replacing standard {@link TransactionInterceptor} with + * {@link DomainTransactionInterceptor} in Spring context. + */ +@Component +public class SpringComponentReplacer implements BeanFactoryPostProcessor { + + @Override + public void postProcessBeanFactory(final ConfigurableListableBeanFactory factory) throws BeansException { + for (String name : factory.getBeanNamesForType(TransactionInterceptor.class)) { + BeanDefinition bd = factory.getBeanDefinition(name); + bd.setBeanClassName(DomainTransactionInterceptor.class.getName()); + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/EntityValidationListener.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/EntityValidationListener.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/EntityValidationListener.java index b7616c7..f1df70c 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/EntityValidationListener.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/EntityValidationListener.java @@ -49,7 +49,7 @@ public class EntityValidationListener { @PrePersist @PreUpdate public void validate(final Object object) { - final Validator validator = ApplicationContextProvider.getApplicationContext().getBean(Validator.class); + final Validator validator = ApplicationContextProvider.getBeanFactory().getBean(Validator.class); Set<ConstraintViolation<Object>> violations = validator.validate(object); if (!violations.isEmpty()) { LOG.warn("Bean validation errors found: {}", violations); http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ProvisioningTaskValidator.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ProvisioningTaskValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ProvisioningTaskValidator.java index 2b6e4e0..3c64499 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ProvisioningTaskValidator.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ProvisioningTaskValidator.java @@ -37,11 +37,11 @@ public class ProvisioningTaskValidator extends AbstractValidator<ProvisioningTas } @Override - public boolean isValid(final ProvisioningTask object, final ConstraintValidatorContext context) { - boolean isValid = schedV.isValid(object, context); + public boolean isValid(final ProvisioningTask task, final ConstraintValidatorContext context) { + boolean isValid = schedV.isValid(task, context); if (isValid) { - isValid = object.getResource() != null; + isValid = task.getResource() != null; if (!isValid) { LOG.error("Resource is null"); @@ -51,15 +51,15 @@ public class ProvisioningTaskValidator extends AbstractValidator<ProvisioningTas addPropertyNode("resource").addConstraintViolation(); } - if (!object.getActionsClassNames().isEmpty()) { - for (String className : object.getActionsClassNames()) { + if (!task.getActionsClassNames().isEmpty()) { + for (String className : task.getActionsClassNames()) { Class<?> actionsClass = null; boolean isAssignable = false; try { actionsClass = Class.forName(className); - isAssignable = object instanceof JPASyncTask + isAssignable = task instanceof JPASyncTask ? SyncActions.class.isAssignableFrom(actionsClass) - : object instanceof JPAPushTask + : task instanceof JPAPushTask ? PushActions.class.isAssignableFrom(actionsClass) : false; } catch (Exception e) { http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SchedTaskValidator.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SchedTaskValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SchedTaskValidator.java index 50a6d5d..5c159c2 100644 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SchedTaskValidator.java +++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SchedTaskValidator.java @@ -21,39 +21,43 @@ package org.apache.syncope.core.persistence.jpa.validation.entity; import java.text.ParseException; import javax.validation.ConstraintValidatorContext; +import org.apache.commons.lang3.ClassUtils; import org.apache.syncope.common.lib.types.EntityViolationType; +import org.apache.syncope.core.persistence.api.entity.task.ProvisioningTask; import org.apache.syncope.core.persistence.api.entity.task.SchedTask; +import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate; import org.quartz.CronExpression; -import org.quartz.Job; public class SchedTaskValidator extends AbstractValidator<SchedTaskCheck, SchedTask> { @Override - public boolean isValid(final SchedTask object, final ConstraintValidatorContext context) { - boolean isValid; + public boolean isValid(final SchedTask task, final ConstraintValidatorContext context) { + boolean isValid = true; - Class<?> jobClass = null; - try { - jobClass = Class.forName(object.getJobClassName()); - isValid = Job.class.isAssignableFrom(jobClass); - } catch (Exception e) { - LOG.error("Invalid Job class specified", e); - isValid = false; - } - if (jobClass == null || !isValid) { - isValid = false; + if (!(task instanceof ProvisioningTask)) { + Class<?> jobDelegateClass = null; + try { + jobDelegateClass = ClassUtils.getClass(task.getJobDelegateClassName()); + isValid = SchedTaskJobDelegate.class.isAssignableFrom(jobDelegateClass); + } catch (Exception e) { + LOG.error("Invalid JobDelegate class specified", e); + isValid = false; + } + if (jobDelegateClass == null || !isValid) { + isValid = false; - context.disableDefaultConstraintViolation(); - context.buildConstraintViolationWithTemplate( - getTemplate(EntityViolationType.InvalidSchedTask, "Invalid job class name")). - addPropertyNode("jobClassName").addConstraintViolation(); + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate( + getTemplate(EntityViolationType.InvalidSchedTask, "Invalid job delegate class name")). + addPropertyNode("jobDelegateClassName").addConstraintViolation(); + } } - if (isValid && object.getCronExpression() != null) { + if (isValid && task.getCronExpression() != null) { try { - new CronExpression(object.getCronExpression()); + new CronExpression(task.getCronExpression()); } catch (ParseException e) { - LOG.error("Invalid cron expression '" + object.getCronExpression() + "'", e); + LOG.error("Invalid cron expression '" + task.getCronExpression() + "'", e); isValid = false; context.disableDefaultConstraintViolation(); http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/UserCheck.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/UserCheck.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/UserCheck.java deleted file mode 100644 index 2d9fec6..0000000 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/UserCheck.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 = UserValidator.class) -@Documented -public @interface UserCheck { - - String message() default "{org.apache.syncope.core.persistence.validation.user}"; - - Class<?>[] groups() default {}; - - Class<? extends Payload>[] payload() default {}; -} http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/UserValidator.java ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/UserValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/UserValidator.java deleted file mode 100644 index e142de3..0000000 --- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/UserValidator.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * 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.util.ArrayList; -import java.util.List; -import javax.annotation.Resource; -import javax.validation.ConstraintValidatorContext; -import org.apache.syncope.common.lib.types.AccountPolicySpec; -import org.apache.syncope.common.lib.types.EntityViolationType; -import org.apache.syncope.common.lib.types.PasswordPolicySpec; -import org.apache.syncope.core.persistence.api.entity.AccountPolicy; -import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource; -import org.apache.syncope.core.persistence.api.entity.PasswordPolicy; -import org.apache.syncope.core.persistence.api.entity.Policy; -import org.apache.syncope.core.persistence.api.entity.user.User; -import org.apache.syncope.core.misc.policy.AccountPolicyEnforcer; -import org.apache.syncope.core.misc.policy.AccountPolicyException; -import org.apache.syncope.core.misc.policy.PasswordPolicyEnforcer; -import org.apache.syncope.core.misc.policy.PolicyEvaluator; -import org.apache.syncope.core.persistence.api.dao.RealmDAO; -import org.apache.syncope.core.persistence.api.dao.UserDAO; -import org.apache.syncope.core.persistence.api.entity.Realm; -import org.springframework.beans.factory.annotation.Autowired; - -public class UserValidator extends AbstractValidator<UserCheck, User> { - - @Resource(name = "adminUser") - private String adminUser; - - @Resource(name = "anonymousUser") - private String anonymousUser; - - @Autowired - private UserDAO userDAO; - - @Autowired - private RealmDAO realmDAO; - - @Autowired - private PolicyEvaluator evaluator; - - @Autowired - private PasswordPolicyEnforcer ppEnforcer; - - @Autowired - private AccountPolicyEnforcer apEnforcer; - - @Override - public boolean isValid(final User user, final ConstraintValidatorContext context) { - context.disableDefaultConstraintViolation(); - - // need to treat it explicitly, otherwise policy evaluation will silently fail - if (user.getRealm() == null) { - context.buildConstraintViolationWithTemplate( - getTemplate(EntityViolationType.InvalidRealm, "realm not specified")). - addPropertyNode("realm").addConstraintViolation(); - - return false; - } - - // ------------------------------ - // Verify password policies - // ------------------------------ - LOG.debug("Password Policy enforcement"); - - try { - int maxPPSpecHistory = 0; - for (Policy policy : getPasswordPolicies(user)) { - // evaluate policy - PasswordPolicySpec ppSpec = evaluator.evaluate(policy, user); - // enforce policy - ppEnforcer.enforce(ppSpec, policy.getType(), user); - - if (ppSpec.getHistoryLength() > maxPPSpecHistory) { - maxPPSpecHistory = ppSpec.getHistoryLength(); - } - } - - // update user's password history with encrypted password - if (maxPPSpecHistory > 0 && user.getPassword() != null) { - user.getPasswordHistory().add(user.getPassword()); - } - // keep only the last maxPPSpecHistory items in user's password history - if (maxPPSpecHistory < user.getPasswordHistory().size()) { - for (int i = 0; i < user.getPasswordHistory().size() - maxPPSpecHistory; i++) { - user.getPasswordHistory().remove(i); - } - } - } catch (Exception e) { - LOG.debug("Invalid password"); - - context.buildConstraintViolationWithTemplate( - getTemplate(EntityViolationType.InvalidPassword, e.getMessage())). - addPropertyNode("password").addConstraintViolation(); - - return false; - } finally { - // password has been validated, let's remove its clear version - user.removeClearPassword(); - } - // ------------------------------ - - // ------------------------------ - // Verify account policies - // ------------------------------ - LOG.debug("Account Policy enforcement"); - - try { - if (adminUser.equals(user.getUsername()) || anonymousUser.equals(user.getUsername())) { - throw new AccountPolicyException("Not allowed: " + user.getUsername()); - } - - // invalid username - for (Policy policy : getAccountPolicies(user)) { - // evaluate policy - AccountPolicySpec accountPolicy = evaluator.evaluate(policy, user); - - // enforce policy - apEnforcer.enforce(accountPolicy, policy.getType(), user); - } - } catch (Exception e) { - LOG.debug("Invalid username"); - - context.buildConstraintViolationWithTemplate( - getTemplate(EntityViolationType.InvalidUsername, e.getMessage())). - addPropertyNode("username").addConstraintViolation(); - - return false; - } - // ------------------------------ - - return true; - } - - private List<PasswordPolicy> getPasswordPolicies(final User user) { - List<PasswordPolicy> policies = new ArrayList<>(); - - PasswordPolicy policy; - - // add resource policies - for (ExternalResource resource : userDAO.findAllResources(user)) { - policy = resource.getPasswordPolicy(); - if (policy != null) { - policies.add(policy); - } - } - - // add realm policies - for (Realm realm : realmDAO.findAncestors(user.getRealm())) { - policy = realm.getPasswordPolicy(); - if (policy != null) { - policies.add(policy); - } - } - - return policies; - } - - private List<AccountPolicy> getAccountPolicies(final User user) { - List<AccountPolicy> policies = new ArrayList<>(); - - AccountPolicy policy; - - // add resource policies - for (ExternalResource resource : userDAO.findAllResources(user)) { - policy = resource.getAccountPolicy(); - if (policy != null) { - policies.add(policy); - } - } - - // add realm policies - for (Realm realm : realmDAO.findAncestors(user.getRealm())) { - policy = realm.getAccountPolicy(); - if (policy != null) { - policies.add(policy); - } - } - - return policies; - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/resources/audit/audit.sql ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/resources/audit/audit.sql b/core/persistence-jpa/src/main/resources/audit/audit.sql index faf8c5b..44ffb17 100644 --- a/core/persistence-jpa/src/main/resources/audit/audit.sql +++ b/core/persistence-jpa/src/main/resources/audit/audit.sql @@ -21,4 +21,6 @@ CREATE TABLE IF NOT EXISTS SYNCOPEAUDIT ( LOGGER VARCHAR(255) NOT NULL, MESSAGE TEXT NOT NULL, THROWABLE TEXT -) +); + +COMMIT; http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/resources/content.xml ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/resources/content.xml b/core/persistence-jpa/src/main/resources/content.xml deleted file mode 100644 index caba10e..0000000 --- a/core/persistence-jpa/src/main/resources/content.xml +++ /dev/null @@ -1,117 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -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. ---> -<dataset> - <Realm id="1" name="/"/> - - <SyncopeConf id="1" - creator="admin" lastModifier="admin" - creationDate="2014-06-20 11:00:00" lastChangeDate="2014-06-20 11:00:00"/> - - <PlainSchema name="password.cipher.algorithm" type="String" - mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="1" owner_id="1" schema_name="password.cipher.algorithm"/> - <CPlainAttrValue id="1" attribute_id="1" stringValue="SHA1"/> - - <!-- notificationjob.cronExpression: - + not existing: NotificationJob runs according to Notification.DEFAULT_CRON_EXP - + provided as empty string: NotificationJob disabled - + provided as non-empty string: NotificationJob runs according to the given value --> - <PlainSchema name="notificationjob.cronExpression" type="String" - mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="2" owner_id="1" schema_name="notificationjob.cronExpression"/> - <CPlainAttrValue id="2" attribute_id="2" stringValue=""/> - - <PlainSchema name="notification.maxRetries" type="Long" - mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="3" owner_id="1" schema_name="notification.maxRetries"/> - <CPlainAttrValue id="3" attribute_id="3" longValue="3"/> - - <PlainSchema name="token.length" type="Long" - mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="4" owner_id="1" schema_name="token.length"/> - <CPlainAttrValue id="4" attribute_id="4" longValue="256"/> - - <PlainSchema name="token.expireTime" type="Long" - mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="5" owner_id="1" schema_name="token.expireTime"/> - <CPlainAttrValue id="5" attribute_id="5" longValue="60"/> - - <PlainSchema name="selfRegistration.allowed" type="Boolean" - mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="6" owner_id="1" schema_name="selfRegistration.allowed"/> - <CPlainAttrValue id="6" attribute_id="6" booleanValue="1"/> - - <PlainSchema name="passwordReset.allowed" type="Boolean" - mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="7" owner_id="1" schema_name="passwordReset.allowed"/> - <CPlainAttrValue id="7" attribute_id="7" booleanValue="1"/> - - <PlainSchema name="passwordReset.securityQuestion" type="Boolean" - mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="8" owner_id="1" schema_name="passwordReset.securityQuestion"/> - <CPlainAttrValue id="8" attribute_id="8" booleanValue="1"/> - - <PlainSchema name="authentication.statuses" type="String" - mandatoryCondition="true" multivalue="1" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="9" owner_id="1" schema_name="authentication.statuses"/> - <CPlainAttrValue id="9" attribute_id="9" stringValue="created"/> - <CPlainAttrValue id="10" attribute_id="9" stringValue="active"/> - - <!-- Save user login date upon successful authentication --> - <PlainSchema name="log.lastlogindate" type="Boolean" - mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="11" owner_id="1" schema_name="log.lastlogindate"/> - <CPlainAttrValue id="11" attribute_id="11" booleanValue="1"/> - - <PlainSchema name="tasks.interruptMaxRetries" type="Long" - mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/> - <CPlainAttr id="12" owner_id="1" schema_name="tasks.interruptMaxRetries"/> - <CPlainAttrValue id="12" attribute_id="12" longValue="20"/> - - <!-- For usage with admin console --> - <PlainSchema name="admin.user.layout" type="String" - mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/> - <PlainSchema name="self.user.layout" type="String" - mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/> - <PlainSchema name="admin.group.layout" type="String" - mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/> - <PlainSchema name="self.group.layout" type="String" - mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/> - <PlainSchema name="admin.membership.layout" type="String" - mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/> - <PlainSchema name="self.membership.layout" type="String" - mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/> - - <PlainSchema name="email" type="String" - mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0" - validatorClass="org.apache.syncope.core.persistence.jpa.attrvalue.validation.EmailAddressValidator"/> - - <!-- Password reset notifications --> - <Notification id="1" active="1" recipientAttrName="email" recipientAttrType="UserPlainSchema" selfAsRecipient="1" - sender="[email protected]" subject="Password Reset request" template="requestPasswordReset" - traceLevel="FAILURES" userAbout="token!=$null"/> - <Notification_events Notification_id="1" event="[CUSTOM]:[]:[]:[requestPasswordReset]:[SUCCESS]"/> - - <Notification id="2" active="1" recipientAttrName="email" recipientAttrType="UserPlainSchema" selfAsRecipient="1" - sender="[email protected]" subject="Password Reset successful" template="confirmPasswordReset" - traceLevel="FAILURES" userAbout="token!=$null"/> - <Notification_events Notification_id="2" event="[CUSTOM]:[]:[]:[confirmPasswordReset]:[SUCCESS]"/> - -</dataset> http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/resources/domains.xml ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/resources/domains.xml b/core/persistence-jpa/src/main/resources/domains.xml new file mode 100644 index 0000000..43fce14 --- /dev/null +++ b/core/persistence-jpa/src/main/resources/domains.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +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. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + 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"> + + <import resource="classpath*:domains/*Domain.xml"/> + + <bean id="commonEMFConf" class="org.apache.syncope.core.persistence.jpa.spring.CommonEntityManagerFactoryConf"> + <property name="packagesToScan" value="org.apache.syncope.core.persistence.jpa.entity"/> + <property name="validationMode" value="NONE"/> + <property name="persistenceUnitPostProcessors"> + <list> + <bean class="org.apache.syncope.core.persistence.jpa.spring.MultiJarAwarePersistenceUnitPostProcessor"/> + </list> + </property> + <property name="jpaPropertyMap"> + <map> + <entry key="openjpa.Log" value="slf4j"/> + <!--<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.DataCache" value="true"/> + <entry key="openjpa.QueryCache" value="true"/> + <entry key="openjpa.RemoteCommitProvider" value="sjvm"/> + </map> + </property> + </bean> + +</beans> http://git-wip-us.apache.org/repos/asf/syncope/blob/6dfedd8f/core/persistence-jpa/src/main/resources/domains/Master.properties ---------------------------------------------------------------------- diff --git a/core/persistence-jpa/src/main/resources/domains/Master.properties b/core/persistence-jpa/src/main/resources/domains/Master.properties new file mode 100644 index 0000000..177e988 --- /dev/null +++ b/core/persistence-jpa/src/main/resources/domains/Master.properties @@ -0,0 +1,28 @@ +# 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. +Master.driverClassName=org.postgresql.Driver +Master.url=jdbc:postgresql://localhost:5432/syncope +Master.schema= +Master.username=syncope +Master.password=syncope +Master.databasePlatform=org.apache.openjpa.jdbc.sql.PostgresDictionary +Master.orm=META-INF/spring-orm.xml + +# note: other connection pool settings can also be configured here, see DataSource definition +Master.pool.validationQuery=SELECT 1 + +Master.audit.sql=audit.sql
