You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by md...@apache.org on 2015/08/27 13:12:38 UTC
[11/33] syncope git commit: Merge branch 'master' of
https://git-wip-us.apache.org/repos/asf/syncope
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java
index 0000000,0000000..8eaad0e
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/DefaultPasswordRule.java
@@@ -1,0 -1,0 +1,218 @@@
++/*
++ * 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 org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
++import org.apache.syncope.common.lib.policy.PasswordRuleConf;
++import org.apache.syncope.core.misc.policy.PasswordPolicyException;
++import org.apache.syncope.core.misc.policy.PolicyPattern;
++import org.apache.syncope.core.persistence.api.dao.PasswordRule;
++import org.apache.syncope.core.persistence.api.dao.PasswordRuleConfClass;
++import org.apache.syncope.core.persistence.api.entity.PlainAttr;
++import org.apache.syncope.core.persistence.api.entity.user.User;
++import org.springframework.transaction.annotation.Transactional;
++
++@PasswordRuleConfClass(DefaultPasswordRuleConf.class)
++public class DefaultPasswordRule implements PasswordRule {
++
++ private DefaultPasswordRuleConf conf;
++
++ @Override
++ public void setConf(final PasswordRuleConf conf) {
++ if (conf instanceof DefaultPasswordRuleConf) {
++ this.conf = (DefaultPasswordRuleConf) conf;
++ } else {
++ throw new IllegalArgumentException(
++ PasswordRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
++ }
++ }
++
++ @Transactional(readOnly = true)
++ @Override
++ public void isCompliant(final User user) {
++ for (String schema : conf.getSchemasNotPermitted()) {
++ PlainAttr<?> attr = user.getPlainAttr(schema);
++ if (attr != null) {
++ List<String> values = attr.getValuesAsStrings();
++ if (values != null && !values.isEmpty()) {
++ conf.getWordsNotPermitted().add(values.get(0));
++ }
++ }
++ }
++
++ String clearPassword = user.getClearPassword();
++ String password = user.getPassword();
++
++ if (password != null && clearPassword != null) {
++ // check length
++ if (conf.getMinLength() > 0 && conf.getMinLength() > clearPassword.length()) {
++ throw new PasswordPolicyException("Password too short");
++ }
++
++ if (conf.getMaxLength() > 0 && conf.getMaxLength() < clearPassword.length()) {
++ throw new PasswordPolicyException("Password too long");
++ }
++
++ // check words not permitted
++ for (String word : conf.getWordsNotPermitted()) {
++ if (clearPassword.contains(word)) {
++ throw new PasswordPolicyException("Used word(s) not permitted");
++ }
++ }
++
++ // check digits occurrence
++ if (conf.isDigitRequired() && !checkDigit(clearPassword)) {
++ throw new PasswordPolicyException("Password must contain digit(s)");
++ }
++
++ // check lowercase alphabetic characters occurrence
++ if (conf.isLowercaseRequired() && !checkLowercase(clearPassword)) {
++ throw new PasswordPolicyException("Password must contain lowercase alphabetic character(s)");
++ }
++
++ // check uppercase alphabetic characters occurrence
++ if (conf.isUppercaseRequired() && !checkUppercase(clearPassword)) {
++ throw new PasswordPolicyException("Password must contain uppercase alphabetic character(s)");
++ }
++
++ // check prefix
++ for (String prefix : conf.getPrefixesNotPermitted()) {
++ if (clearPassword.startsWith(prefix)) {
++ throw new PasswordPolicyException("Prefix not permitted");
++ }
++ }
++
++ // check suffix
++ for (String suffix : conf.getSuffixesNotPermitted()) {
++ if (clearPassword.endsWith(suffix)) {
++ throw new PasswordPolicyException("Suffix not permitted");
++ }
++ }
++
++ // check digit first occurrence
++ if (conf.isMustStartWithDigit() && !checkFirstDigit(clearPassword)) {
++ throw new PasswordPolicyException("Password must start with a digit");
++ }
++
++ if (conf.isMustntStartWithDigit() && checkFirstDigit(clearPassword)) {
++ throw new PasswordPolicyException("Password mustn't start with a digit");
++ }
++
++ // check digit last occurrence
++ if (conf.isMustEndWithDigit() && !checkLastDigit(clearPassword)) {
++ throw new PasswordPolicyException("Password must end with a digit");
++ }
++
++ if (conf.isMustntEndWithDigit() && checkLastDigit(clearPassword)) {
++ throw new PasswordPolicyException("Password mustn't end with a digit");
++ }
++
++ // check alphanumeric characters occurence
++ if (conf.isAlphanumericRequired() && !checkAlphanumeric(clearPassword)) {
++ throw new PasswordPolicyException("Password must contain alphanumeric character(s)");
++ }
++
++ // check non alphanumeric characters occurence
++ if (conf.isNonAlphanumericRequired() && !checkNonAlphanumeric(clearPassword)) {
++ throw new PasswordPolicyException("Password must contain non-alphanumeric character(s)");
++ }
++
++ // check alphanumeric character first occurrence
++ if (conf.isMustStartWithAlpha() && !checkFirstAlphanumeric(clearPassword)) {
++ throw new PasswordPolicyException("Password must start with an alphanumeric character");
++ }
++
++ if (conf.isMustntStartWithAlpha() && checkFirstAlphanumeric(clearPassword)) {
++ throw new PasswordPolicyException("Password mustn't start with an alphanumeric character");
++ }
++
++ // check alphanumeric character last occurrence
++ if (conf.isMustEndWithAlpha() && !checkLastAlphanumeric(clearPassword)) {
++ throw new PasswordPolicyException("Password must end with an alphanumeric character");
++ }
++
++ if (conf.isMustntEndWithAlpha() && checkLastAlphanumeric(clearPassword)) {
++ throw new PasswordPolicyException("Password mustn't end with an alphanumeric character");
++ }
++
++ // check non alphanumeric character first occurrence
++ if (conf.isMustStartWithNonAlpha() && !checkFirstNonAlphanumeric(clearPassword)) {
++ throw new PasswordPolicyException("Password must start with a non-alphanumeric character");
++ }
++
++ if (conf.isMustntStartWithNonAlpha() && checkFirstNonAlphanumeric(clearPassword)) {
++ throw new PasswordPolicyException("Password mustn't start with a non-alphanumeric character");
++ }
++
++ // check non alphanumeric character last occurrence
++ if (conf.isMustEndWithNonAlpha() && !checkLastNonAlphanumeric(clearPassword)) {
++ throw new PasswordPolicyException("Password must end with a non-alphanumeric character");
++ }
++
++ if (conf.isMustntEndWithNonAlpha() && checkLastNonAlphanumeric(clearPassword)) {
++ throw new PasswordPolicyException("Password mustn't end with a non-alphanumeric character");
++ }
++ }
++ }
++
++ private boolean checkDigit(final String str) {
++ return PolicyPattern.DIGIT.matcher(str).matches();
++ }
++
++ private boolean checkLowercase(final String str) {
++ return PolicyPattern.ALPHA_LOWERCASE.matcher(str).matches();
++ }
++
++ private boolean checkUppercase(final String str) {
++ return PolicyPattern.ALPHA_UPPERCASE.matcher(str).matches();
++ }
++
++ private boolean checkFirstDigit(final String str) {
++ return PolicyPattern.FIRST_DIGIT.matcher(str).matches();
++ }
++
++ private boolean checkLastDigit(final String str) {
++ return PolicyPattern.LAST_DIGIT.matcher(str).matches();
++ }
++
++ private boolean checkAlphanumeric(final String str) {
++ return PolicyPattern.ALPHANUMERIC.matcher(str).matches();
++ }
++
++ private boolean checkFirstAlphanumeric(final String str) {
++ return PolicyPattern.FIRST_ALPHANUMERIC.matcher(str).matches();
++ }
++
++ private boolean checkLastAlphanumeric(final String str) {
++ return PolicyPattern.LAST_ALPHANUMERIC.matcher(str).matches();
++ }
++
++ private boolean checkNonAlphanumeric(final String str) {
++ return PolicyPattern.NON_ALPHANUMERIC.matcher(str).matches();
++ }
++
++ private boolean checkFirstNonAlphanumeric(final String str) {
++ return PolicyPattern.FIRST_NON_ALPHANUMERIC.matcher(str).matches();
++ }
++
++ private boolean checkLastNonAlphanumeric(final String str) {
++ return PolicyPattern.LAST_NON_ALPHANUMERIC.matcher(str).matches();
++ }
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/AbstractPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/AbstractPolicy.java
index 0000000,0000000..843bbcd
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/AbstractPolicy.java
@@@ -1,0 -1,0 +1,67 @@@
++/*
++ * 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.policy;
++
++import javax.persistence.Entity;
++import javax.persistence.EnumType;
++import javax.persistence.Enumerated;
++import javax.persistence.Id;
++import javax.persistence.Inheritance;
++import javax.persistence.InheritanceType;
++import javax.validation.constraints.NotNull;
++import org.apache.syncope.common.lib.types.PolicyType;
++import org.apache.syncope.core.persistence.api.entity.Policy;
++import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
++
++@Entity
++@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
++public abstract class AbstractPolicy extends AbstractEntity<Long> implements Policy {
++
++ private static final long serialVersionUID = -5844833125843247458L;
++
++ @Id
++ private Long id;
++
++ @NotNull
++ private String description;
++
++ @NotNull
++ @Enumerated(EnumType.STRING)
++ protected PolicyType type;
++
++ @Override
++ public Long getKey() {
++ return id;
++ }
++
++ @Override
++ public String getDescription() {
++ return description;
++ }
++
++ @Override
++ public void setDescription(final String description) {
++ this.description = description;
++ }
++
++ @Override
++ public PolicyType getType() {
++ return type;
++ }
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
index 0000000,0000000..87aa04f
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
@@@ -1,0 -1,0 +1,160 @@@
++/*
++ * 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.policy;
++
++import java.util.ArrayList;
++import java.util.HashSet;
++import java.util.List;
++import java.util.Set;
++import javax.persistence.Basic;
++import javax.persistence.CascadeType;
++import javax.persistence.Entity;
++import javax.persistence.FetchType;
++import javax.persistence.JoinColumn;
++import javax.persistence.JoinTable;
++import javax.persistence.ManyToMany;
++import javax.persistence.OneToMany;
++import javax.persistence.Table;
++import javax.validation.constraints.Max;
++import javax.validation.constraints.Min;
++import org.apache.commons.collections4.CollectionUtils;
++import org.apache.commons.collections4.Predicate;
++import org.apache.commons.collections4.Transformer;
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++import org.apache.syncope.common.lib.types.PolicyType;
++import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
++import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
++import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResource;
++
++@Entity
++@Table(name = JPAAccountPolicy.TABLE)
++public class JPAAccountPolicy extends AbstractPolicy implements AccountPolicy {
++
++ private static final long serialVersionUID = -2767606675667839060L;
++
++ public static final String TABLE = "AccountPolicy";
++
++ @Basic
++ @Min(0)
++ @Max(1)
++ private Integer propagateSuspension;
++
++ private int maxAuthenticationAttempts;
++
++ @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "accountPolicy")
++ private List<JPAAccountRuleConfInstance> ruleConfs;
++
++ /**
++ * Resources for alternative user authentication: if empty, only internal storage will be used.
++ */
++ @ManyToMany(fetch = FetchType.EAGER)
++ @JoinTable(joinColumns =
++ @JoinColumn(name = "accountPolicy_id"),
++ inverseJoinColumns =
++ @JoinColumn(name = "resource_name"))
++ private Set<JPAExternalResource> resources = new HashSet<>();
++
++ public JPAAccountPolicy() {
++ super();
++ this.type = PolicyType.ACCOUNT;
++ }
++
++ @Override
++ public boolean isPropagateSuspension() {
++ return isBooleanAsInteger(propagateSuspension);
++ }
++
++ @Override
++ public void setPropagateSuspension(final boolean propagateSuspension) {
++ this.propagateSuspension = getBooleanAsInteger(propagateSuspension);
++ }
++
++ @Override
++ public int getMaxAuthenticationAttempts() {
++ return maxAuthenticationAttempts;
++ }
++
++ @Override
++ public void setMaxAuthenticationAttempts(final int maxAuthenticationAttempts) {
++ this.maxAuthenticationAttempts = maxAuthenticationAttempts;
++ }
++
++ @Override
++ public boolean add(final AccountRuleConf accountRuleConf) {
++ if (accountRuleConf == null) {
++ return false;
++ }
++
++ JPAAccountRuleConfInstance instance = new JPAAccountRuleConfInstance();
++ instance.setAccountPolicy(this);
++ instance.setInstance(accountRuleConf);
++
++ return ruleConfs.add(instance);
++ }
++
++ @Override
++ public boolean remove(final AccountRuleConf accountRuleConf) {
++ return CollectionUtils.filter(ruleConfs, new Predicate<JPAAccountRuleConfInstance>() {
++
++ @Override
++ public boolean evaluate(final JPAAccountRuleConfInstance object) {
++ return accountRuleConf.equals(object.getInstance());
++ }
++ });
++ }
++
++ @Override
++ public List<AccountRuleConf> getRuleConfs() {
++ return CollectionUtils.collect(ruleConfs, new Transformer<JPAAccountRuleConfInstance, AccountRuleConf>() {
++
++ @Override
++ public AccountRuleConf transform(final JPAAccountRuleConfInstance input) {
++ return input.getInstance();
++ }
++ }, new ArrayList<AccountRuleConf>());
++ }
++
++ @Override
++ public boolean add(final ExternalResource resource) {
++ checkType(resource, JPAExternalResource.class);
++ return resources.add((JPAExternalResource) resource);
++ }
++
++ @Override
++ public boolean remove(final ExternalResource resource) {
++ checkType(resource, JPAExternalResource.class);
++ return resources.remove((JPAExternalResource) resource);
++ }
++
++ @Override
++ public Set<? extends ExternalResource> getResources() {
++ return resources;
++ }
++
++ @Override
++ public Set<String> getResourceNames() {
++ return CollectionUtils.collect(getResources(), new Transformer<ExternalResource, String>() {
++
++ @Override
++ public String transform(final ExternalResource input) {
++ return input.getKey();
++ }
++ }, new HashSet<String>());
++ }
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountRuleConfInstance.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountRuleConfInstance.java
index 0000000,0000000..782e6b4
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountRuleConfInstance.java
@@@ -1,0 -1,0 +1,73 @@@
++/*
++ * 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.policy;
++
++import javax.persistence.Entity;
++import javax.persistence.Id;
++import javax.persistence.Lob;
++import javax.persistence.ManyToOne;
++import javax.persistence.Table;
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++import org.apache.syncope.core.misc.serialization.POJOHelper;
++import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
++import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
++
++@Entity
++@Table(name = JPAAccountRuleConfInstance.TABLE)
++public class JPAAccountRuleConfInstance extends AbstractEntity<Long> {
++
++ private static final long serialVersionUID = -2436055132955674610L;
++
++ public static final String TABLE = "AccountRuleConfInstance";
++
++ @Id
++ private Long id;
++
++ @Lob
++ private String serializedInstance;
++
++ @ManyToOne
++ private JPAAccountPolicy accountPolicy;
++
++ @Override
++ public Long getKey() {
++ return id;
++ }
++
++ public AccountPolicy getAccountPolicy() {
++ return accountPolicy;
++ }
++
++ public void setAccountPolicy(final AccountPolicy report) {
++ checkType(report, JPAAccountPolicy.class);
++ this.accountPolicy = (JPAAccountPolicy) report;
++ }
++
++ public AccountRuleConf getInstance() {
++ return serializedInstance == null
++ ? null
++ : POJOHelper.deserialize(serializedInstance, AccountRuleConf.class);
++ }
++
++ public void setInstance(final AccountRuleConf instance) {
++ this.serializedInstance = instance == null
++ ? null
++ : POJOHelper.serialize(instance);
++ }
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
index 0000000,0000000..1491c25
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
@@@ -1,0 -1,0 +1,115 @@@
++/*
++ * 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.policy;
++
++import java.util.ArrayList;
++import java.util.List;
++import javax.persistence.Basic;
++import javax.persistence.CascadeType;
++import javax.persistence.Entity;
++import javax.persistence.FetchType;
++import javax.persistence.OneToMany;
++import javax.persistence.Table;
++import javax.validation.constraints.Max;
++import javax.validation.constraints.Min;
++import org.apache.commons.collections4.CollectionUtils;
++import org.apache.commons.collections4.Predicate;
++import org.apache.commons.collections4.Transformer;
++import org.apache.syncope.common.lib.policy.PasswordRuleConf;
++import org.apache.syncope.common.lib.types.PolicyType;
++import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
++
++@Entity
++@Table(name = JPAPasswordPolicy.TABLE)
++public class JPAPasswordPolicy extends AbstractPolicy implements PasswordPolicy {
++
++ private static final long serialVersionUID = 9138550910385232849L;
++
++ public static final String TABLE = "PasswordPolicy";
++
++ @Basic
++ @Min(0)
++ @Max(1)
++ private Integer allowNullPassword;
++
++ private int historyLength;
++
++ @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "passwordPolicy")
++ private List<JPAPasswordRuleConfInstance> ruleConfs;
++
++ public JPAPasswordPolicy() {
++ super();
++ this.type = PolicyType.PASSWORD;
++ }
++
++ @Override
++ public boolean isAllowNullPassword() {
++ return isBooleanAsInteger(allowNullPassword);
++ }
++
++ @Override
++ public void setAllowNullPassword(final boolean allowNullPassword) {
++ this.allowNullPassword = getBooleanAsInteger(allowNullPassword);
++ }
++
++ @Override
++ public int getHistoryLength() {
++ return historyLength;
++ }
++
++ @Override
++ public void setHistoryLength(final int historyLength) {
++ this.historyLength = historyLength;
++ }
++
++ @Override
++ public boolean add(final PasswordRuleConf passwordRuleConf) {
++ if (passwordRuleConf == null) {
++ return false;
++ }
++
++ JPAPasswordRuleConfInstance instance = new JPAPasswordRuleConfInstance();
++ instance.setPasswordPolicy(this);
++ instance.setInstance(passwordRuleConf);
++
++ return ruleConfs.add(instance);
++ }
++
++ @Override
++ public boolean remove(final PasswordRuleConf passwordRuleConf) {
++ return CollectionUtils.filter(ruleConfs, new Predicate<JPAPasswordRuleConfInstance>() {
++
++ @Override
++ public boolean evaluate(final JPAPasswordRuleConfInstance object) {
++ return passwordRuleConf.equals(object.getInstance());
++ }
++ });
++ }
++
++ @Override
++ public List<PasswordRuleConf> getRuleConfs() {
++ return CollectionUtils.collect(ruleConfs, new Transformer<JPAPasswordRuleConfInstance, PasswordRuleConf>() {
++
++ @Override
++ public PasswordRuleConf transform(final JPAPasswordRuleConfInstance input) {
++ return input.getInstance();
++ }
++ }, new ArrayList<PasswordRuleConf>());
++ }
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordRuleConfInstance.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordRuleConfInstance.java
index 0000000,0000000..4b39dc8
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordRuleConfInstance.java
@@@ -1,0 -1,0 +1,73 @@@
++/*
++ * 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.policy;
++
++import javax.persistence.Entity;
++import javax.persistence.Id;
++import javax.persistence.Lob;
++import javax.persistence.ManyToOne;
++import javax.persistence.Table;
++import org.apache.syncope.common.lib.policy.PasswordRuleConf;
++import org.apache.syncope.core.misc.serialization.POJOHelper;
++import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
++import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
++
++@Entity
++@Table(name = JPAPasswordRuleConfInstance.TABLE)
++public class JPAPasswordRuleConfInstance extends AbstractEntity<Long> {
++
++ private static final long serialVersionUID = -2436055132955674610L;
++
++ public static final String TABLE = "PasswordRuleConfInstance";
++
++ @Id
++ private Long id;
++
++ @Lob
++ private String serializedInstance;
++
++ @ManyToOne
++ private JPAPasswordPolicy passwordPolicy;
++
++ @Override
++ public Long getKey() {
++ return id;
++ }
++
++ public PasswordPolicy getPasswordPolicy() {
++ return passwordPolicy;
++ }
++
++ public void setPasswordPolicy(final PasswordPolicy report) {
++ checkType(report, JPAPasswordPolicy.class);
++ this.passwordPolicy = (JPAPasswordPolicy) report;
++ }
++
++ public PasswordRuleConf getInstance() {
++ return serializedInstance == null
++ ? null
++ : POJOHelper.deserialize(serializedInstance, PasswordRuleConf.class);
++ }
++
++ public void setInstance(final PasswordRuleConf instance) {
++ this.serializedInstance = instance == null
++ ? null
++ : POJOHelper.serialize(instance);
++ }
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPushPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPushPolicy.java
index 0000000,0000000..3bc0009
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPushPolicy.java
@@@ -1,0 -1,0 +1,55 @@@
++/*
++ * 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.policy;
++
++import javax.persistence.Entity;
++import javax.persistence.Lob;
++import javax.persistence.Table;
++import org.apache.syncope.common.lib.types.PolicyType;
++import org.apache.syncope.common.lib.policy.PushPolicySpec;
++import org.apache.syncope.core.misc.serialization.POJOHelper;
++import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
++
++@Entity
++@Table(name = JPAPushPolicy.TABLE)
++public class JPAPushPolicy extends AbstractPolicy implements PushPolicy {
++
++ private static final long serialVersionUID = -5875589156893921113L;
++
++ public static final String TABLE = "PushPolicy";
++
++ @Lob
++ private String specification;
++
++ public JPAPushPolicy() {
++ super();
++ this.type = PolicyType.PUSH;
++ }
++
++ @Override
++ public PushPolicySpec getSpecification() {
++ return POJOHelper.deserialize(specification, PushPolicySpec.class);
++ }
++
++ @Override
++ public void setSpecification(final PushPolicySpec policy) {
++ this.specification = POJOHelper.serialize(policy);
++ }
++
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPASyncPolicy.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPASyncPolicy.java
index 0000000,0000000..913ee54
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPASyncPolicy.java
@@@ -1,0 -1,0 +1,54 @@@
++/*
++ * 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.policy;
++
++import javax.persistence.Entity;
++import javax.persistence.Lob;
++import javax.persistence.Table;
++import org.apache.syncope.common.lib.policy.SyncPolicySpec;
++import org.apache.syncope.common.lib.types.PolicyType;
++import org.apache.syncope.core.misc.serialization.POJOHelper;
++import org.apache.syncope.core.persistence.api.entity.policy.SyncPolicy;
++
++@Entity
++@Table(name = JPASyncPolicy.TABLE)
++public class JPASyncPolicy extends AbstractPolicy implements SyncPolicy {
++
++ private static final long serialVersionUID = -6090413855809521279L;
++
++ public static final String TABLE = "SyncPolicy";
++
++ @Lob
++ private String specification;
++
++ public JPASyncPolicy() {
++ super();
++ this.type = PolicyType.SYNC;
++ }
++
++ @Override
++ public SyncPolicySpec getSpecification() {
++ return POJOHelper.deserialize(specification, SyncPolicySpec.class);
++ }
++
++ @Override
++ public void setSpecification(final SyncPolicySpec policy) {
++ this.specification = POJOHelper.serialize(policy);
++ }
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java
index 0000000,0000000..36c52a3
new file mode 100644
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/AbstractTask.java
@@@ -1,0 -1,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.core.persistence.jpa.entity.task;
++
++import java.util.ArrayList;
++import java.util.List;
++
++import javax.persistence.CascadeType;
++import javax.persistence.DiscriminatorColumn;
++import javax.persistence.Entity;
++import javax.persistence.EnumType;
++import javax.persistence.Enumerated;
++import javax.persistence.Id;
++import javax.persistence.Inheritance;
++import javax.persistence.InheritanceType;
++import javax.persistence.OneToMany;
++import javax.persistence.Table;
++import javax.validation.constraints.NotNull;
++import org.apache.syncope.common.lib.types.TaskType;
++import org.apache.syncope.core.persistence.api.entity.task.Task;
++import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
++import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
++
++@Entity
++@Table(name = AbstractTask.TABLE)
++@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
++@DiscriminatorColumn(name = "DTYPE")
++public abstract class AbstractTask extends AbstractEntity<Long> implements Task {
++
++ private static final long serialVersionUID = 5837401178128177511L;
++
++ public static final String TABLE = "Task";
++
++ /**
++ * Id.
++ */
++ @Id
++ private Long id;
++
++ @NotNull
++ @Enumerated(EnumType.STRING)
++ protected TaskType type;
++
++ @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "task")
++ private List<JPATaskExec> executions;
++
++ public AbstractTask() {
++ super();
++
++ executions = new ArrayList<>();
++ }
++
++ @Override
++ public Long getKey() {
++ return id;
++ }
++
++ @Override
++ public TaskType getType() {
++ return type;
++ }
++
++ @Override
++ public boolean addExec(final TaskExec exec) {
++ checkType(exec, JPATaskExec.class);
++ return exec != null && !executions.contains((JPATaskExec) exec) && executions.add((JPATaskExec) exec);
++ }
++
++ @Override
++ public boolean removeExec(final TaskExec exec) {
++ checkType(exec, JPATaskExec.class);
++ return exec != null && executions.remove((JPATaskExec) exec);
++ }
++
++ @Override
++ public List<? extends TaskExec> getExecs() {
++ return executions;
++ }
++
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java
----------------------------------------------------------------------
diff --cc fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java
index 0000000,0000000..2b67f37
new file mode 100644
--- /dev/null
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRule.java
@@@ -1,0 -1,0 +1,48 @@@
++/*
++ * 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.fit.core.reference;
++
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++import org.apache.syncope.core.misc.policy.AccountPolicyException;
++import org.apache.syncope.core.persistence.api.dao.AccountRule;
++import org.apache.syncope.core.persistence.api.dao.AccountRuleConfClass;
++import org.apache.syncope.core.persistence.api.entity.user.User;
++import org.springframework.transaction.annotation.Transactional;
++
++@AccountRuleConfClass(TestAccountRuleConf.class)
++public class TestAccountRule implements AccountRule {
++
++ private TestAccountRuleConf conf;
++
++ @Transactional(readOnly = true)
++ @Override
++ public void enforce(final AccountRuleConf conf, final User user) {
++ if (conf instanceof TestAccountRuleConf) {
++ this.conf = TestAccountRuleConf.class.cast(conf);
++ } else {
++ throw new IllegalArgumentException(
++ AccountRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
++ }
++
++ if (!user.getUsername().contains(this.conf.getMustContainSubstring())) {
++ throw new AccountPolicyException("Username not containing " + this.conf.getMustContainSubstring());
++ }
++ }
++
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java
----------------------------------------------------------------------
diff --cc fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java
index 0000000,0000000..8903058
new file mode 100644
--- /dev/null
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestAccountRuleConf.java
@@@ -1,0 -1,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.fit.core.reference;
++
++import org.apache.syncope.common.lib.AbstractBaseBean;
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++
++public class TestAccountRuleConf extends AbstractBaseBean implements AccountRuleConf {
++
++ private static final long serialVersionUID = -1803947511928491978L;
++
++ @Override
++ public String getName() {
++ return getClass().getName();
++ }
++
++ public String getMustContainSubstring() {
++ return "YYY";
++ }
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
----------------------------------------------------------------------
diff --cc fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
index 0000000,0000000..2b67f37
new file mode 100644
--- /dev/null
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRule.java
@@@ -1,0 -1,0 +1,48 @@@
++/*
++ * 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.fit.core.reference;
++
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++import org.apache.syncope.core.misc.policy.AccountPolicyException;
++import org.apache.syncope.core.persistence.api.dao.AccountRule;
++import org.apache.syncope.core.persistence.api.dao.AccountRuleConfClass;
++import org.apache.syncope.core.persistence.api.entity.user.User;
++import org.springframework.transaction.annotation.Transactional;
++
++@AccountRuleConfClass(TestAccountRuleConf.class)
++public class TestAccountRule implements AccountRule {
++
++ private TestAccountRuleConf conf;
++
++ @Transactional(readOnly = true)
++ @Override
++ public void enforce(final AccountRuleConf conf, final User user) {
++ if (conf instanceof TestAccountRuleConf) {
++ this.conf = TestAccountRuleConf.class.cast(conf);
++ } else {
++ throw new IllegalArgumentException(
++ AccountRuleConf.class.getName() + " expected, got " + conf.getClass().getName());
++ }
++
++ if (!user.getUsername().contains(this.conf.getMustContainSubstring())) {
++ throw new AccountPolicyException("Username not containing " + this.conf.getMustContainSubstring());
++ }
++ }
++
++}
http://git-wip-us.apache.org/repos/asf/syncope/blob/77f697b2/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java
----------------------------------------------------------------------
diff --cc fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java
index 0000000,0000000..8903058
new file mode 100644
--- /dev/null
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/TestPasswordRuleConf.java
@@@ -1,0 -1,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.fit.core.reference;
++
++import org.apache.syncope.common.lib.AbstractBaseBean;
++import org.apache.syncope.common.lib.policy.AccountRuleConf;
++
++public class TestAccountRuleConf extends AbstractBaseBean implements AccountRuleConf {
++
++ private static final long serialVersionUID = -1803947511928491978L;
++
++ @Override
++ public String getName() {
++ return getClass().getName();
++ }
++
++ public String getMustContainSubstring() {
++ return "YYY";
++ }
++}