You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by ma...@apache.org on 2012/10/23 10:51:36 UTC
svn commit: r1401200 - in /incubator/syncope/trunk/core/src:
main/java/org/apache/syncope/core/persistence/validation/entity/
main/java/org/apache/syncope/core/policy/
main/java/org/apache/syncope/core/util/
test/java/org/apache/syncope/core/persistenc...
Author: massi
Date: Tue Oct 23 08:51:35 2012
New Revision: 1401200
URL: http://svn.apache.org/viewvc?rev=1401200&view=rev
Log:
Issue 121 closed
Added:
incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PolicyPattern.java (with props)
incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/IncompatiblePolicyException.java (with props)
incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/PasswordGenerator.java (with props)
incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/util/
incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/util/PasswordGeneratorTest.java (with props)
Modified:
incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/SyncopeUserValidator.java
incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PasswordPolicyEnforcer.java
incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/UserTest.java
incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java
incubator/syncope/trunk/core/src/test/resources/content.xml
Modified: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/SyncopeUserValidator.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/SyncopeUserValidator.java?rev=1401200&r1=1401199&r2=1401200&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/SyncopeUserValidator.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/persistence/validation/entity/SyncopeUserValidator.java Tue Oct 23 08:51:35 2012
@@ -22,11 +22,10 @@ import java.util.ArrayList;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
-import org.springframework.beans.factory.annotation.Autowired;
import org.apache.syncope.core.persistence.beans.AccountPolicy;
-import org.apache.syncope.core.persistence.beans.Policy;
import org.apache.syncope.core.persistence.beans.ExternalResource;
import org.apache.syncope.core.persistence.beans.PasswordPolicy;
+import org.apache.syncope.core.persistence.beans.Policy;
import org.apache.syncope.core.persistence.beans.role.SyncopeRole;
import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
import org.apache.syncope.core.persistence.dao.PolicyDAO;
@@ -36,6 +35,7 @@ import org.apache.syncope.core.policy.Po
import org.apache.syncope.types.AccountPolicySpec;
import org.apache.syncope.types.EntityViolationType;
import org.apache.syncope.types.PasswordPolicySpec;
+import org.springframework.beans.factory.annotation.Autowired;
public class SyncopeUserValidator extends AbstractValidator implements
ConstraintValidator<SyncopeUserCheck, SyncopeUser> {
Modified: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PasswordPolicyEnforcer.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PasswordPolicyEnforcer.java?rev=1401200&r1=1401199&r2=1401200&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PasswordPolicyEnforcer.java (original)
+++ incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PasswordPolicyEnforcer.java Tue Oct 23 08:51:35 2012
@@ -18,36 +18,13 @@
*/
package org.apache.syncope.core.policy;
-import java.util.regex.Pattern;
-import org.springframework.stereotype.Component;
import org.apache.syncope.types.PasswordPolicySpec;
import org.apache.syncope.types.PolicyType;
+import org.springframework.stereotype.Component;
@Component
public class PasswordPolicyEnforcer extends PolicyEnforcer<PasswordPolicySpec, String> {
- private static final Pattern DIGIT = Pattern.compile(".*\\d+.*");
-
- private static final Pattern ALPHA_LOWERCASE = Pattern.compile(".*[a-z]+.*");
-
- private static final Pattern ALPHA_UPPERCASE = Pattern.compile(".*[A-Z]+.*");
-
- private static final Pattern FIRSTDIGIT = Pattern.compile("\\d.*");
-
- private static final Pattern LASTDIGIT = Pattern.compile(".*\\d");
-
- private static final Pattern ALPHANUMERIC = Pattern.compile(".*\\w.*");
-
- private static final Pattern FIRSTALPHANUMERIC = Pattern.compile("\\w.*");
-
- private static final Pattern LASTALPHANUMERIC = Pattern.compile(".*\\w");
-
- private static final Pattern NONALPHANUMERIC = Pattern.compile(".*\\W.*");
-
- private static final Pattern FIRSTNONALPHANUMERIC = Pattern.compile("\\W.*");
-
- private static final Pattern LASTNONALPHANUMERIC = Pattern.compile(".*\\W");
-
@Override
public void enforce(final PasswordPolicySpec policy, final PolicyType type, final String password)
throws PasswordPolicyException, PolicyEnforceException {
@@ -171,46 +148,46 @@ public class PasswordPolicyEnforcer exte
}
private boolean checkForDigit(String str) {
- return DIGIT.matcher((CharSequence) str).matches();
+ return PolicyPattern.DIGIT.matcher((CharSequence) str).matches();
}
private boolean checkForLowercase(String str) {
- return ALPHA_LOWERCASE.matcher((CharSequence) str).matches();
+ return PolicyPattern.ALPHA_LOWERCASE.matcher((CharSequence) str).matches();
}
private boolean checkForUppercase(String str) {
- return ALPHA_UPPERCASE.matcher((CharSequence) str).matches();
+ return PolicyPattern.ALPHA_UPPERCASE.matcher((CharSequence) str).matches();
}
private boolean checkForFirstDigit(String str) {
- return FIRSTDIGIT.matcher((CharSequence) str).matches();
+ return PolicyPattern.FIRST_DIGIT.matcher((CharSequence) str).matches();
}
private boolean checkForLastDigit(String str) {
- return LASTDIGIT.matcher((CharSequence) str).matches();
+ return PolicyPattern.LAST_DIGIT.matcher((CharSequence) str).matches();
}
private boolean checkForAlphanumeric(String str) {
- return ALPHANUMERIC.matcher(str).matches();
+ return PolicyPattern.ALPHANUMERIC.matcher(str).matches();
}
private boolean checkForFirstAlphanumeric(String str) {
- return FIRSTALPHANUMERIC.matcher(str).matches();
+ return PolicyPattern.FIRST_ALPHANUMERIC.matcher(str).matches();
}
private boolean checkForLastAlphanumeric(String str) {
- return LASTALPHANUMERIC.matcher(str).matches();
+ return PolicyPattern.LAST_ALPHANUMERIC.matcher(str).matches();
}
private boolean checkForNonAlphanumeric(String str) {
- return NONALPHANUMERIC.matcher(str).matches();
+ return PolicyPattern.NON_ALPHANUMERIC.matcher(str).matches();
}
private boolean checkForFirstNonAlphanumeric(String str) {
- return FIRSTNONALPHANUMERIC.matcher(str).matches();
+ return PolicyPattern.FIRST_NON_ALPHANUMERIC.matcher(str).matches();
}
private boolean checkForLastNonAlphanumeric(String str) {
- return LASTNONALPHANUMERIC.matcher(str).matches();
+ return PolicyPattern.LAST_NON_ALPHANUMERIC.matcher(str).matches();
}
}
Added: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PolicyPattern.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PolicyPattern.java?rev=1401200&view=auto
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PolicyPattern.java (added)
+++ incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PolicyPattern.java Tue Oct 23 08:51:35 2012
@@ -0,0 +1,46 @@
+/*
+ * 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.policy;
+
+import java.util.regex.Pattern;
+
+public class PolicyPattern {
+
+ public static final Pattern DIGIT = Pattern.compile(".*\\d+.*");
+
+ public static final Pattern ALPHA_LOWERCASE = Pattern.compile(".*[a-z]+.*");
+
+ public static final Pattern ALPHA_UPPERCASE = Pattern.compile(".*[A-Z]+.*");
+
+ public static final Pattern FIRST_DIGIT = Pattern.compile("\\d.*");
+
+ public static final Pattern LAST_DIGIT = Pattern.compile(".*\\d");
+
+ public static final Pattern ALPHANUMERIC = Pattern.compile(".*\\w.*");
+
+ public static final Pattern FIRST_ALPHANUMERIC = Pattern.compile("\\w.*");
+
+ public static final Pattern LAST_ALPHANUMERIC = Pattern.compile(".*\\w");
+
+ public static final Pattern NON_ALPHANUMERIC = Pattern.compile(".*\\W.*");
+
+ public static final Pattern FIRST_NON_ALPHANUMERIC = Pattern.compile("\\W.*");
+
+ public static final Pattern LAST_NON_ALPHANUMERIC = Pattern.compile(".*\\W");
+}
Propchange: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PolicyPattern.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PolicyPattern.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/PolicyPattern.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/IncompatiblePolicyException.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/IncompatiblePolicyException.java?rev=1401200&view=auto
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/IncompatiblePolicyException.java (added)
+++ incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/IncompatiblePolicyException.java Tue Oct 23 08:51:35 2012
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.util;
+
+public class IncompatiblePolicyException extends Exception {
+
+ private static final long serialVersionUID = 4810651743226663580L;
+
+ public IncompatiblePolicyException(String msg) {
+ super(msg);
+ }
+
+ public IncompatiblePolicyException(String msg, Exception e) {
+ super(msg, e);
+ }
+}
Propchange: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/IncompatiblePolicyException.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/IncompatiblePolicyException.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/IncompatiblePolicyException.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/PasswordGenerator.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/PasswordGenerator.java?rev=1401200&view=auto
==============================================================================
--- incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/PasswordGenerator.java (added)
+++ incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/PasswordGenerator.java Tue Oct 23 08:51:35 2012
@@ -0,0 +1,334 @@
+/*
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.syncope.core.persistence.beans.ExternalResource;
+import org.apache.syncope.core.persistence.beans.role.SyncopeRole;
+import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
+import org.apache.syncope.core.persistence.dao.PolicyDAO;
+import org.apache.syncope.core.policy.PolicyPattern;
+import org.apache.syncope.types.PasswordPolicySpec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PasswordGenerator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PasswordGenerator.class);
+
+ private static final String[] SPECIAL_CHAR = {"!", "£", "%", "&", "(", ")", "?", "#", "_", "$"};
+
+ @Autowired
+ private PolicyDAO policyDAO;
+
+ public String generatePasswordFromPwdSpec(final List<PasswordPolicySpec> passwordPolicySpecs)
+ throws IncompatiblePolicyException {
+ PasswordPolicySpec policySpec = mergePolicySpecs(passwordPolicySpecs);
+
+ evaluateFinalPolicySpec(policySpec);
+ return generatePassword(policySpec);
+ }
+
+ public String generateUserPassword(final SyncopeUser user)
+ throws IncompatiblePolicyException {
+ List<PasswordPolicySpec> userPasswordPolicies = new ArrayList<PasswordPolicySpec>();
+ PasswordPolicySpec passwordPolicySpec = policyDAO.getGlobalPasswordPolicy().getSpecification();
+
+ userPasswordPolicies.add(passwordPolicySpec);
+
+ PasswordPolicySpec rolePasswordPolicySpec;
+ if ((user.getRoles() != null) || (!user.getRoles().isEmpty())) {
+ for (Iterator<SyncopeRole> rolesIterator = user.getRoles().iterator(); rolesIterator.hasNext();) {
+ SyncopeRole syncopeRole = rolesIterator.next();
+ rolePasswordPolicySpec = syncopeRole.getPasswordPolicy().getSpecification();
+ userPasswordPolicies.add(rolePasswordPolicySpec);
+ }
+ }
+
+ PasswordPolicySpec resourcePasswordPolicySpec;
+
+ if ((user.getResources() != null) || (!user.getResources().isEmpty())) {
+ for (Iterator<ExternalResource> resourcesIterator = user.getResources().iterator();
+ resourcesIterator.hasNext();) {
+ ExternalResource externalResource = resourcesIterator.next();
+ if (externalResource.getPasswordPolicy() != null) {
+ resourcePasswordPolicySpec = externalResource.getPasswordPolicy().getSpecification();
+ userPasswordPolicies.add(resourcePasswordPolicySpec);
+ }
+ }
+ }
+
+ PasswordPolicySpec policySpec = mergePolicySpecs(userPasswordPolicies);
+
+ evaluateFinalPolicySpec(policySpec);
+ return generatePassword(policySpec);
+ }
+
+ private PasswordPolicySpec mergePolicySpecs(List<PasswordPolicySpec> userPasswordPolicies) {
+
+ PasswordPolicySpec fpps = new PasswordPolicySpec();
+ fpps.setMinLength(0);
+ fpps.setMaxLength(1000);
+
+ for (Iterator<PasswordPolicySpec> it = userPasswordPolicies.iterator(); it.hasNext();) {
+ PasswordPolicySpec policySpec = it.next();
+ if (policySpec.getMinLength() > fpps.getMinLength()) {
+ fpps.setMinLength(policySpec.getMinLength());
+ }
+
+ if ((policySpec.getMaxLength() != 0) && ((policySpec.getMaxLength() < fpps.getMaxLength()))) {
+ fpps.setMaxLength(policySpec.getMaxLength());
+ }
+ fpps.setPrefixesNotPermitted(policySpec.getPrefixesNotPermitted());
+ fpps.setSuffixesNotPermitted(policySpec.getSuffixesNotPermitted());
+
+ if (!fpps.isNonAlphanumericRequired()) {
+ fpps.setNonAlphanumericRequired(policySpec.isNonAlphanumericRequired());
+ }
+
+ if (!fpps.isAlphanumericRequired()) {
+ fpps.setAlphanumericRequired(policySpec.isAlphanumericRequired());
+ }
+ if (!fpps.isDigitRequired()) {
+ fpps.setDigitRequired(policySpec.isDigitRequired());
+ }
+
+ if (!fpps.isLowercaseRequired()) {
+ fpps.setLowercaseRequired(policySpec.isLowercaseRequired());
+ }
+ if (!fpps.isUppercaseRequired()) {
+ fpps.setUppercaseRequired(policySpec.isUppercaseRequired());
+ }
+ if (!fpps.isMustStartWithDigit()) {
+ fpps.setMustStartWithDigit(policySpec.isMustStartWithDigit());
+ }
+ if (!fpps.isMustntStartWithDigit()) {
+ fpps.setMustntStartWithDigit(policySpec.isMustntStartWithDigit());
+ }
+ if (!fpps.isMustEndWithDigit()) {
+ fpps.setMustEndWithDigit(policySpec.isMustEndWithDigit());
+ }
+ if (fpps.isMustntEndWithDigit()) {
+ fpps.setMustntEndWithDigit(policySpec.isMustntEndWithDigit());
+ }
+ if (!fpps.isMustStartWithAlpha()) {
+ fpps.setMustStartWithAlpha(policySpec.isMustStartWithAlpha());
+ }
+ if (!fpps.isMustntStartWithAlpha()) {
+ fpps.setMustntStartWithAlpha(policySpec.isMustntStartWithAlpha());
+ }
+ if (!fpps.isMustStartWithNonAlpha()) {
+ fpps.setMustStartWithNonAlpha(policySpec.isMustStartWithNonAlpha());
+ }
+ if (!fpps.isMustntStartWithNonAlpha()) {
+ fpps.setMustntStartWithNonAlpha(policySpec.isMustntStartWithNonAlpha());
+ }
+ if (!fpps.isMustEndWithNonAlpha()) {
+ fpps.setMustEndWithNonAlpha(policySpec.isMustEndWithNonAlpha());
+ }
+ if (!fpps.isMustntEndWithNonAlpha()) {
+ fpps.setMustntEndWithNonAlpha(policySpec.isMustntEndWithNonAlpha());
+ }
+ if (!fpps.isMustEndWithAlpha()) {
+ fpps.setMustEndWithAlpha(policySpec.isMustEndWithAlpha());
+ }
+ if (!fpps.isMustntEndWithAlpha()) {
+ fpps.setMustntEndWithAlpha(policySpec.isMustntEndWithAlpha());
+ }
+ }
+ return fpps;
+ }
+
+ private void evaluateFinalPolicySpec(final PasswordPolicySpec policySpec)
+ throws IncompatiblePolicyException {
+ if (policySpec.getMinLength() == 0) {
+ LOG.error("Minimum lenght given is zero");
+ throw new IncompatiblePolicyException("Minimum lenght given is zero");
+ }
+ if (policySpec.isMustEndWithAlpha() && policySpec.isMustntEndWithAlpha()) {
+ LOG.error("Incompatible password policy specification: mustEndWithAlpha and"
+ + "mustntEndWithAlpha are true");
+ throw new IncompatiblePolicyException("Incompatible password policy specification: mustEndWithAlpha and"
+ + "mustntEndWithAlpha are true");
+ }
+ if (policySpec.isMustEndWithAlpha() && policySpec.isMustEndWithDigit()) {
+ LOG.error("Incompatible password policy specification: mustEndWithAlpha and"
+ + "mustEndWithDigit are true");
+ throw new IncompatiblePolicyException("Incompatible password policy specification: mustEndWithAlpha and"
+ + "mustEndWithDigit are true");
+ }
+ if (policySpec.isMustEndWithDigit() && policySpec.isMustntEndWithDigit()) {
+ LOG.error("Incompatible password policy specification: mustEndWithDigit and"
+ + "mustntEndWithDigit are true");
+ throw new IncompatiblePolicyException("Incompatible password policy specification: mustEndWithDigit and"
+ + "mustntEndWithDigit are true");
+ }
+ if (policySpec.isMustEndWithNonAlpha() && policySpec.isMustntEndWithNonAlpha()) {
+ LOG.error("Incompatible password policy specification: mustEndWithNonAlpha and"
+ + "mustntEndWithNonAlpha are true");
+ throw new IncompatiblePolicyException("Incompatible password policy specification: mustEndWithNonAlpha and"
+ + "mustntEndWithNonAlpha are true");
+ }
+ if (policySpec.isMustStartWithAlpha() && policySpec.isMustntStartWithAlpha()) {
+ LOG.error("Incompatible password policy specification: mustStartWithAlpha and"
+ + "mustntStartWithAlpha are true");
+ throw new IncompatiblePolicyException("Incompatible password policy specification: mustStartWithAlpha and"
+ + "mustntStartWithAlpha are true");
+ }
+ if (policySpec.isMustStartWithAlpha() && policySpec.isMustStartWithDigit()) {
+ LOG.error("Incompatible password policy specification: mustStartWithAlpha and"
+ + "mustStartWithDigit are true");
+ throw new IncompatiblePolicyException("Incompatible password policy specification: mustStartWithAlpha and"
+ + "mustStartWithDigit are true");
+ }
+ if (policySpec.isMustStartWithDigit() && policySpec.isMustntStartWithDigit()) {
+ LOG.error("Incompatible password policy specification: mustStartWithDigit and"
+ + "mustntStartWithDigit are true");
+ throw new IncompatiblePolicyException("Incompatible password policy specification: mustStartWithDigit and"
+ + " mustntStartWithDigit are true");
+ }
+ if (policySpec.isMustStartWithNonAlpha() && policySpec.isMustntStartWithNonAlpha()) {
+ LOG.error("Incompatible password policy specification: mustStartWithNonAlpha"
+ + "and mustntStartWithNonAlpha are true");
+ throw new IncompatiblePolicyException("Incompatible password policy specification: mustStartWithNonAlpha"
+ + "and mustntStartWithNonAlpha are true");
+ }
+ if (policySpec.getMinLength() > policySpec.getMaxLength()) {
+ LOG.error("Minimun length given (" + policySpec.getMinLength() + ") is higher than"
+ + "maximum allowed (" + policySpec.getMaxLength() + ")");
+ throw new IncompatiblePolicyException("Minimun length given (" + policySpec.getMinLength() + ")"
+ + "is higher than maximum allowed (" + policySpec.getMaxLength() + ")");
+ }
+ }
+
+ private String generatePassword(final PasswordPolicySpec policySpec) {
+ StringBuilder generatedPassword = new StringBuilder(policySpec.getMinLength());
+
+ if (policySpec.isDigitRequired() || policySpec.isAlphanumericRequired()) {
+ generatedPassword.append(RandomStringUtils.randomAlphanumeric(policySpec.getMinLength()));
+ }
+
+ if (policySpec.isDigitRequired() && !PolicyPattern.DIGIT.matcher(generatedPassword.toString()).matches()) {
+ int where = randomNumber(policySpec.getMinLength());
+ generatedPassword.deleteCharAt(where);
+ generatedPassword.insert(where, RandomStringUtils.randomNumeric(1));
+ }
+
+ if (!policySpec.isAlphanumericRequired() && !policySpec.isDigitRequired()) {
+ generatedPassword.append(RandomStringUtils.randomAlphabetic(policySpec.getMinLength()));
+ }
+
+ if (policySpec.isUppercaseRequired() && !PolicyPattern.ALPHA_UPPERCASE
+ .matcher(generatedPassword.toString()).matches()) {
+ int where = randomNumber(policySpec.getMinLength());
+ generatedPassword.deleteCharAt(where);
+ generatedPassword.insert(where, RandomStringUtils.randomAlphabetic(1));
+ }
+
+ if (policySpec.isLowercaseRequired() && !PolicyPattern.ALPHA_LOWERCASE.
+ matcher(generatedPassword.toString()).matches()) {
+ int where = randomNumber(policySpec.getMinLength());
+ generatedPassword.deleteCharAt(where);
+ generatedPassword.insert(where, RandomStringUtils.randomAlphabetic(1).toLowerCase());
+ }
+
+ if (policySpec.isNonAlphanumericRequired()) {
+ int where = randomNumber(policySpec.getMinLength());
+ generatedPassword.deleteCharAt(where);
+ generatedPassword.insert(where, SPECIAL_CHAR[randomNumber(SPECIAL_CHAR.length - 1)]);
+ }
+
+ checkEndChar(generatedPassword, policySpec);
+
+ checkstartChar(generatedPassword, policySpec);
+
+ for (Iterator<String> it = policySpec.getPrefixesNotPermitted().iterator(); it.hasNext();) {
+ String prefix = it.next();
+ if (generatedPassword.toString().startsWith(prefix)) {
+ checkstartChar(generatedPassword, policySpec);
+ }
+ }
+
+ for (Iterator<String> it = policySpec.getSuffixesNotPermitted().iterator(); it.hasNext();) {
+ String suffix = it.next();
+ if (generatedPassword.toString().endsWith(suffix)) {
+ checkEndChar(generatedPassword, policySpec);
+ }
+ }
+ return generatedPassword.toString();
+ }
+
+ private int randomNumber(int range) {
+ int randomNumber = (int) (Math.random() * (range - 1));
+ return randomNumber == 0 ? 1 : randomNumber;
+ }
+
+ private void checkstartChar(final StringBuilder generatedPassword, final PasswordPolicySpec policySpec) {
+ if (policySpec.isMustStartWithAlpha()) {
+ generatedPassword.deleteCharAt(0);
+ generatedPassword.insert(0, RandomStringUtils.randomAlphabetic(1));
+ }
+ if (policySpec.isMustStartWithNonAlpha() || policySpec.isMustStartWithDigit()) {
+ generatedPassword.deleteCharAt(0);
+ generatedPassword.insert(0, RandomStringUtils.randomNumeric(1));
+ }
+ if (policySpec.isMustntStartWithAlpha()) {
+ generatedPassword.deleteCharAt(0);
+ generatedPassword.insert(0, RandomStringUtils.randomNumeric(1));
+ }
+ if (policySpec.isMustntStartWithDigit()) {
+ generatedPassword.deleteCharAt(0);
+ generatedPassword.insert(0, RandomStringUtils.randomAlphabetic(1));
+ }
+ if (policySpec.isMustntStartWithNonAlpha()) {
+ generatedPassword.deleteCharAt(0);
+ generatedPassword.insert(0, RandomStringUtils.randomAlphanumeric(1));
+ }
+ }
+
+ private void checkEndChar(final StringBuilder generatedPassword, final PasswordPolicySpec policySpec) {
+ if (policySpec.isMustEndWithAlpha()) {
+ generatedPassword.deleteCharAt(policySpec.getMinLength() - 1);
+ generatedPassword.insert(policySpec.getMinLength() - 1, RandomStringUtils.randomAlphabetic(1));
+ }
+ if (policySpec.isMustEndWithNonAlpha() || policySpec.isMustEndWithDigit()) {
+ generatedPassword.deleteCharAt(policySpec.getMinLength() - 1);
+ generatedPassword.insert(policySpec.getMinLength() - 1, RandomStringUtils.randomNumeric(1));
+ }
+
+ if (policySpec.isMustntEndWithAlpha()) {
+ generatedPassword.deleteCharAt(policySpec.getMinLength() - 1);
+ generatedPassword.insert(policySpec.getMinLength() - 1, RandomStringUtils.randomNumeric(1));
+ }
+ if (policySpec.isMustntEndWithDigit()) {
+ generatedPassword.deleteCharAt(policySpec.getMinLength() - 1);
+ generatedPassword.insert(policySpec.getMinLength() - 1, RandomStringUtils.randomAlphabetic(1));
+ }
+ if (policySpec.isMustntEndWithNonAlpha()) {
+ generatedPassword.deleteCharAt(policySpec.getMinLength() - 1);
+ generatedPassword.insert(policySpec.getMinLength() - 1, RandomStringUtils.randomAlphabetic(1));
+ }
+ }
+}
Propchange: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/PasswordGenerator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/PasswordGenerator.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: incubator/syncope/trunk/core/src/main/java/org/apache/syncope/core/util/PasswordGenerator.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/UserTest.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/UserTest.java?rev=1401200&r1=1401199&r2=1401200&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/UserTest.java (original)
+++ incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/persistence/dao/UserTest.java Tue Oct 23 08:51:35 2012
@@ -18,26 +18,30 @@
*/
package org.apache.syncope.core.persistence.dao;
-import static org.junit.Assert.*;
-
import java.util.Date;
import java.util.List;
import java.util.Set;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
import org.apache.syncope.core.AbstractTest;
+import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
import org.apache.syncope.core.persistence.beans.user.UAttrValue;
import org.apache.syncope.core.persistence.validation.entity.InvalidEntityException;
import org.apache.syncope.core.rest.controller.InvalidSearchConditionException;
import org.apache.syncope.core.util.EntitlementUtil;
+import org.apache.syncope.core.util.IncompatiblePolicyException;
+import org.apache.syncope.core.util.PasswordGenerator;
import org.apache.syncope.types.CipherAlgorithm;
+import static org.junit.Assert.*;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
@Transactional
public class UserTest extends AbstractTest {
@Autowired
+ private PasswordGenerator passwordGenerator;
+
+ @Autowired
private UserDAO userDAO;
@Autowired
@@ -78,18 +82,21 @@ public class UserTest extends AbstractTe
}
@Test
- public void findByDerAttributeValue() throws InvalidSearchConditionException {
+ public void findByDerAttributeValue()
+ throws InvalidSearchConditionException {
final List<SyncopeUser> list = userDAO.findByDerAttrValue("cn", "Doe, John");
assertEquals("did not get expected number of users ", 1, list.size());
}
@Test(expected = InvalidSearchConditionException.class)
- public void findByInvalidDerAttrValue() throws InvalidSearchConditionException {
+ public void findByInvalidDerAttrValue()
+ throws InvalidSearchConditionException {
userDAO.findByDerAttrValue("cn", "Antonio, Maria, Rossi");
}
@Test(expected = InvalidSearchConditionException.class)
- public void findByInvalidDerAttrExpression() throws InvalidSearchConditionException {
+ public void findByInvalidDerAttrExpression()
+ throws InvalidSearchConditionException {
userDAO.findByDerAttrValue("noschema", "Antonio, Maria");
}
@@ -191,8 +198,16 @@ public class UserTest extends AbstractTe
@Test
public void issueSYNCOPE226() {
SyncopeUser user = userDAO.find(5L);
+ String password = "";
+ try {
+ password = passwordGenerator.generateUserPassword(user);
+ System.out.println("PASSWORD GENERATA: " + password);
+ } catch (IncompatiblePolicyException ex) {
+ fail(ex.getMessage());
+ }
+ assertNotNull(password);
- user.setPassword("123password", CipherAlgorithm.AES, 0);
+ user.setPassword(password, CipherAlgorithm.AES, 0);
SyncopeUser actual = userDAO.save(user);
assertNotNull(actual);
Modified: incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java?rev=1401200&r1=1401199&r2=1401200&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java (original)
+++ incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java Tue Oct 23 08:51:35 2012
@@ -1138,7 +1138,7 @@ public class UserTestITCase extends Abst
UserMod userMod = new UserMod();
userMod.setId(userTO.getId());
- userMod.setPassword("newPassword");
+ userMod.setPassword("new2Password");
userMod.addAttributeToBeRemoved("userId");
attributeMod = new AttributeMod();
@@ -1160,7 +1160,7 @@ public class UserTestITCase extends Abst
assertNotNull(userTO);
SyncopeUser passwordTestUser = new SyncopeUser();
- passwordTestUser.setPassword("newPassword", CipherAlgorithm.SHA1, 0);
+ passwordTestUser.setPassword("new2Password", CipherAlgorithm.SHA1, 0);
assertEquals(passwordTestUser.getPassword(), userTO.getPassword());
assertEquals(1, userTO.getMemberships().size());
@@ -1204,7 +1204,7 @@ public class UserTestITCase extends Abst
UserMod userMod = new UserMod();
userMod.setId(userTO.getId());
- userMod.setPassword("newPassword");
+ userMod.setPassword("newPassword123");
userTO = restTemplate.postForObject(BASE_URL + "user/update", userMod, UserTO.class);
@@ -1212,7 +1212,7 @@ public class UserTestITCase extends Abst
assertNotNull(userTO.getChangePwdDate());
SyncopeUser passwordTestUser = new SyncopeUser();
- passwordTestUser.setPassword("newPassword", CipherAlgorithm.SHA1, 0);
+ passwordTestUser.setPassword("newPassword123", CipherAlgorithm.SHA1, 0);
assertEquals(passwordTestUser.getPassword(), userTO.getPassword());
List<PropagationTaskTO> afterTasks = Arrays.asList(restTemplate.getForObject(
Added: incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/util/PasswordGeneratorTest.java
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/util/PasswordGeneratorTest.java?rev=1401200&view=auto
==============================================================================
--- incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/util/PasswordGeneratorTest.java (added)
+++ incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/util/PasswordGeneratorTest.java Tue Oct 23 08:51:35 2012
@@ -0,0 +1,145 @@
+/*
+ * 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.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.core.AbstractTest;
+import org.apache.syncope.core.persistence.beans.user.SyncopeUser;
+import org.apache.syncope.core.persistence.dao.UserDAO;
+import org.apache.syncope.core.policy.PolicyPattern;
+import org.apache.syncope.types.CipherAlgorithm;
+import org.apache.syncope.types.PasswordPolicySpec;
+import static org.junit.Assert.*;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class PasswordGeneratorTest extends AbstractTest {
+
+ @Autowired
+ private PasswordGenerator passwordGenerator;
+
+ @Autowired
+ private UserDAO userDAO;
+
+ @Test
+ public void testPasswordGenerator() {
+ SyncopeUser user = userDAO.find(5L);
+
+ String password = "";
+ try {
+ password = passwordGenerator.generateUserPassword(user);
+
+ } catch (IncompatiblePolicyException ex) {
+ fail(ex.getMessage());
+ }
+ assertNotNull(password);
+ user.setPassword(password, CipherAlgorithm.SHA1, 0);
+ userDAO.save(user);
+ }
+
+ @Test
+ public void startEndWithDigit()
+ throws IncompatiblePolicyException {
+ PasswordPolicySpec passwordPolicySpec = createBasePasswordPolicySpec();
+ passwordPolicySpec.setMustStartWithDigit(true);
+
+ PasswordPolicySpec passwordPolicySpec2 = createBasePasswordPolicySpec();
+ passwordPolicySpec.setMustEndWithDigit(true);
+ List<PasswordPolicySpec> passwordPolicySpecs = new ArrayList<PasswordPolicySpec>();
+ passwordPolicySpecs.add(passwordPolicySpec);
+ passwordPolicySpecs.add(passwordPolicySpec2);
+ String generatedPassword = passwordGenerator.generatePasswordFromPwdSpec(passwordPolicySpecs);
+ assertTrue(Character.isDigit(generatedPassword.charAt(0)));
+ assertTrue(Character.isDigit(generatedPassword.charAt(generatedPassword.length() - 1)));
+ }
+
+ @Test
+ public void startWithDigitAndWithAlpha()
+ throws IncompatiblePolicyException {
+ PasswordPolicySpec passwordPolicySpec = createBasePasswordPolicySpec();
+ passwordPolicySpec.setMustStartWithDigit(true);
+
+ PasswordPolicySpec passwordPolicySpec2 = createBasePasswordPolicySpec();
+ passwordPolicySpec.setMustEndWithAlpha(true);
+ List<PasswordPolicySpec> passwordPolicySpecs = new ArrayList<PasswordPolicySpec>();
+ passwordPolicySpecs.add(passwordPolicySpec);
+ passwordPolicySpecs.add(passwordPolicySpec2);
+ String generatedPassword = passwordGenerator.generatePasswordFromPwdSpec(passwordPolicySpecs);
+ assertTrue(Character.isDigit(generatedPassword.charAt(0)));
+ assertTrue(Character.isLetter(generatedPassword.charAt(generatedPassword.length() - 1)));
+ }
+
+ @Test
+ public void passwordWithNonAlpha()
+ throws IncompatiblePolicyException {
+ PasswordPolicySpec passwordPolicySpec = createBasePasswordPolicySpec();
+ passwordPolicySpec.setNonAlphanumericRequired(true);
+
+ PasswordPolicySpec passwordPolicySpec2 = createBasePasswordPolicySpec();
+ passwordPolicySpec.setMustEndWithAlpha(true);
+ List<PasswordPolicySpec> passwordPolicySpecs = new ArrayList<PasswordPolicySpec>();
+ passwordPolicySpecs.add(passwordPolicySpec);
+ passwordPolicySpecs.add(passwordPolicySpec2);
+ String generatedPassword = passwordGenerator.generatePasswordFromPwdSpec(passwordPolicySpecs);
+ assertTrue(PolicyPattern.NON_ALPHANUMERIC.matcher(generatedPassword.toString()).matches());
+ assertTrue(Character.isLetter(generatedPassword.charAt(generatedPassword.length() - 1)));
+ }
+
+ @Test(expected = IncompatiblePolicyException.class)
+ public void incopatiblePolicies()
+ throws IncompatiblePolicyException {
+ PasswordPolicySpec passwordPolicySpec = createBasePasswordPolicySpec();
+ passwordPolicySpec.setMinLength(12);
+
+ PasswordPolicySpec passwordPolicySpec2 = createBasePasswordPolicySpec();
+ passwordPolicySpec.setMaxLength(10);
+
+ List<PasswordPolicySpec> passwordPolicySpecs = new ArrayList<PasswordPolicySpec>();
+ passwordPolicySpecs.add(passwordPolicySpec);
+ passwordPolicySpecs.add(passwordPolicySpec2);
+ passwordGenerator.generatePasswordFromPwdSpec(passwordPolicySpecs);
+ }
+
+ private PasswordPolicySpec createBasePasswordPolicySpec() {
+ PasswordPolicySpec basePasswordPolicySpec = new PasswordPolicySpec();
+ basePasswordPolicySpec.setAlphanumericRequired(false);
+ basePasswordPolicySpec.setDigitRequired(false);
+ basePasswordPolicySpec.setLowercaseRequired(false);
+ basePasswordPolicySpec.setMaxLength(1000);
+ basePasswordPolicySpec.setMinLength(8);
+ basePasswordPolicySpec.setMustEndWithAlpha(false);
+ basePasswordPolicySpec.setMustEndWithDigit(false);
+ basePasswordPolicySpec.setMustEndWithNonAlpha(false);
+ basePasswordPolicySpec.setMustStartWithAlpha(false);
+ basePasswordPolicySpec.setMustStartWithDigit(false);
+ basePasswordPolicySpec.setMustStartWithNonAlpha(false);
+ basePasswordPolicySpec.setMustntEndWithAlpha(false);
+ basePasswordPolicySpec.setMustntEndWithDigit(false);
+ basePasswordPolicySpec.setMustntEndWithNonAlpha(false);
+ basePasswordPolicySpec.setMustntStartWithAlpha(false);
+ basePasswordPolicySpec.setMustntStartWithDigit(false);
+ basePasswordPolicySpec.setMustntStartWithNonAlpha(false);
+ basePasswordPolicySpec.setNonAlphanumericRequired(false);
+ basePasswordPolicySpec.setUppercaseRequired(false);
+ return basePasswordPolicySpec;
+ }
+}
Propchange: incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/util/PasswordGeneratorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/util/PasswordGeneratorTest.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: incubator/syncope/trunk/core/src/test/java/org/apache/syncope/core/util/PasswordGeneratorTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: incubator/syncope/trunk/core/src/test/resources/content.xml
URL: http://svn.apache.org/viewvc/incubator/syncope/trunk/core/src/test/resources/content.xml?rev=1401200&r1=1401199&r2=1401200&view=diff
==============================================================================
--- incubator/syncope/trunk/core/src/test/resources/content.xml (original)
+++ incubator/syncope/trunk/core/src/test/resources/content.xml Tue Oct 23 08:51:35 2012
@@ -36,11 +36,11 @@ under the License.
<Policy DTYPE="SyncPolicy" id="1" description="sync policy 1" type="GLOBAL_SYNC" specification="%3Corg.apache.syncope.types.SyncPolicySpec%2F%3E"/>
<Policy DTYPE="PasswordPolicy" id="2" description="global password policy" type="GLOBAL_PASSWORD" specification="%3Corg.apache.syncope.types.PasswordPolicySpec%3E%0A++%3ChistoryLength%3E1%3C%2FhistoryLength%3E%0A++%3CmaxLength%3E0%3C%2FmaxLength%3E%0A++%3CminLength%3E8%3C%2FminLength%3E%0A++%3CnonAlphanumericRequired%3Efalse%3C%2FnonAlphanumericRequired%3E%0A++%3CalphanumericRequired%3Efalse%3C%2FalphanumericRequired%3E%0A++%3CdigitRequired%3Efalse%3C%2FdigitRequired%3E%0A++%3ClowercaseRequired%3Efalse%3C%2FlowercaseRequired%3E%0A++%3CuppercaseRequired%3Efalse%3C%2FuppercaseRequired%3E%0A++%3CmustStartWithDigit%3Efalse%3C%2FmustStartWithDigit%3E%0A++%3CmustntStartWithDigit%3Efalse%3C%2FmustntStartWithDigit%3E%0A++%3CmustEndWithDigit%3Efalse%3C%2FmustEndWithDigit%3E%0A++%3CmustntEndWithDigit%3Efalse%3C%2FmustntEndWithDigit%3E%0A++%3CmustStartWithNonAlpha%3Efalse%3C%2FmustStartWithNonAlpha%3E%0A++%3CmustStartWithAlpha%3Efalse%3C%2FmustStartWithAlpha%3E%0A++%3CmustntStartWith
NonAlpha%3Efalse%3C%2FmustntStartWithNonAlpha%3E%0A++%3CmustntStartWithAlpha%3Efalse%3C%2FmustntStartWithAlpha%3E%0A++%3CmustEndWithNonAlpha%3Efalse%3C%2FmustEndWithNonAlpha%3E%0A++%3CmustEndWithAlpha%3Efalse%3C%2FmustEndWithAlpha%3E%0A++%3CmustntEndWithNonAlpha%3Efalse%3C%2FmustntEndWithNonAlpha%3E%0A++%3CmustntEndWithAlpha%3Efalse%3C%2FmustntEndWithAlpha%3E%0A++%3CprefixesNotPermitted%3E%0A++++%3Cstring%3Enotpermitted1%3C%2Fstring%3E%0A++++%3Cstring%3Enotpermitted2%3C%2Fstring%3E%0A++%3C%2FprefixesNotPermitted%3E%0A%3C%2Forg.apache.syncope.types.PasswordPolicySpec%3E"/>
<Policy DTYPE="SyncPolicy" id="3" description="sync policy 2" type="SYNC" specification="%3Corg.apache.syncope.types.SyncPolicySpec%3E%0A++%3CalternativeSearchAttrs%3E%0A++++%3Cstring%3Eusername%3C%2Fstring%3E%0A++++%3Cstring%3Efirstname%3C%2Fstring%3E%0A++%3C%2FalternativeSearchAttrs%3E%0A++%3CconflictResolutionAction%3EALL%3C%2FconflictResolutionAction%3E%0A%3C%2Forg.apache.syncope.types.SyncPolicySpec%3E"/>
- <Policy DTYPE="PasswordPolicy" id="4" description="sample password policy" type="PASSWORD" specification="%3Corg.apache.syncope.types.PasswordPolicySpec%3E%0A++%3ChistoryLength%3E0%3C%2FhistoryLength%3E%0A++%3CmaxLength%3E0%3C%2FmaxLength%3E%0A++%3CminLength%3E10%3C%2FminLength%3E%0A++%3CnonAlphanumericRequired%3Efalse%3C%2FnonAlphanumericRequired%3E%0A++%3CalphanumericRequired%3Efalse%3C%2FalphanumericRequired%3E%0A++%3CdigitRequired%3Efalse%3C%2FdigitRequired%3E%0A++%3ClowercaseRequired%3Efalse%3C%2FlowercaseRequired%3E%0A++%3CuppercaseRequired%3Efalse%3C%2FuppercaseRequired%3E%0A++%3CmustStartWithDigit%3Efalse%3C%2FmustStartWithDigit%3E%0A++%3CmustntStartWithDigit%3Efalse%3C%2FmustntStartWithDigit%3E%0A++%3CmustEndWithDigit%3Efalse%3C%2FmustEndWithDigit%3E%0A++%3CmustntEndWithDigit%3Efalse%3C%2FmustntEndWithDigit%3E%0A++%3CmustStartWithNonAlpha%3Efalse%3C%2FmustStartWithNonAlpha%3E%0A++%3CmustStartWithAlpha%3Efalse%3C%2FmustStartWithAlpha%3E%0A++%3CmustntStartWithNonAlp
ha%3Efalse%3C%2FmustntStartWithNonAlpha%3E%0A++%3CmustntStartWithAlpha%3Efalse%3C%2FmustntStartWithAlpha%3E%0A++%3CmustEndWithNonAlpha%3Efalse%3C%2FmustEndWithNonAlpha%3E%0A++%3CmustEndWithAlpha%3Efalse%3C%2FmustEndWithAlpha%3E%0A++%3CmustntEndWithNonAlpha%3Efalse%3C%2FmustntEndWithNonAlpha%3E%0A++%3CmustntEndWithAlpha%3Efalse%3C%2FmustntEndWithAlpha%3E%0A++%3CprefixesNotPermitted%3E%0A++++%3Cstring%3Enotpermitted1%3C%2Fstring%3E%0A++++%3Cstring%3Enotpermitted2%3C%2Fstring%3E%0A++%3C%2FprefixesNotPermitted%3E%0A%3C%2Forg.apache.syncope.types.PasswordPolicySpec%3E"/>
+ <Policy DTYPE="PasswordPolicy" id="4" description="sample password policy" type="PASSWORD" specification="%3Corg.apache.syncope.types.PasswordPolicySpec%3E%0A++%3ChistoryLength%3E0%3C%2FhistoryLength%3E%0A++%3CmaxLength%3E0%3C%2FmaxLength%3E%0A++%3CminLength%3E10%3C%2FminLength%3E%0A++%3CnonAlphanumericRequired%3Efalse%3C%2FnonAlphanumericRequired%3E%0A++%3CalphanumericRequired%3Efalse%3C%2FalphanumericRequired%3E%0A++%3CdigitRequired%3Etrue%3C%2FdigitRequired%3E%0A++%3ClowercaseRequired%3Efalse%3C%2FlowercaseRequired%3E%0A++%3CuppercaseRequired%3Efalse%3C%2FuppercaseRequired%3E%0A++%3CmustStartWithDigit%3Efalse%3C%2FmustStartWithDigit%3E%0A++%3CmustntStartWithDigit%3Efalse%3C%2FmustntStartWithDigit%3E%0A++%3CmustEndWithDigit%3Efalse%3C%2FmustEndWithDigit%3E%0A++%3CmustntEndWithDigit%3Efalse%3C%2FmustntEndWithDigit%3E%0A++%3CmustStartWithNonAlpha%3Efalse%3C%2FmustStartWithNonAlpha%3E%0A++%3CmustStartWithAlpha%3Efalse%3C%2FmustStartWithAlpha%3E%0A++%3CmustntStartWithNonAlph
a%3Efalse%3C%2FmustntStartWithNonAlpha%3E%0A++%3CmustntStartWithAlpha%3Efalse%3C%2FmustntStartWithAlpha%3E%0A++%3CmustEndWithNonAlpha%3Efalse%3C%2FmustEndWithNonAlpha%3E%0A++%3CmustEndWithAlpha%3Efalse%3C%2FmustEndWithAlpha%3E%0A++%3CmustntEndWithNonAlpha%3Efalse%3C%2FmustntEndWithNonAlpha%3E%0A++%3CmustntEndWithAlpha%3Efalse%3C%2FmustntEndWithAlpha%3E%0A++%3CprefixesNotPermitted%3E%0A++++%3Cstring%3Enotpermitted1%3C%2Fstring%3E%0A++++%3Cstring%3Enotpermitted2%3C%2Fstring%3E%0A++%3C%2FprefixesNotPermitted%3E%0A%3C%2Forg.apache.syncope.types.PasswordPolicySpec%3E"/>
<Policy DTYPE="AccountPolicy" id="5" description="global account policy" type="GLOBAL_ACCOUNT" specification="%3Corg.apache.syncope.types.AccountPolicySpec%3E%0A++%3CmaxLength%3E0%3C%2FmaxLength%3E%0A++%3CminLength%3E0%3C%2FminLength%3E%0A++%3CallUpperCase%3Efalse%3C%2FallUpperCase%3E%0A++%3CallLowerCase%3Efalse%3C%2FallLowerCase%3E%0A++%3CpropagateSuspension%3Efalse%3C%2FpropagateSuspension%3E%0A++%3CpermittedLoginRetries%3E0%3C%2FpermittedLoginRetries%3E%0A%3C%2Forg.apache.syncope.types.AccountPolicySpec%3E"/>
<Policy DTYPE="AccountPolicy" id="6" description="sample account policy" type="ACCOUNT" specification="%3Corg.apache.syncope.types.AccountPolicySpec%3E%0A++%3CmaxLength%3E0%3C%2FmaxLength%3E%0A++%3CminLength%3E4%3C%2FminLength%3E%0A++%3CprefixesNotPermitted%3E%0A++++%3Cstring%3Enotpermitted1%3C%2Fstring%3E%0A++++%3Cstring%3Enotpermitted2%3C%2Fstring%3E%0A++%3C%2FprefixesNotPermitted%3E%0A++%3CallUpperCase%3Efalse%3C%2FallUpperCase%3E%0A++%3CallLowerCase%3Efalse%3C%2FallLowerCase%3E%0A++%3CpropagateSuspension%3Efalse%3C%2FpropagateSuspension%3E%0A++%3CpermittedLoginRetries%3E3%3C%2FpermittedLoginRetries%3E%0A%3C%2Forg.apache.syncope.types.AccountPolicySpec%3E"/>
<Policy DTYPE="SyncPolicy" id="7" description="sync policy 1" type="SYNC" specification="%3Corg.apache.syncope.types.SyncPolicySpec%2F%3E"/>
- <Policy DTYPE="PasswordPolicy" id="8" description="sample password policy" type="PASSWORD" specification="%3Corg.apache.syncope.types.PasswordPolicySpec%3E%0A++%3ChistoryLength%3E0%3C%2FhistoryLength%3E%0A++%3CmaxLength%3E0%3C%2FmaxLength%3E%0A++%3CminLength%3E10%3C%2FminLength%3E%0A++%3CnonAlphanumericRequired%3Efalse%3C%2FnonAlphanumericRequired%3E%0A++%3CalphanumericRequired%3Efalse%3C%2FalphanumericRequired%3E%0A++%3CdigitRequired%3Etrue%3C%2FdigitRequired%3E%0A++%3ClowercaseRequired%3Efalse%3C%2FlowercaseRequired%3E%0A++%3CuppercaseRequired%3Efalse%3C%2FuppercaseRequired%3E%0A++%3CmustStartWithDigit%3Efalse%3C%2FmustStartWithDigit%3E%0A++%3CmustntStartWithDigit%3Efalse%3C%2FmustntStartWithDigit%3E%0A++%3CmustEndWithDigit%3Efalse%3C%2FmustEndWithDigit%3E%0A++%3CmustntEndWithDigit%3Efalse%3C%2FmustntEndWithDigit%3E%0A++%3CmustStartWithNonAlpha%3Efalse%3C%2FmustStartWithNonAlpha%3E%0A++%3CmustStartWithAlpha%3Efalse%3C%2FmustStartWithAlpha%3E%0A++%3CmustntStartWithNonAlph
a%3Efalse%3C%2FmustntStartWithNonAlpha%3E%0A++%3CmustntStartWithAlpha%3Efalse%3C%2FmustntStartWithAlpha%3E%0A++%3CmustEndWithNonAlpha%3Efalse%3C%2FmustEndWithNonAlpha%3E%0A++%3CmustEndWithAlpha%3Efalse%3C%2FmustEndWithAlpha%3E%0A++%3CmustntEndWithNonAlpha%3Efalse%3C%2FmustntEndWithNonAlpha%3E%0A++%3CmustntEndWithAlpha%3Efalse%3C%2FmustntEndWithAlpha%3E%0A++%3CprefixesNotPermitted%3E%0A++++%3Cstring%3Enotpermitted1%3C%2Fstring%3E%0A++++%3Cstring%3Enotpermitted2%3C%2Fstring%3E%0A++%3C%2FprefixesNotPermitted%3E%0A%3C%2Forg.apache.syncope.types.PasswordPolicySpec%3E"/>
+ <Policy DTYPE="PasswordPolicy" id="8" description="sample password policy" type="PASSWORD" specification="%3Corg.apache.syncope.types.PasswordPolicySpec%3E%0A++%3ChistoryLength%3E0%3C%2FhistoryLength%3E%0A++%3CmaxLength%3E0%3C%2FmaxLength%3E%0A++%3CminLength%3E10%3C%2FminLength%3E%0A++%3CnonAlphanumericRequired%3Etrue%3C%2FnonAlphanumericRequired%3E%0A++%3CalphanumericRequired%3Efalse%3C%2FalphanumericRequired%3E%0A++%3CdigitRequired%3Etrue%3C%2FdigitRequired%3E%0A++%3ClowercaseRequired%3Etrue%3C%2FlowercaseRequired%3E%0A++%3CuppercaseRequired%3Etrue%3C%2FuppercaseRequired%3E%0A++%3CmustStartWithDigit%3Etrue%3C%2FmustStartWithDigit%3E%0A++%3CmustntStartWithDigit%3Efalse%3C%2FmustntStartWithDigit%3E%0A++%3CmustEndWithDigit%3Etrue%3C%2FmustEndWithDigit%3E%0A++%3CmustntEndWithDigit%3Efalse%3C%2FmustntEndWithDigit%3E%0A++%3CmustStartWithNonAlpha%3Efalse%3C%2FmustStartWithNonAlpha%3E%0A++%3CmustStartWithAlpha%3Efalse%3C%2FmustStartWithAlpha%3E%0A++%3CmustntStartWithNonAlpha%3Ef
alse%3C%2FmustntStartWithNonAlpha%3E%0A++%3CmustntStartWithAlpha%3Efalse%3C%2FmustntStartWithAlpha%3E%0A++%3CmustEndWithNonAlpha%3Efalse%3C%2FmustEndWithNonAlpha%3E%0A++%3CmustEndWithAlpha%3Efalse%3C%2FmustEndWithAlpha%3E%0A++%3CmustntEndWithNonAlpha%3Efalse%3C%2FmustntEndWithNonAlpha%3E%0A++%3CmustntEndWithAlpha%3Efalse%3C%2FmustntEndWithAlpha%3E%0A++%3CprefixesNotPermitted%3E%0A++++%3Cstring%3Enotpermitted1%3C%2Fstring%3E%0A++++%3Cstring%3Enotpermitted2%3C%2Fstring%3E%0A++%3C%2FprefixesNotPermitted%3E%0A%3C%2Forg.apache.syncope.types.PasswordPolicySpec%3E"/>
<SyncopeUser id="1" workflowId="0" status="active" password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
username="user1" creationDate="2010-10-20 11:00:00"/>