org.wso2.carbon.identity.mgt.IdentityMgtConfig.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.mgt.IdentityMgtConfig.java

Source

/*
 * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. 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.wso2.carbon.identity.mgt;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.mgt.constants.IdentityMgtConstants;
import org.wso2.carbon.identity.mgt.mail.DefaultEmailSendingModule;
import org.wso2.carbon.identity.mgt.password.DefaultPasswordGenerator;
import org.wso2.carbon.identity.mgt.password.RandomPasswordGenerator;
import org.wso2.carbon.identity.mgt.policy.PolicyEnforcer;
import org.wso2.carbon.identity.mgt.policy.PolicyRegistry;
import org.wso2.carbon.identity.mgt.store.RegistryRecoveryDataStore;
import org.wso2.carbon.identity.mgt.store.UserIdentityDataStore;
import org.wso2.carbon.identity.mgt.store.UserRecoveryDataStore;
import org.wso2.carbon.identity.mgt.store.UserStoreBasedIdentityDataStore;
import org.wso2.carbon.user.api.RealmConfiguration;
import org.wso2.carbon.user.core.jdbc.JDBCRealmConstants;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Enumeration;

/**
 * encapsulates recovery config data
 */
public class IdentityMgtConfig {

    private static final Log log = LogFactory.getLog(IdentityMgtConfig.class);
    private static IdentityMgtConfig identityMgtConfig;
    private boolean saasEnable;
    private boolean listenerEnable;
    private int noOfUserChallenges;
    private boolean notificationInternallyManaged;
    private boolean captchaVerificationInternallyManaged;
    private String challengeQuestionSeparator;
    private int authPolicyMaxLoginAttempts;
    private int temporaryPasswordExpireTime;
    private String temporaryDefaultPassword;
    private boolean enableTemporaryPassword;
    private boolean enableAuthPolicy;
    private boolean authPolicyOneTimePasswordCheck;
    private boolean authPolicyExpirePasswordCheck;
    private int authPolicyLockingTime;
    private int authPolicyPasswordExpireTime;
    private int notificationExpireTime;
    private boolean authPolicyAccountLockCheck;
    private boolean authPolicyAccountExistCheck;
    private boolean authPolicyAccountLockOnFailure;
    private boolean authPolicyAccountLockOnCreation;
    private boolean enableUserAccountVerification;
    private boolean userAccountVerificationByUser;
    private boolean temporaryPasswordOneTime;
    private String userAccountVerificationRole;
    private boolean notificationSending;
    private String digsestFunction;
    private RandomPasswordGenerator passwordGenerator;
    private UserIdentityDataStore identityDataStore;
    private UserRecoveryDataStore recoveryDataStore;
    private List<NotificationSendingModule> sendingModules = new ArrayList<NotificationSendingModule>();
    private List<String> notificationTypes = new ArrayList<String>();
    private String recoveryClaim;
    private PolicyRegistry policyRegistry = new PolicyRegistry();

    protected Properties properties = new Properties();

    private long registryCleanUpPeriod;

    /*
     * Define the pattern of the configuration file. Assume following
     * pattern in config.
     * Eg. Password.policy.extensions.1.min.length=6
     */
    private Pattern propertyPattern = Pattern.compile("(\\.\\d\\.)");

    public IdentityMgtConfig(RealmConfiguration configuration) {

        InputStream inStream = null;

        File pipConfigXml = new File(IdentityUtil.getIdentityConfigDirPath(),
                IdentityMgtConstants.PropertyConfig.CONFIG_FILE_NAME);
        if (pipConfigXml.exists()) {
            try {
                inStream = new FileInputStream(pipConfigXml);
                properties.load(inStream);
            } catch (FileNotFoundException e) {
                log.error("Can not load identity-mgt properties file ", e);
            } catch (IOException e) {
                log.error("Can not load identity-mgt properties file ", e);
            } finally {
                if (inStream != null) {
                    try {
                        inStream.close();
                    } catch (IOException e) {
                        log.error("Error while closing stream ", e);
                    }
                }
            }
        }

        try {
            String notificationInternallyManagedProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.NOTIFICATION_SEND_INTERNALLY);
            if (notificationInternallyManagedProperty != null) {
                this.notificationInternallyManaged = Boolean
                        .parseBoolean(notificationInternallyManagedProperty.trim());
            }

            String saasEnableProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.USER_INFO_RECOVERY_SAA_SENABLE);
            if (saasEnableProperty != null) {
                this.saasEnable = Boolean.parseBoolean(saasEnableProperty.trim());
            }

