This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 4_1_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/4_1_X by this push:
     new 343714fe7e Upgrading Passay
343714fe7e is described below

commit 343714fe7ed5dcc1d8303efa3733c9c09aae9d1a
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Tue Apr 7 09:49:05 2026 +0200

    Upgrading Passay
---
 .../core/spring/policy/DefaultPasswordRule.java    | 204 +++++++--------------
 .../spring/security/DefaultPasswordGenerator.java  |  16 +-
 .../core/spring/security/PasswordGenerator.java    |  78 ++++++++
 .../core/spring/security/SecureRandomUtils.java    |  10 +-
 .../spring/security/PasswordGeneratorTest.java     |  40 ++++
 .../apache/syncope/fit/core/PullTaskITCase.java    |   2 +-
 pom.xml                                            |   2 +-
 7 files changed, 201 insertions(+), 151 deletions(-)

diff --git 
a/core/spring/src/main/java/org/apache/syncope/core/spring/policy/DefaultPasswordRule.java
 
b/core/spring/src/main/java/org/apache/syncope/core/spring/policy/DefaultPasswordRule.java
index ad1b81b051..e39b6abafc 100644
--- 
a/core/spring/src/main/java/org/apache/syncope/core/spring/policy/DefaultPasswordRule.java
+++ 
b/core/spring/src/main/java/org/apache/syncope/core/spring/policy/DefaultPasswordRule.java
@@ -19,16 +19,12 @@
 package org.apache.syncope.core.spring.policy;
 
 import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.Comparator;
 import java.util.List;
-import java.util.Objects;
 import java.util.Properties;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.Strings;
 import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
 import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.core.persistence.api.EncryptorManager;
@@ -37,18 +33,16 @@ import 
org.apache.syncope.core.persistence.api.entity.user.LinkedAccount;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.rules.PasswordRule;
 import org.apache.syncope.core.provisioning.api.rules.PasswordRuleConfClass;
-import org.passay.CharacterData;
-import org.passay.CharacterRule;
-import org.passay.EnglishCharacterData;
-import org.passay.IllegalCharacterRule;
-import org.passay.LengthRule;
+import org.apache.syncope.core.spring.security.PasswordGenerator;
+import org.passay.DefaultPasswordValidator;
 import org.passay.PasswordData;
 import org.passay.PasswordValidator;
