/*
 * 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.ranger.ldapconfigcheck;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.apache.commons.configuration2.FileBasedConfiguration;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.lang.NullArgumentException;

public class LdapConfig {

    public static final String CONFIG_FILE = "input.properties";

    private static final String LGSYNC_LDAP_URL = "ranger.usersync.ldap.url";

    private static final String LGSYNC_LDAP_BIND_DN = "ranger.usersync.ldap.binddn";

    private static final String LGSYNC_LDAP_BIND_PASSWORD = "ranger.usersync.ldap.ldapbindpassword";

    private static final String LGSYNC_LDAP_AUTHENTICATION_MECHANISM = "ranger.usersync.ldap.authentication.mechanism";
    private static final String DEFAULT_AUTHENTICATION_MECHANISM = "simple";

    private static final String LGSYNC_SEARCH_BASE = "ranger.usersync.ldap.searchBase";

    private static final String LGSYNC_USER_SEARCH_BASE = "ranger.usersync.ldap.user.searchbase";

    private static final String LGSYNC_USER_SEARCH_SCOPE = "ranger.usersync.ldap.user.searchscope";

    private static final String LGSYNC_USER_OBJECT_CLASS = "ranger.usersync.ldap.user.objectclass";

    private static final String LGSYNC_USER_SEARCH_FILTER = "ranger.usersync.ldap.user.searchfilter";

    private static final String LGSYNC_USER_NAME_ATTRIBUTE = "ranger.usersync.ldap.user.nameattribute";

    private static final String LGSYNC_USER_GROUP_NAME_ATTRIBUTE = "ranger.usersync.ldap.user.groupnameattribute";

    public static final String UGSYNC_NONE_CASE_CONVERSION_VALUE = "none";
    public static final String UGSYNC_LOWER_CASE_CONVERSION_VALUE = "lower";

    private static final String UGSYNC_USERNAME_CASE_CONVERSION_PARAM = "ranger.usersync.ldap.username.caseconversion";
    private static final String DEFAULT_UGSYNC_USERNAME_CASE_CONVERSION_VALUE = UGSYNC_NONE_CASE_CONVERSION_VALUE;

    private static final String UGSYNC_GROUPNAME_CASE_CONVERSION_PARAM = "ranger.usersync.ldap.groupname.caseconversion";
    private static final String DEFAULT_UGSYNC_GROUPNAME_CASE_CONVERSION_VALUE = UGSYNC_NONE_CASE_CONVERSION_VALUE;


    private static final String LGSYNC_PAGED_RESULTS_ENABLED = "ranger.usersync.pagedresultsenabled";
    private static final boolean DEFAULT_LGSYNC_PAGED_RESULTS_ENABLED = true;

    private static final String LGSYNC_PAGED_RESULTS_SIZE = "ranger.usersync.pagedresultssize";
    private static final int DEFAULT_LGSYNC_PAGED_RESULTS_SIZE = 500;

    private static final String LGSYNC_GROUP_SEARCH_ENABLED = "ranger.usersync.group.searchenabled";
    private static final boolean DEFAULT_LGSYNC_GROUP_SEARCH_ENABLED = false;

    private static final String LGSYNC_GROUP_USER_MAP_SYNC_ENABLED = "ranger.usersync.group.usermapsyncenabled";
    private static final boolean DEFAULT_LGSYNC_GROUP_USER_MAP_SYNC_ENABLED = false;

    private static final String LGSYNC_GROUP_SEARCH_BASE = "ranger.usersync.group.searchbase";

    private static final String LGSYNC_GROUP_SEARCH_SCOPE = "ranger.usersync.group.searchscope";

    private static final String LGSYNC_GROUP_OBJECT_CLASS = "ranger.usersync.group.objectclass";

    private static final String LGSYNC_GROUP_SEARCH_FILTER = "ranger.usersync.group.searchfilter";

    private static final String LGSYNC_GROUP_NAME_ATTRIBUTE = "ranger.usersync.group.nameattribute";

    private static final String LGSYNC_GROUP_MEMBER_ATTRIBUTE_NAME = "ranger.usersync.group.memberattributename";

    //Authentication related properties
    private static final String AUTHENTICATION_METHOD = "ranger.authentication.method";
    private static final String AD_DOMAIN = "ranger.ldap.ad.domain";
    private static final String USER_DN_PATTERN = "ranger.ldap.user.dnpattern";
    private static final String GROUP_ROLE_ATTRIBUTE = "ranger.ldap.group.roleattribute";
    private static final String GROUP_SEARCH_BASE = "ranger.ldap.group.searchbase";
    private static final String GROUP_SEARCH_FILTER = "ranger.ldap.group.searchfilter";
    private static final String AUTH_USERNAME = "ranger.admin.auth.sampleuser";
    private static final String AUTH_PASSWORD = "ranger.admin.auth.samplepassword";


    private Properties prop = new Properties();


    public LdapConfig(String configFile, String bindPasswd) {
        init(configFile, bindPasswd);
    }

    private void init(String configFile, String bindPasswd) {
        readConfigFile(configFile);
        prop.setProperty(LGSYNC_LDAP_BIND_PASSWORD, bindPasswd);
    }

    private void readConfigFile(String fileName) {
        try {
            InputStream in = getFileInputStream(fileName);
            if (in != null) {
                try {
                    System.out.println("Reading ldap properties from " + fileName);
                    prop.load(in);

                } finally {
                    try {
                        in.close();
                    } catch (IOException ioe) {
                        // Ignore IOE when closing stream
                        System.out.println(ioe);
                    }
                }
            }
        } catch (Throwable e) {
            throw new RuntimeException("Unable to load configuration file [" + fileName + "]", e);
        }
    }


    /*private InputStream getFileInputStream(String path) throws FileNotFoundException {

        InputStream ret = null;

        File f = new File(path);

        if (f.exists()) {
            ret = new FileInputStream(f);
        }

        return ret;
    }*/

    private InputStream getFileInputStream(String path) throws FileNotFoundException {

		InputStream ret = null;

		File f = new File(path);

		if (f.exists()) {
			ret = new FileInputStream(f);
		} else {
			ret = getClass().getResourceAsStream(path);
			
			if (ret == null) {
				if (! path.startsWith("/")) {
					ret = getClass().getResourceAsStream("/" + path);
				}
			}
			
			if (ret == null) {
				ret = ClassLoader.getSystemClassLoader().getResourceAsStream(path);
				if (ret == null) {
					if (! path.startsWith("/")) {
						ret = ClassLoader.getSystemResourceAsStream("/" + path);
					}
				}
			}
		}

		return ret;
	}

    public String getLdapUrl() throws Throwable {
        String val = prop.getProperty(LGSYNC_LDAP_URL);
        if (val == null || val.trim().isEmpty()) {
            throw new NullArgumentException(LGSYNC_LDAP_URL);
        }
        return val;
    }


    public String getLdapBindDn() throws Throwable {
        String val = prop.getProperty(LGSYNC_LDAP_BIND_DN);
        if (val == null || val.trim().isEmpty()) {
            throw new NullArgumentException(LGSYNC_LDAP_BIND_DN);
        }
        return val;
    }


    public String getLdapBindPassword() {
        //update credential from keystore
        if (prop == null) {
            return null;
        }
        return prop.getProperty(LGSYNC_LDAP_BIND_PASSWORD);
    }


    public String getLdapAuthenticationMechanism() {
        String val = prop.getProperty(LGSYNC_LDAP_AUTHENTICATION_MECHANISM);
        if (val == null || val.trim().isEmpty()) {
            return DEFAULT_AUTHENTICATION_MECHANISM;
        }
        return val;
    }


    public String getUserSearchBase() {
        String val = prop.getProperty(LGSYNC_USER_SEARCH_BASE);
        if (val == null || val.trim().isEmpty()) {
            val = getSearchBase();
        }
        return val;
    }


    public int getUserSearchScope() {
        String val = prop.getProperty(LGSYNC_USER_SEARCH_SCOPE);
        if (val == null || val.trim().isEmpty()) {
            return 2; //subtree scope
        }

        val = val.trim().toLowerCase();
        if (val.equals("0") || val.startsWith("base")) {
            return 0; // object scope
        } else if (val.equals("1") || val.startsWith("one")) {
            return 1; // one level scope
        } else {
            return 2; // subtree scope
        }
    }


    public String getUserObjectClass() {
        String val = prop.getProperty(LGSYNC_USER_OBJECT_CLASS);
        return val;
    }

    public String getUserSearchFilter() {
        return prop.getProperty(LGSYNC_USER_SEARCH_FILTER);
    }


    public String getUserNameAttribute() {
        String val = prop.getProperty(LGSYNC_USER_NAME_ATTRIBUTE);
        return val;
    }

    public String getUserGroupNameAttribute() {
        String val = prop.getProperty(LGSYNC_USER_GROUP_NAME_ATTRIBUTE);
        return val;
    }

    public String getUserNameCaseConversion() {
        String ret = prop.getProperty(UGSYNC_USERNAME_CASE_CONVERSION_PARAM, DEFAULT_UGSYNC_USERNAME_CASE_CONVERSION_VALUE);
        return ret.trim().toLowerCase();
    }

    public String getGroupNameCaseConversion() {
        String ret = prop.getProperty(UGSYNC_GROUPNAME_CASE_CONVERSION_PARAM, DEFAULT_UGSYNC_GROUPNAME_CASE_CONVERSION_VALUE);
        return ret.trim().toLowerCase();
    }

    public String getSearchBase() {
        return prop.getProperty(LGSYNC_SEARCH_BASE);
    }

    public boolean isPagedResultsEnabled() {
        boolean pagedResultsEnabled;
        String val = prop.getProperty(LGSYNC_PAGED_RESULTS_ENABLED);
        if (val == null || val.trim().isEmpty()) {
            pagedResultsEnabled = DEFAULT_LGSYNC_PAGED_RESULTS_ENABLED;
        } else {
            pagedResultsEnabled = Boolean.valueOf(val);
        }
        return pagedResultsEnabled;
    }

    public int getPagedResultsSize() {
        int pagedResultsSize;
        String val = prop.getProperty(LGSYNC_PAGED_RESULTS_SIZE);
        if (val == null || val.trim().isEmpty()) {
            pagedResultsSize = DEFAULT_LGSYNC_PAGED_RESULTS_SIZE;
        } else {
            pagedResultsSize = Integer.parseInt(val);
        }
        if (pagedResultsSize < 1) {
            pagedResultsSize = DEFAULT_LGSYNC_PAGED_RESULTS_SIZE;
        }
        return pagedResultsSize;
    }

    public boolean isGroupSearchEnabled() {
        boolean groupSearchEnabled;
        String val = prop.getProperty(LGSYNC_GROUP_SEARCH_ENABLED);
        if (val == null || val.trim().isEmpty()) {
            groupSearchEnabled = DEFAULT_LGSYNC_GROUP_SEARCH_ENABLED;
        } else {
            groupSearchEnabled = Boolean.valueOf(val);
        }
        return groupSearchEnabled;
    }

    public boolean isGroupUserMapSyncEnabled() {
        boolean groupUserMapSyncEnabled;
        String val = prop.getProperty(LGSYNC_GROUP_USER_MAP_SYNC_ENABLED);
        if (val == null || val.trim().isEmpty()) {
            groupUserMapSyncEnabled = DEFAULT_LGSYNC_GROUP_USER_MAP_SYNC_ENABLED;
        } else {
            groupUserMapSyncEnabled = Boolean.valueOf(val);
        }
        return groupUserMapSyncEnabled;
    }

    public String getGroupSearchBase() {
        String val = prop.getProperty(LGSYNC_GROUP_SEARCH_BASE);
        return val;
    }

    public int getGroupSearchScope() {
        String val = prop.getProperty(LGSYNC_GROUP_SEARCH_SCOPE);
        if (val == null || val.trim().isEmpty()) {
            return 2; //subtree scope
        }

        val = val.trim().toLowerCase();
        if (val.equals("0") || val.startsWith("base")) {
            return 0; // object scope
        } else if (val.equals("1") || val.startsWith("one")) {
            return 1; // one level scope
        } else {
            return 2; // subtree scope
        }
    }

    public String getGroupObjectClass() {
        String val = prop.getProperty(LGSYNC_GROUP_OBJECT_CLASS);
        return val;
    }

    public String getGroupSearchFilter() {
        return prop.getProperty(LGSYNC_GROUP_SEARCH_FILTER);
    }

    public String getUserGroupMemberAttributeName() {
        String val = prop.getProperty(LGSYNC_GROUP_MEMBER_ATTRIBUTE_NAME);
        return val;
    }

    public String getGroupNameAttribute() {
        String val = prop.getProperty(LGSYNC_GROUP_NAME_ATTRIBUTE);
        return val;
    }

    public String getAuthenticationMethod() {
        String val = prop.getProperty(AUTHENTICATION_METHOD);
        return val;
    }

    public String getAdDomain() {
        String val = prop.getProperty(AD_DOMAIN);
        return val;
    }

    public String getUserDnPattern() {
        String val = prop.getProperty(USER_DN_PATTERN);
        return val;
    }

    public String getGroupRoleAttribute() {
        String val = prop.getProperty(GROUP_ROLE_ATTRIBUTE);
        return val;
    }

    public String getAuthGroupSearchBase() {
        String val = prop.getProperty(GROUP_SEARCH_BASE);
        return val;
    }

    public String getAuthGroupSearchFilter() {
        String val = prop.getProperty(GROUP_SEARCH_FILTER);
        return val;
    }

    public String getAuthUsername() {
        return prop.getProperty(AUTH_USERNAME);
    }

    public String getAuthPassword() {
        return prop.getProperty(AUTH_PASSWORD);
    }

    public void updateInputPropFile(String ldapUrl, String bindDn, String bindPassword,
                                    String userSearchBase, String userSearchFilter,
                                    String authUser, String authPass) {
        try {
            Parameters params = new Parameters();
            FileBasedConfigurationBuilder<FileBasedConfiguration> builder =
                new FileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class)
                .configure(params.fileBased().setFileName(CONFIG_FILE));
            FileBasedConfiguration config = builder.getConfiguration();
            // Update properties in memory and update the file as well
            prop.setProperty(LGSYNC_LDAP_URL, ldapUrl);
            prop.setProperty(LGSYNC_LDAP_BIND_DN, bindDn);
            prop.setProperty(LGSYNC_LDAP_BIND_PASSWORD, bindPassword);
            prop.setProperty(LGSYNC_USER_SEARCH_BASE, userSearchBase);
            prop.setProperty(LGSYNC_USER_SEARCH_FILTER, userSearchFilter);
            prop.setProperty(AUTH_USERNAME, authUser);
            prop.setProperty(AUTH_PASSWORD, authPass);
            config.setProperty(LGSYNC_LDAP_URL, ldapUrl);
            config.setProperty(LGSYNC_LDAP_BIND_DN, bindDn);
            //config.setProperty(LGSYNC_LDAP_BIND_PASSWORD, bindPassword);
            config.setProperty(LGSYNC_USER_SEARCH_BASE, userSearchBase);
            config.setProperty(LGSYNC_USER_SEARCH_FILTER, userSearchFilter);
            config.setProperty(AUTH_USERNAME, authUser);
            //config.setProperty(AUTH_PASSWORD, authPass);
            builder.save();
        } catch (ConfigurationException e) {
            System.out.println("Failed to update " + CONFIG_FILE + ": " + e);
        }
    }
}





