/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2022 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed 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.jboss.installer.validators;

import org.jboss.installer.core.ValidationResult;
import org.jboss.installer.postinstall.ldap.LdapSecurity;
import org.jboss.installer.postinstall.task.LDAPSetupTask;
import org.jboss.installer.postinstall.task.SecurityDomainTask;
import org.jboss.installer.test.utils.MockLanguageUtils;
import org.junit.Before;
import org.junit.Test;

import static org.jboss.installer.screens.LDAPConnectionScreen.LDAP_SCREEN_LABEL_DIRECTORY_SERVER;
import static org.jboss.installer.screens.LDAPConnectionScreen.LDAP_SCREEN_LABEL_DISTINGUISHED_NAME;
import static org.jboss.installer.screens.LDAPConnectionScreen.LDAP_SCREEN_LABEL_DN_PASSWORD;
import static org.jboss.installer.screens.LDAPSecurityRealmScreen.LDAP_REALM_SCREEN_BASE_DN_LABEL;
import static org.jboss.installer.screens.LDAPSecurityRealmScreen.LDAP_REALM_SCREEN_USERNAME_FILTER_LABEL;
import static org.jboss.installer.screens.domain.LdapSecurityDomainPanel.LDAP_PASSWORD_ATTR_LABEL;
import static org.jboss.installer.screens.domain.LdapSecurityDomainPanel.LDAP_ROLES_ATTR_LABEL;
import static org.jboss.installer.screens.domain.LdapSecurityDomainPanel.LDAP_ROLES_FILTER_LABEL;
import static org.jboss.installer.screens.domain.LdapSecurityDomainPanel.LDAP_ROLE_FILTER_BASE_DN_LABEL;
import static org.jboss.installer.validators.CertificateSecurityDomainValidator.GENERIC_VALIDATION_EMPTY_FIELD;
import static org.junit.Assert.assertEquals;

public class LdapSecurityDomainValidatorTest {

    private final MockLanguageUtils langUtils = new MockLanguageUtils();
    private final LDAPSecurityDomainValidator validator = new LDAPSecurityDomainValidator(langUtils);
    private LdapSecurity.Model config;

    @Before
    public void setUp() {
        config = defaultConfig();
    }

    @Test
    public void testDefaultConfigOK() {
        assertEquals(ValidationResult.ok(), validator.validate(config));
    }

    @Test
    public void testUrlPresentExistsAndNonEmpty() {
        final String expectedError = langUtils.getString(GENERIC_VALIDATION_EMPTY_FIELD, langUtils.getString(LDAP_SCREEN_LABEL_DIRECTORY_SERVER));
        config.setConnection("test-domain-name" + ".connection", null, "uid=admin,ou=system", "password");
        assertEquals(ValidationResult.error(expectedError), validator.validate(config));
    }

    @Test
    public void testLdapUsernamePresentExistsAndNonEmpty() {
        final String expectedError = langUtils.getString(GENERIC_VALIDATION_EMPTY_FIELD, langUtils.getString(LDAP_SCREEN_LABEL_DISTINGUISHED_NAME));
        config.setConnection("test-domain-name" + ".connection", "ldap://127.0.0.1:10389", null, "password");
        assertEquals(ValidationResult.error(expectedError), validator.validate(config));
    }

    @Test
    public void testLdapPasswordPresentExistsAndNonEmpty() {
        final String expectedError = langUtils.getString(GENERIC_VALIDATION_EMPTY_FIELD, langUtils.getString(LDAP_SCREEN_LABEL_DN_PASSWORD));
        config.setConnection("test-domain-name" + ".connection", "ldap://127.0.0.1:10389", "uid=admin,ou=system", null);
        assertEquals(ValidationResult.error(expectedError), validator.validate(config));
    }

    @Test
    public void testBaseDNPresentExistsAndNonEmpty() {
        final String expectedError = langUtils.getString(GENERIC_VALIDATION_EMPTY_FIELD, langUtils.getString(LDAP_REALM_SCREEN_BASE_DN_LABEL));
        config.setUserFilter(LDAPSetupTask.FilterType.USERNAME, "uid", null, "userPassword", true);
        assertEquals(ValidationResult.error(expectedError), validator.validate(config));
    }

    @Test
    public void testUserFilterPresentExistsAndNonEmpty() {
        final String expectedError = langUtils.getString(GENERIC_VALIDATION_EMPTY_FIELD, langUtils.getString(LDAP_REALM_SCREEN_USERNAME_FILTER_LABEL));
        config.setUserFilter(LDAPSetupTask.FilterType.USERNAME, null, "ou=Users,dc=example,dc=org", "userPassword", true);
        assertEquals(ValidationResult.error(expectedError), validator.validate(config));
    }

    @Test
    public void testPasswordAttributePresentExistsAndNonEmpty() {
        final String expectedError = langUtils.getString(GENERIC_VALIDATION_EMPTY_FIELD, langUtils.getString(LDAP_PASSWORD_ATTR_LABEL));
        config.setUserFilter(LDAPSetupTask.FilterType.USERNAME, "uid", "ou=Users,dc=example,dc=org", null, true);
        assertEquals(ValidationResult.error(expectedError), validator.validate(config));
    }

    @Test
    public void testRoleFilterBaseDNPresentExistsAndNonEmpty() {
        final String expectedError = langUtils.getString(GENERIC_VALIDATION_EMPTY_FIELD, langUtils.getString(LDAP_ROLE_FILTER_BASE_DN_LABEL));
        config.setRole(null, "(&(objectClass=groupOfNames)(member={1}))", "cn");
        assertEquals(ValidationResult.error(expectedError), validator.validate(config));
    }

    @Test
    public void testRolesFilterPresentExistsAndNonEmpty() {
        final String expectedError = langUtils.getString(GENERIC_VALIDATION_EMPTY_FIELD, langUtils.getString(LDAP_ROLES_FILTER_LABEL));
        config.setRole("ou=Roles,dc=example,dc=org", null, "cn");
        assertEquals(ValidationResult.error(expectedError), validator.validate(config));
    }

    @Test
    public void testRolesAttributePresentExistsAndNonEmpty() {
        final String expectedError = langUtils.getString(GENERIC_VALIDATION_EMPTY_FIELD, langUtils.getString(LDAP_ROLES_ATTR_LABEL));
        config.setRole("ou=Roles,dc=example,dc=org", "(&(objectClass=groupOfNames)(member={1}))", null);
        assertEquals(ValidationResult.error(expectedError), validator.validate(config));
    }

    private LdapSecurity.Model defaultConfig() {
        final LdapSecurity.Model config = new LdapSecurity.Model();
        config.setRealmName("test-domain-name" + SecurityDomainTask.REALM_SUFFIX);
        config.setConnection("test-domain-name" + ".connection", "ldap://127.0.0.1:10389", "uid=admin,ou=system", "password");
        config.setUserFilter(LDAPSetupTask.FilterType.USERNAME, "uid", "ou=Users,dc=example,dc=org", "userPassword", true);
        config.setRole("ou=Roles,dc=example,dc=org", "(&(objectClass=groupOfNames)(member={1}))", "cn");
        return config;
    }
}
