protected Pair enforcePolicies()

in core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java [106:226]


    protected Pair<Boolean, Boolean> enforcePolicies(
            final User user,
            final boolean disablePwdPolicyCheck,
            final String clearPassword) {

        if (!disablePwdPolicyCheck) {
            // ------------------------------
            // Verify password policies
            // ------------------------------
            LOG.debug("Password Policy enforcement");

            try {
                int maxPPSpecHistory = 0;
                for (PasswordPolicy policy : ruleProvider.getPasswordPolicies(
                        user.getRealm(), userDAO.findAllResources(user))) {

                    if (clearPassword == null && !policy.isAllowNullPassword()) {
                        throw new PasswordPolicyException("Password mandatory");
                    }

                    ruleProvider.getPasswordRules(policy).forEach(rule -> {
                        rule.enforce(user, clearPassword);

                        user.getLinkedAccounts().stream().
                                filter(account -> account.getPassword() != null).
                                forEach(rule::enforce);
                    });

                    boolean matching = false;
                    if (policy.getHistoryLength() > 0) {
                        List<String> pwdHistory = user.getPasswordHistory();
                        matching = pwdHistory.subList(policy.getHistoryLength() >= pwdHistory.size()
                                ? 0
                                : pwdHistory.size() - policy.getHistoryLength(), pwdHistory.size()).stream().
                                map(old -> encryptorManager.getInstance().verify(
                                clearPassword, user.getCipherAlgorithm(), old)).
                                reduce(matching, (accumulator, item) -> accumulator | item);
                    }
                    if (matching) {
                        throw new PasswordPolicyException("Password value was used in the past: not allowed");
                    }

                    if (policy.getHistoryLength() > maxPPSpecHistory) {
                        maxPPSpecHistory = policy.getHistoryLength();
                    }
                }

                // update user's password history with encrypted password
                if (maxPPSpecHistory > 0
                        && user.getPassword() != null
                        && !user.getPasswordHistory().contains(user.getPassword())) {

                    user.addToPasswordHistory(user.getPassword());
                }
                // keep only the last maxPPSpecHistory items in user's password history
                if (maxPPSpecHistory < user.getPasswordHistory().size()) {
                    user.removeOldestEntriesFromPasswordHistory(user.getPasswordHistory().size() - maxPPSpecHistory);
                }
            } catch (InvalidEntityException e) {
                throw e;
            } catch (Exception e) {
                LOG.error("Invalid password for {}", user, e);
                throw new InvalidEntityException(User.class, EntityViolationType.InvalidPassword, e.getMessage());
            }
        }

        // ------------------------------
        // Verify account policies
        // ------------------------------
        LOG.debug("Account Policy enforcement");

        boolean suspend = false;
        boolean propagateSuspension = false;
        try {
            if (user.getUsername() == null) {
                throw new AccountPolicyException("Null username");
            }

            if (securityProperties.getAdminUser().equals(user.getUsername())
                    || securityProperties.getAnonymousUser().equals(user.getUsername())) {

                throw new AccountPolicyException("Not allowed: " + user.getUsername());
            }

            List<AccountPolicy> accountPolicies =
                    ruleProvider.getAccountPolicies(user.getRealm(), userDAO.findAllResources(user));
            if (accountPolicies.isEmpty()) {
                if (!Entity.ID_PATTERN.matcher(user.getUsername()).matches()) {
                    throw new AccountPolicyException("Character(s) not allowed: " + user.getUsername());
                }
                user.getLinkedAccounts().stream().
                        filter(account -> account.getUsername() != null).
                        forEach(account -> {
                            if (!Entity.ID_PATTERN.matcher(account.getUsername()).matches()) {
                                throw new AccountPolicyException("Character(s) not allowed: " + account.getUsername());
                            }
                        });
            } else {
                for (AccountPolicy policy : accountPolicies) {
                    ruleProvider.getAccountRules(policy).forEach(rule -> {
                        rule.enforce(user);

                        user.getLinkedAccounts().stream().
                                filter(account -> account.getUsername() != null).
                                forEach(rule::enforce);
                    });

                    suspend |= user.getFailedLogins() != null && policy.getMaxAuthenticationAttempts() > 0
                            && user.getFailedLogins() > policy.getMaxAuthenticationAttempts() && !user.isSuspended();
                    propagateSuspension |= policy.isPropagateSuspension();
                }
            }
        } catch (InvalidEntityException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("Invalid username for {}", user, e);
            throw new InvalidEntityException(User.class, EntityViolationType.InvalidUsername, e.getMessage());
        }

        return Pair.of(suspend, propagateSuspension);
    }