-import org.passay.PropertiesMessageResolver;
-import org.passay.RepeatCharactersRule;
-import org.passay.Rule;
-import org.passay.RuleResult;
-import org.passay.UsernameRule;
+import org.passay.ValidationResult;
+import org.passay.dictionary.ArrayWordList;
+import org.passay.dictionary.WordListDictionary;
+import org.passay.resolver.PropertiesMessageResolver;
+import org.passay.rule.DictionaryRule;
+import org.passay.rule.Rule;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -60,71 +54,22 @@ public class DefaultPasswordRule implements PasswordRule {
 
     protected static final Logger LOG = 
LoggerFactory.getLogger(DefaultPasswordRule.class);
 
-    public static List<Rule> conf2Rules(final DefaultPasswordRuleConf conf) {
-        List<Rule> rules = new ArrayList<>();
-
-        LengthRule lengthRule = new LengthRule();
-        if (conf.getMinLength() > 0) {
-            lengthRule.setMinimumLength(conf.getMinLength());
-        }
-        if (conf.getMaxLength() > 0) {
-            lengthRule.setMaximumLength(conf.getMaxLength());
-        }
-        rules.add(lengthRule);
-
-        if (conf.getAlphabetical() > 0) {
-            rules.add(new CharacterRule(EnglishCharacterData.Alphabetical, 
conf.getAlphabetical()));
-        }
-
-        if (conf.getUppercase() > 0) {
-            rules.add(new CharacterRule(EnglishCharacterData.UpperCase, 
conf.getUppercase()));
-        }
-
-        if (conf.getLowercase() > 0) {
-            rules.add(new CharacterRule(EnglishCharacterData.LowerCase, 
conf.getLowercase()));
-        }
-
-        if (conf.getDigit() > 0) {
-            rules.add(new CharacterRule(EnglishCharacterData.Digit, 
conf.getDigit()));
-        }
-
-        if (conf.getSpecial() > 0) {
-            rules.add(new CharacterRule(new CharacterData() {
-
-                @Override
-                public String getErrorCode() {
-                    return "INSUFFICIENT_SPECIAL";
-                }
-
-                @Override
-                public String getCharacters() {
-                    return new 
String(ArrayUtils.toPrimitive(conf.getSpecialChars().toArray(Character[]::new)));
-                }
-            }, conf.getSpecial()));
-        }
-
-        if (!conf.getIllegalChars().isEmpty()) {
-            rules.add(new IllegalCharacterRule(
-                    
ArrayUtils.toPrimitive(conf.getIllegalChars().toArray(Character[]::new))));
-        }
-
-        if (conf.getRepeatSame() > 0) {
-            rules.add(new RepeatCharactersRule(conf.getRepeatSame()));
-        }
-
-        if (!conf.isUsernameAllowed()) {
-            rules.add(new UsernameRule(true, true));
-        }
-
-        return rules;
-    }
+    protected final PropertiesMessageResolver messageResolver;
 
     @Autowired
     protected EncryptorManager encryptorManager;
 
     protected DefaultPasswordRuleConf conf;
 
-    protected PasswordValidator passwordValidator;
+    public DefaultPasswordRule() {
+        Properties passay = new Properties();
+        try (InputStream in = 
getClass().getResourceAsStream("/passay.properties")) {
+            passay.load(in);
+            messageResolver = new PropertiesMessageResolver(passay);
+        } catch (Exception e) {
+            throw new IllegalStateException("Could not initialize Passay", e);
+        }
+    }
 
     @Override
     public PasswordRuleConf getConf() {
@@ -135,96 +80,77 @@ public class DefaultPasswordRule implements PasswordRule {
     public void setConf(final PasswordRuleConf conf) {
         if (conf instanceof DefaultPasswordRuleConf defaultPasswordRuleConf) {
             this.conf = defaultPasswordRuleConf;
-
-            Properties passay = new Properties();
-            try (InputStream in = 
getClass().getResourceAsStream("/passay.properties")) {
-                passay.load(in);
-                passwordValidator = new PasswordValidator(new 
PropertiesMessageResolver(passay), conf2Rules(this.conf));
-            } catch (Exception e) {
-                throw new IllegalStateException("Could not initialize Passay", 
e);
-            }
         } else {
             throw new IllegalArgumentException(
                     DefaultPasswordRuleConf.class.getName() + " expected, got 
" + conf.getClass().getName());
         }
     }
 
-    protected void enforce(final String clear, final String username, final 
Set<String> wordsNotPermitted) {
-        RuleResult result = passwordValidator.validate(
-                username == null ? new PasswordData(clear) : new 
PasswordData(username, clear));
-        if (!result.isValid()) {
-            throw new PasswordPolicyException(String.join(",", 
passwordValidator.getMessages(result)));
+    protected void enforce(final String username, final String clearPassword, 
final Collection<String> notPermitted) {
+        List<Rule> rules = PasswordGenerator.conf2Rules(conf);
+        if (!notPermitted.isEmpty()) {
+            rules.add(new DictionaryRule(new WordListDictionary(new 
ArrayWordList(
+                    
notPermitted.stream().distinct().sorted(Comparator.naturalOrder()).toArray(String[]::new),
 true)),
+                    true));
         }
 
-        // check words not permitted
-        wordsNotPermitted.stream().
-                filter(word -> Strings.CI.contains(clear, word)).findFirst().
-                ifPresent(word -> {
-                    throw new PasswordPolicyException("Used word(s) not 
permitted");
-                });
+        PasswordValidator passwordValidator = new 
DefaultPasswordValidator(messageResolver, rules);
+        ValidationResult result = passwordValidator.validate(
+                username == null ? new PasswordData(clearPassword) : new 
PasswordData(username, clearPassword));
+        if (!result.isValid()) {
+            throw new 
PasswordPolicyException(result.getMessages().stream().collect(Collectors.joining(",")));
+        }
     }
 
     @Override
     public void enforce(final String username, final String clearPassword) {
-        if (clearPassword != null) {
-            Set<String> wordsNotPermitted = new 
HashSet<>(conf.getWordsNotPermitted());
-            enforce(clearPassword, username, wordsNotPermitted);
+        if (clearPassword == null) {
+            return;
         }
+
+        enforce(username, clearPassword, Set.of());
     }
 
     @Transactional(readOnly = true)
     @Override
     public void enforce(final User user, final String clearPassword) {
-        if (clearPassword != null) {
-            Set<String> wordsNotPermitted = new 
HashSet<>(conf.getWordsNotPermitted());
-            wordsNotPermitted.addAll(
-                    conf.getSchemasNotPermitted().stream().
-                            map(schema -> user.getPlainAttr(schema).
-                            map(PlainAttr::getValuesAsStrings).orElse(null)).
-                            filter(Objects::nonNull).
-                            filter(values -> !CollectionUtils.isEmpty(values)).
-                            flatMap(Collection::stream).
-                            collect(Collectors.toSet()));
-
-            enforce(clearPassword, user.getUsername(), wordsNotPermitted);
+        if (clearPassword == null) {
+            return;
         }
+
+        List<String> notPermitted = conf.getSchemasNotPermitted().stream().
+                map(schema -> user.getPlainAttr(schema).
+                map(PlainAttr::getValuesAsStrings).orElse(null)).
+                filter(values -> !CollectionUtils.isEmpty(values)).
+                flatMap(Collection::stream).
+                toList();
+
+        enforce(user.getUsername(), clearPassword, notPermitted);
     }
 
     @Transactional(readOnly = true)
     @Override
     public void enforce(final LinkedAccount account) {
-        conf.getWordsNotPermitted().addAll(
-                conf.getSchemasNotPermitted().stream().
-                        map(schema -> account.getPlainAttr(schema).
-                        map(PlainAttr::getValuesAsStrings).orElse(null)).
-                        filter(Objects::nonNull).
-                        filter(values -> !CollectionUtils.isEmpty(values)).
-                        flatMap(Collection::stream).
-                        toList());
-
-        if (account.getPassword() != null) {
-            String clear = null;
-            if (account.canDecodeSecrets()) {
-                try {
-                    clear = 
encryptorManager.getInstance().decode(account.getPassword(), 
account.getCipherAlgorithm());
-                } catch (Exception e) {
-                    LOG.error("Could not decode password for {}", account, e);
-                }
-            }
-
-            if (clear != null) {
-                Set<String> wordsNotPermitted = new 
HashSet<>(conf.getWordsNotPermitted());
-                wordsNotPermitted.addAll(
-                        conf.getSchemasNotPermitted().stream().
-                                map(schema -> account.getPlainAttr(schema).
-                                
map(PlainAttr::getValuesAsStrings).orElse(null)).
-                                filter(Objects::nonNull).
-                                filter(values -> 
!CollectionUtils.isEmpty(values)).
-                                flatMap(Collection::stream).
-                                collect(Collectors.toSet()));
-
-                enforce(clear, account.getUsername(), wordsNotPermitted);
+        String clearPassword = null;
+        if (account.getPassword() != null && account.canDecodeSecrets()) {
+            try {
+                clearPassword = encryptorManager.getInstance().decode(
+                        account.getPassword(), account.getCipherAlgorithm());
+            } catch (Exception e) {
+                LOG.error("Could not decode password for {}", account, e);
             }
         }
+        if (clearPassword == null) {
+            return;
+        }
+
+        List<String> notPermitted = conf.getSchemasNotPermitted().stream().
+                map(schema -> account.getPlainAttr(schema).
+                map(PlainAttr::getValuesAsStrings).orElse(null)).
+                filter(values -> !CollectionUtils.isEmpty(values)).
+                flatMap(Collection::stream).
+                toList();
+
+        enforce(account.getUsername(), clearPassword, notPermitted);
     }
 }
diff --git 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultPasswordGenerator.java
 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultPasswordGenerator.java
index 73a03d93d7..8ee5ad2f38 100644
--- 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultPasswordGenerator.java
+++ 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/DefaultPasswordGenerator.java
@@ -30,9 +30,9 @@ import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.provisioning.api.rules.PasswordRule;
 import org.apache.syncope.core.spring.implementation.ImplementationManager;
-import org.apache.syncope.core.spring.policy.DefaultPasswordRule;
-import org.passay.CharacterRule;
-import org.passay.EnglishCharacterData;
+import org.passay.data.EnglishCharacterData;
+import org.passay.rule.CharacterRule;
+import org.passay.rule.Rule;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.transaction.annotation.Transactional;
@@ -104,6 +104,7 @@ public class DefaultPasswordGenerator implements 
PasswordGenerator {
         DefaultPasswordRuleConf result = new DefaultPasswordRuleConf();
         result.setMinLength(VERY_MIN_LENGTH);
         result.setMaxLength(VERY_MAX_LENGTH);
+        result.setUsernameAllowed(true);
 
         defaultRuleConfs.forEach(ruleConf -> {
             if (ruleConf.getMinLength() > result.getMinLength()) {
@@ -170,7 +171,9 @@ public class DefaultPasswordGenerator implements 
PasswordGenerator {
     }
 
     protected String generate(final DefaultPasswordRuleConf ruleConf) {
-        List<CharacterRule> characterRules = 
DefaultPasswordRule.conf2Rules(ruleConf).stream().
+        List<Rule> rules = PasswordGenerator.conf2Rules(ruleConf);
+
+        List<CharacterRule> characterRules = rules.stream().
                 
filter(CharacterRule.class::isInstance).map(CharacterRule.class::cast).
                 toList();
         if (characterRules.isEmpty()) {
@@ -178,9 +181,12 @@ public class DefaultPasswordGenerator implements 
PasswordGenerator {
             characterRules = List.of(
                     new CharacterRule(EnglishCharacterData.Alphabetical, 
halfMinLength),
                     new CharacterRule(EnglishCharacterData.Digit, 
halfMinLength));
+
+            rules.addAll(characterRules);
         }
         int min = Math.max(ruleConf.getMinLength(),
                 
characterRules.stream().mapToInt(CharacterRule::getNumberOfCharacters).sum());
-        return SecureRandomUtils.passwordGenerator().generatePassword(min, 
characterRules);
+
+        return SecureRandomUtils.passwordGenerator(min, 
rules).generate().toString();
     }
 }
diff --git 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/PasswordGenerator.java
 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/PasswordGenerator.java
index 758ea159f4..c57515b1a5 100644
--- 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/PasswordGenerator.java
+++ 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/PasswordGenerator.java
@@ -18,13 +18,91 @@
  */
 package org.apache.syncope.core.spring.security;
 
+import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.List;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
 import org.apache.syncope.core.persistence.api.entity.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
+import org.passay.UnicodeString;
+import org.passay.data.CharacterData;
+import org.passay.data.EnglishCharacterData;
+import org.passay.dictionary.ArrayWordList;
+import org.passay.dictionary.WordListDictionary;
+import org.passay.rule.CharacterRule;
+import org.passay.rule.DictionaryRule;
+import org.passay.rule.IllegalCharacterRule;
+import org.passay.rule.LengthRule;
+import org.passay.rule.RepeatCharactersRule;
+import org.passay.rule.Rule;
+import org.passay.rule.UsernameRule;
 
 public interface PasswordGenerator {
 
+    static List<Rule> conf2Rules(final DefaultPasswordRuleConf conf) {
+        List<Rule> rules = new ArrayList<>();
+
+        if (conf.getMinLength() > 0 || conf.getMaxLength() > 0) {
+            rules.add(new LengthRule(
+                    conf.getMinLength() > 0 ? conf.getMinLength() : 0,
+                    conf.getMaxLength() > 0 ? conf.getMaxLength() : 
Integer.MAX_VALUE));
+        }
+
+        if (conf.getAlphabetical() > 0) {
+            rules.add(new CharacterRule(EnglishCharacterData.Alphabetical, 
conf.getAlphabetical()));
+        }
+
+        if (conf.getUppercase() > 0) {
+            rules.add(new CharacterRule(EnglishCharacterData.UpperCase, 
conf.getUppercase()));
+        }
+
+        if (conf.getLowercase() > 0) {
+            rules.add(new CharacterRule(EnglishCharacterData.LowerCase, 
conf.getLowercase()));
+        }
+
+        if (conf.getDigit() > 0) {
+            rules.add(new CharacterRule(EnglishCharacterData.Digit, 
conf.getDigit()));
+        }
+
+        if (conf.getSpecial() > 0) {
+            rules.add(new CharacterRule(new CharacterData() {
+
+                @Override
+                public String getErrorCode() {
+                    return "INSUFFICIENT_SPECIAL";
+                }
+
+                @Override
+                public String getCharacters() {
+                    return new 
String(ArrayUtils.toPrimitive(conf.getSpecialChars().toArray(Character[]::new)));
+                }
+            }, conf.getSpecial()));
+        }
+
+        if (!conf.getIllegalChars().isEmpty()) {
+            rules.add(new IllegalCharacterRule(
+                    new 
UnicodeString(ArrayUtils.toPrimitive(conf.getIllegalChars().toArray(Character[]::new)))));
+        }
+
+        if (conf.getRepeatSame() > 0) {
+            rules.add(new RepeatCharactersRule(conf.getRepeatSame()));
+        }
+
+        if (!conf.isUsernameAllowed()) {
+            rules.add(new UsernameRule(true, true));
+        }
+
+        if (!conf.getWordsNotPermitted().isEmpty()) {
+            conf.getWordsNotPermitted().sort(Comparator.naturalOrder());
+            rules.add(new DictionaryRule(new WordListDictionary(
+                    new 
ArrayWordList(conf.getWordsNotPermitted().toArray(String[]::new), true)), 
true));
+        }
+
+        return rules;
+    }
+
     String generate(ExternalResource resource, List<Realm> realms);
 
     String generate(List<PasswordPolicy> policies);
diff --git 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecureRandomUtils.java
 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecureRandomUtils.java
index 0b38f5c832..016f6798d5 100644
--- 
a/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecureRandomUtils.java
+++ 
b/core/spring/src/main/java/org/apache/syncope/core/spring/security/SecureRandomUtils.java
@@ -21,16 +21,16 @@ package org.apache.syncope.core.spring.security;
 import com.fasterxml.uuid.Generators;
 import com.fasterxml.uuid.NoArgGenerator;
 import java.security.SecureRandom;
+import java.util.List;
 import java.util.UUID;
 import org.apache.commons.text.RandomStringGenerator;
-import org.passay.PasswordGenerator;
+import org.passay.generate.PasswordGenerator;
+import org.passay.rule.Rule;
 
 public final class SecureRandomUtils {
 
     private static final SecureRandom RANDOM = new SecureRandom();
 
-    private static final PasswordGenerator PASSWORD_GENERATOR = new 
PasswordGenerator(RANDOM);
-
     private static final RandomStringGenerator FOR_PASSWORD = new 
RandomStringGenerator.Builder().
             usingRandom(RANDOM::nextInt).
             withinRange('0', 'z').
@@ -86,8 +86,8 @@ public final class SecureRandomUtils {
         return UUID_GENERATOR.generate();
     }
 
-    public static PasswordGenerator passwordGenerator() {
-        return PASSWORD_GENERATOR;
+    public static PasswordGenerator passwordGenerator(final int length, final 
List<? extends Rule> rules) {
+        return new PasswordGenerator(RANDOM, length, 2, rules);
     }
 
     private SecureRandomUtils() {
diff --git 
a/core/spring/src/test/java/org/apache/syncope/core/spring/security/PasswordGeneratorTest.java
 
b/core/spring/src/test/java/org/apache/syncope/core/spring/security/PasswordGeneratorTest.java
index 50ea8be828..4e830342ca 100644
--- 
a/core/spring/src/test/java/org/apache/syncope/core/spring/security/PasswordGeneratorTest.java
+++ 
b/core/spring/src/test/java/org/apache/syncope/core/spring/security/PasswordGeneratorTest.java
@@ -18,14 +18,18 @@
  */
 package org.apache.syncope.core.spring.security;
 
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import java.util.List;
 import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.core.spring.SpringTestConfiguration;
 import org.apache.syncope.core.spring.implementation.PasswordRuleTest;
+import org.apache.syncope.core.spring.policy.DefaultPasswordRule;
 import org.junit.jupiter.api.Test;
 import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
 
@@ -97,6 +101,42 @@ public class PasswordGeneratorTest {
         assertTrue(generatedPassword.chars().anyMatch(c -> '@' == c || '!' == 
c || '%' == c));
     }
 
+    @Test
+    public void validateGenerated() throws JsonProcessingException {
+        String input =
+                """
+{
+  "_class": "org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf",
+  "alphabetical": 0,
+  "digit": 1,
+  "illegalChars": [],
+  "lowercase": 0,
+  "maxLength": 64,
+  "minLength": 10,
+  "name": "org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf",
+  "repeatSame": 0,
+  "schemasNotPermitted": [],
+  "special": 0,
+  "specialChars": [],
+  "uppercase": 0,
+  "usernameAllowed": false,
+  "wordsNotPermitted": [
+    "notpermitted1",
+    "notpermitted2"
+  ]
+}
+""";
+        DefaultPasswordRuleConf ruleConf = 
JsonMapper.builder().build().readValue(input, DefaultPasswordRuleConf.class);
+        TestImplementation passwordRule = new TestImplementation();
+        passwordRule.setBody(POJOHelper.serialize(ruleConf));
+
+        String password = passwordGenerator.generate(List.of(new 
TestPasswordPolicy(passwordRule)));
+
+        DefaultPasswordRule rule = new DefaultPasswordRule();
+        rule.setConf(ruleConf);
+        assertDoesNotThrow(() -> rule.enforce((String) null, password));
+    }
+
     @Test
     public void issueSYNCOPE678() {
         String password = passwordGenerator.generate(List.of());
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
index f620bb3800..a7d4cdbd14 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
@@ -865,7 +865,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
             userCR.getResources().clear();
 
             String email = 
userCR.getPlainAttr("email").orElseThrow().getValues().getFirst();
-            userCR.getPlainAttrs().add(new 
Attr.Builder("userId").value(email).build());
+            userCR.getPlainAttrs().add(attr("userId", email));
 
             REMEDIATION_SERVICE.remedy(remediation.getKey(), userCR);
 
diff --git a/pom.xml b/pom.xml
index 6cc4dfe173..65c9aeea05 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1327,7 +1327,7 @@ under the License.
       <dependency>
         <groupId>org.passay</groupId>
         <artifactId>passay</artifactId>
-        <version>1.6.6</version>
+        <version>2.0.0</version>
       </dependency>
 
       <dependency>

Reply via email to