            String listenerEnableProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.IDENTITY_LISTENER_ENABLE);
            if (listenerEnableProperty != null) {
                this.listenerEnable = Boolean.parseBoolean(listenerEnableProperty.trim());
            }

            String notificationSendingProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.NOTIFICATION_SEND_ENABLE);
            if (notificationSendingProperty != null) {
                this.notificationSending = Boolean.parseBoolean(notificationSendingProperty.trim());
            }

            String recoveryClaimProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.RECOVERY_CLAIM);
            if (recoveryClaimProperty != null) {
                this.recoveryClaim = recoveryClaimProperty.trim();
            }

            String captchaVerificationInternallyManagedProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.CAPTCHA_VERIFICATION_INTERNALLY);
            if (captchaVerificationInternallyManagedProperty != null) {
                this.captchaVerificationInternallyManaged = Boolean
                        .parseBoolean(captchaVerificationInternallyManagedProperty.trim());
            }

            String enableUserAccountVerificationProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.ACCOUNT_VERIFICATION_ENABLE);
            if (enableUserAccountVerificationProperty != null) {
                this.enableUserAccountVerification = Boolean
                        .parseBoolean(enableUserAccountVerificationProperty.trim());
            }

            String userAccountVerificationRoleProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.ACCOUNT_VERIFICATION_ROLE);
            if (userAccountVerificationRoleProperty != null
                    && userAccountVerificationRoleProperty.trim().length() > 0) {
                this.userAccountVerificationRole = userAccountVerificationRoleProperty;
            } else {
                this.userAccountVerificationByUser = true;
            }

            String allowTemporaryPasswordProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.TEMPORARY_PASSWORD_ENABLE);
            if (allowTemporaryPasswordProperty != null) {
                this.enableTemporaryPassword = Boolean.parseBoolean(allowTemporaryPasswordProperty.trim());
            }

            String temporaryPasswordExpireTimeProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.TEMPORARY_PASSWORD_EXPIRE_TIME);
            if (temporaryPasswordExpireTimeProperty != null) {
                this.temporaryPasswordExpireTime = Integer.parseInt(temporaryPasswordExpireTimeProperty.trim());
            }

            String defaultPasswordProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.TEMPORARY_PASSWORD_DEFAULT);
            if (defaultPasswordProperty != null) {
                this.temporaryDefaultPassword = defaultPasswordProperty.trim();
            }

            String temporaryPasswordOneTimeProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.TEMPORARY_PASSWORD_ONETIME);
            if (temporaryPasswordOneTimeProperty != null) {
                this.temporaryPasswordOneTime = Boolean.parseBoolean(temporaryPasswordOneTimeProperty.trim());
            }

            String enableAuthPolicyProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.AUTH_POLICY_ENABLE);
            if (enableAuthPolicyProperty != null) {
                this.enableAuthPolicy = Boolean.parseBoolean(enableAuthPolicyProperty.trim());
            }

            String oneTimePasswordCheck = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.AUTH_POLICY_PASSWORD_ONE_TIME);
            if (oneTimePasswordCheck != null) {
                this.authPolicyOneTimePasswordCheck = Boolean.parseBoolean(oneTimePasswordCheck.trim());
            }

            String maxLoginAttemptProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.AUTH_POLICY_ACCOUNT_LOCKING_FAIL_ATTEMPTS);
            if (maxLoginAttemptProperty != null) {
                this.authPolicyMaxLoginAttempts = Integer.parseInt(maxLoginAttemptProperty.trim());
            }

            if (this.authPolicyMaxLoginAttempts == 0) {
                // default value is set
                this.authPolicyMaxLoginAttempts = 10;
            }

            String expirePasswordCheck = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.AUTH_POLICY_PASSWORD_EXPIRE);
            if (expirePasswordCheck != null) {
                this.authPolicyExpirePasswordCheck = Boolean.parseBoolean(expirePasswordCheck.trim());
            }

            String authPolicyLockingTimeProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.AUTH_POLICY_ACCOUNT_LOCKING_TIME);
            if (authPolicyLockingTimeProperty != null) {
                this.authPolicyLockingTime = Integer.parseInt(authPolicyLockingTimeProperty.trim());
            }

            String authPolicyPasswordExpireTimeProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.AUTH_POLICY_PASSWORD_EXPIRE_TIME);
            if (authPolicyPasswordExpireTimeProperty != null) {
                this.authPolicyPasswordExpireTime = Integer.parseInt(authPolicyPasswordExpireTimeProperty.trim());
            }

            String notificationExpireTimeProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.NOTIFICATION_LINK_EXPIRE_TIME);
            if (notificationExpireTimeProperty != null) {
                this.notificationExpireTime = Integer.parseInt(notificationExpireTimeProperty.trim());
            }

            String authPolicyAccountLockCheckProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.AUTH_POLICY_ACCOUNT_LOCK);
            if (authPolicyAccountLockCheckProperty != null) {
                this.authPolicyAccountLockCheck = Boolean.parseBoolean(authPolicyAccountLockCheckProperty.trim());
            }

            String authPolicyAccountExistCheckProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.AUTH_POLICY_ACCOUNT_EXIST);
            if (authPolicyAccountExistCheckProperty != null) {
                this.authPolicyAccountExistCheck = Boolean.parseBoolean(authPolicyAccountExistCheckProperty.trim());
            }

            String authPolicyAccountLockOnFailureProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.AUTH_POLICY_LOCK_ON_FAILURE);
            if (authPolicyAccountLockOnFailureProperty != null) {
                this.authPolicyAccountLockOnFailure = Boolean
                        .parseBoolean(authPolicyAccountLockOnFailureProperty.trim());
            }

            String authPolicyAccountLockOnCreationProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.AUTH_POLICY_ACCOUNT_LOCK_ON_CREATION);
            if (authPolicyAccountLockOnCreationProperty != null) {
                this.authPolicyAccountLockOnCreation = Boolean
                        .parseBoolean(authPolicyAccountLockOnCreationProperty.trim());
            }

            String digsestFunctionProperty = configuration.getUserStoreProperties()
                    .get(JDBCRealmConstants.DIGEST_FUNCTION);
            if (digsestFunctionProperty != null && digsestFunctionProperty.trim().length() > 0) {
                this.digsestFunction = digsestFunctionProperty;
            }

            String challengeQuestionSeparatorProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.CHALLENGE_QUESTION_SEPARATOR);
            if (challengeQuestionSeparatorProperty != null
                    && challengeQuestionSeparatorProperty.trim().length() == 1) {
                this.challengeQuestionSeparator = challengeQuestionSeparatorProperty.trim();
            } else {
                this.challengeQuestionSeparator = IdentityMgtConstants.LINE_SEPARATOR;
            }

            String passwordGeneratorProperty = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.EXTENSION_PASSWORD_GENERATOR);
            if (passwordGeneratorProperty != null && passwordGeneratorProperty.trim().length() > 0) {
                try {
                    Class clazz = Thread.currentThread().getContextClassLoader()
                            .loadClass(passwordGeneratorProperty);
                    this.passwordGenerator = (RandomPasswordGenerator) clazz.newInstance();
                } catch (Exception e) {
                    log.error("Error while loading random password generator class. "
                            + "Default random password generator would be used", e);
                }
            }

            String dataPersistModule = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.EXTENSION_USER_DATA_STORE);
            if (dataPersistModule != null && dataPersistModule.trim().length() > 0) {
                try {
                    Class clazz = Thread.currentThread().getContextClassLoader().loadClass(dataPersistModule);
                    this.identityDataStore = (UserIdentityDataStore) clazz.newInstance();
                } catch (Exception e) {
                    log.error("Error while loading user identity data persist class. " + dataPersistModule
                            + " Default module would be used", e);
                }
            }

            String recoveryPersistModule = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.EXTENSION_USER_RECOVERY_DATA_STORE);
            if (dataPersistModule != null && dataPersistModule.trim().length() > 0) {
                try {
                    Class clazz = Thread.currentThread().getContextClassLoader().loadClass(recoveryPersistModule);
                    this.recoveryDataStore = (UserRecoveryDataStore) clazz.newInstance();
                } catch (Exception e) {
                    log.error("Error while loading user recovery data persist class. " + dataPersistModule
                            + " Default module would be used", e);
                }
            }

            String registryCleanUpPeriod = properties
                    .getProperty(IdentityMgtConstants.PropertyConfig.REGISTRY_CLEANUP_PERIOD);
            if (StringUtils.isNotBlank(registryCleanUpPeriod)) {
                this.registryCleanUpPeriod = Long.parseLong(registryCleanUpPeriod);
            }

            int i = 1;
            while (true) {
                String module = properties.getProperty(
                        IdentityMgtConstants.PropertyConfig.EXTENSION_NOTIFICATION_SENDING_MODULE + "." + i);
                if (module == null) {
                    break;
                }
                if (module.trim().length() > 0) {
                    try {
                        Class clazz = Thread.currentThread().getContextClassLoader().loadClass(module);
                        NotificationSendingModule sendingModule = (NotificationSendingModule) clazz.newInstance();
                        String type = sendingModule.getNotificationType();
                        if (type == null || type.trim().length() == 0) {
                            log.error("Notification type can not be null. Module " + module + "  is not loaded.");
                        } else {
                            if (notificationTypes.contains(type)) {
                                log.error("Same Notification type can not be supported by more than "
                                        + "one module. Module " + module + "  is not loaded.");
                            } else {
                                notificationTypes.add(type);
                                sendingModule.init();
                                sendingModules.add(sendingModule);
                            }
                        }
                    } catch (Exception e) {
                        log.error("Error while loading notification sending class  " + module, e);
                    }
                }
                i++;
            }

            // Load the configuration for Password.policy.extensions.
            loadPolicyExtensions(properties, IdentityMgtConstants.PropertyConfig.PASSWORD_POLICY_EXTENSIONS);

            if (this.passwordGenerator == null) {
                this.passwordGenerator = new DefaultPasswordGenerator();
            }

            if (this.identityDataStore == null) {
                this.identityDataStore = new UserStoreBasedIdentityDataStore();
            }

            if (this.recoveryDataStore == null) {
                this.recoveryDataStore = new RegistryRecoveryDataStore();
            }

            if (this.sendingModules.isEmpty()) {
                NotificationSendingModule module = new DefaultEmailSendingModule();
                module.init();
                this.sendingModules.add(module);
                this.notificationTypes.add(module.getNotificationType());
            }

        } catch (Exception e) {
            log.error("Error while loading identity mgt configurations", e);
        }
    }

    /**
     * Gets instance
     * <p/>
     * As this is only called in start up syn and null check is not needed
     *
     * @param configuration a primary <code>RealmConfiguration</code>
     * @return <code>IdentityMgtConfig</code>
     */
    public static IdentityMgtConfig getInstance(RealmConfiguration configuration) {

        identityMgtConfig = new IdentityMgtConfig(configuration);
        return identityMgtConfig;
    }

    public static IdentityMgtConfig getInstance() {
        return identityMgtConfig;
    }

    public int getNoOfUserChallenges() {
        return noOfUserChallenges;
    }

    public boolean isSaasEnabled() {
        return saasEnable;
    }

    public boolean isNotificationInternallyManaged() {
        return notificationInternallyManaged;
    }

    public boolean isCaptchaVerificationInternallyManaged() {
        return captchaVerificationInternallyManaged;
    }

    public boolean isEnableUserAccountVerification() {
        return enableUserAccountVerification;
    }

    public int getAuthPolicyMaxLoginAttempts() {
        return authPolicyMaxLoginAttempts;
    }

    public int getTemporaryPasswordExpireTime() {
        return temporaryPasswordExpireTime;
    }

    public String getTemporaryDefaultPassword() {
        return temporaryDefaultPassword;
    }

    public boolean isEnableTemporaryPassword() {
        return enableTemporaryPassword;
    }

    public boolean isEnableAuthPolicy() {
        return enableAuthPolicy;
    }

    public boolean isAuthPolicyExpirePasswordCheck() {
        return authPolicyExpirePasswordCheck;
    }

    public boolean isAuthPolicyOneTimePasswordCheck() {
        return authPolicyOneTimePasswordCheck;
    }

    public int getAuthPolicyLockingTime() {
        return authPolicyLockingTime;
    }

    public boolean isAuthPolicyAccountLockCheck() {
        return authPolicyAccountLockCheck;
    }

    public boolean isUserAccountVerificationByUser() {
        return userAccountVerificationByUser;
    }

    public boolean isTemporaryPasswordOneTime() {
        return temporaryPasswordOneTime;
    }

    public String getUserAccountVerificationRole() {
        return userAccountVerificationRole;
    }

    public String getChallengeQuestionSeparator() {
        return challengeQuestionSeparator;
    }

    public String getDigsestFunction() {
        return digsestFunction;
    }

    public RandomPasswordGenerator getPasswordGenerator() {
        return passwordGenerator;
    }

    public UserIdentityDataStore getIdentityDataStore() {
        return identityDataStore;
    }

    public boolean isNotificationSending() {
        return notificationSending;
    }

    public boolean isAuthPolicyAccountExistCheck() {
        return authPolicyAccountExistCheck;
    }

    public boolean isAuthPolicyAccountLockOnFailure() {
        return authPolicyAccountLockOnFailure;
    }

    public int getAuthPolicyPasswordExpireTime() {
        return authPolicyPasswordExpireTime;
    }

    public boolean isAuthPolicyAccountLockOnCreation() {
        return authPolicyAccountLockOnCreation;
    }

    public int getNotificationExpireTime() {
        return notificationExpireTime;
    }

    public boolean isListenerEnable() {
        return listenerEnable;
    }

    public List<NotificationSendingModule> getNotificationSendingModules() {
        return sendingModules;
    }

    public String getAccountRecoveryClaim() {
        return recoveryClaim;
    }

    public List<String> getNotificationTypes() {
        return notificationTypes;
    }

    public UserRecoveryDataStore getRecoveryDataStore() {
        return recoveryDataStore;
    }

    public PolicyRegistry getPolicyRegistry() {
        return policyRegistry;
    }

    public long getRegistryCleanUpPeriod() {
        return registryCleanUpPeriod;
    }

    /**
     * This method is used to load the policies declared in the configuration.
     *
     * @param properties    Loaded properties
     * @param extensionType Type of extension
     */
    private void loadPolicyExtensions(Properties properties, String extensionType) {

        // First property must start with 1.
        int count = 1;
        String className = null;
        int size = 0;
        Enumeration<String> keyValues = (Enumeration<String>) properties.propertyNames();
        while (keyValues.hasMoreElements()) {
            String currentProp = keyValues.nextElement();
            if (currentProp.contains(extensionType)) {
                size++;
            }
        }
        //setting the number of extensionTypes as the upper bound as there can be many extension policy numbers,
        //eg: Password.policy.extensions.1, Password.policy.extensions.4, Password.policy.extensions.15
        while (size > 0) {
            className = properties.getProperty(extensionType + "." + count);
            if (className == null) {
                count++;
                continue;
            }
            try {
                Class clazz = Thread.currentThread().getContextClassLoader().loadClass(className);

                PolicyEnforcer policy = (PolicyEnforcer) clazz.newInstance();
                policy.init(getParameters(properties, extensionType, count));

                this.policyRegistry.addPolicy((PolicyEnforcer) policy);
                count++;
                size--;
            } catch (ClassNotFoundException | IllegalAccessException | InstantiationException
                    | SecurityException e) {
                log.error("Error while loading password policies " + className, e);
            }
        }

    }

    /**
     * This utility method is used to get the parameters from the configuration
     * file for a given policy extension.
     *
     * @param prop         - properties
     * @param extensionKey - extension key which is defined in the
     *                     IdentityMgtConstants
     * @param sequence     - property sequence number in the file
     * @return Map of parameters with key and value from the configuration file.
     */
    private Map<String, String> getParameters(Properties prop, String extensionKey, int sequence) {

        Set<String> keys = prop.stringPropertyNames();

        Map<String, String> keyValues = new HashMap<String, String>();

        for (String key : keys) {
            // Get only the provided extensions.
            // Eg.
            // Password.policy.extensions.1
            if (key.contains(extensionKey + "." + String.valueOf(sequence))) {

                Matcher m = propertyPattern.matcher(key);

                // Find the .1. pattern in the property key.
                if (m.find()) {
                    int searchIndex = m.end();

                    /*
                          * Key length is > matched pattern's end index if it has
                     * parameters
                     * in the config file.
                     */
                    if (key.length() > searchIndex) {
                        String propKey = key.substring(searchIndex);
                        String propValue = prop.getProperty(key);
                        keyValues.put(propKey, propValue);
                    }
                }

            }
        }

        return keyValues;
    }

    public Properties getProperties() {
        return properties;
    }

    public String getProperty(String key) {
        return properties.getProperty(key);
    }

    public void setProperty(String key, String value) {
        this.properties.setProperty(key, value);
    }
}