/*
 * 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.sling.jcr.jackrabbit.usermanager.it.post;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.ops4j.pax.exam.CoreOptions.options;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

import javax.inject.Inject;
import javax.jcr.AccessDeniedException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.security.Privilege;

import org.apache.jackrabbit.api.security.user.User;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
import org.apache.sling.jackrabbit.usermanager.AuthorizablePrivilegesInfo;
import org.apache.sling.jackrabbit.usermanager.ChangeUserPassword;
import org.apache.sling.jackrabbit.usermanager.CreateGroup;
import org.apache.sling.jackrabbit.usermanager.CreateUser;
import org.apache.sling.jackrabbit.usermanager.DeleteUser;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.jackrabbit.accessmanager.DeleteAces;
import org.apache.sling.jcr.jackrabbit.accessmanager.ModifyAce;
import org.apache.sling.jcr.jackrabbit.usermanager.it.UserManagerTestSupport;
import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerClass;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Basic test of ChangeUserPassword component
 */
@RunWith(PaxExam.class)
@ExamReactorStrategy(PerClass.class)
public class ChangeUserPasswordIT extends UserManagerTestSupport {

    private static AtomicLong counter = new AtomicLong(0);

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Inject
    protected BundleContext bundleContext;

    @Inject
    protected SlingRepository repository;

    @Inject
    protected ConfigurationAdmin configAdmin;

    @Inject
    private CreateUser createUser;

    @Inject
    private CreateGroup createGroup;

    @Inject
    private ModifyAce modifyAce;

    @Inject
    private DeleteAces deleteAces;

    @Inject
    private DeleteUser deleteUser;

    @Inject
    private AuthorizablePrivilegesInfo privilegesInfo;

    @Rule
    public TestName testName = new TestName();

    protected Session adminSession;
    protected User user1;
    protected Session user1Session;

    @Configuration
    public Option[] configuration() {
        return options(
            baseConfiguration()
        );
    }

    @Before
    public void setup() throws RepositoryException {
        adminSession = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
        assertNotNull("Expected adminSession to not be null", adminSession);

        user1 = createUser.createUser(adminSession, createUniqueName("user"), "testPwd", "testPwd",
                Collections.emptyMap(), new ArrayList<>());
        assertNotNull("Expected user1 to not be null", user1);

        user1Session = repository.login(new SimpleCredentials(user1.getID(), "testPwd".toCharArray()));
        assertNotNull("Expected user1Session to not be null", user1Session);

        //change the ACE for the user home folder to the minimum privileges
        // and without rep:userManagement
        deleteAces.deleteAces(adminSession, user1.getPath(), new String[] {user1.getID()});
        Map<String, String> privileges = new HashMap<>();
        privileges.put(String.format("privilege@%s", Privilege.JCR_READ), "granted");
        privileges.put(String.format("privilege@%s", PrivilegeConstants.REP_ALTER_PROPERTIES), "granted");
        modifyAce.modifyAce(adminSession, user1.getPath(), user1.getID(),
                privileges,
                "first");
        if (adminSession.hasPendingChanges()) {
            adminSession.save();
        }
    }

    @After
    public void teardown() {
        try {
            adminSession.refresh(false);
            if (user1 != null) {
                deleteUser.deleteUser(adminSession, user1.getID(), new ArrayList<>());
            }
            if (adminSession.hasPendingChanges()) {
                adminSession.save();
            }
        } catch (RepositoryException e) {
            logger.warn(String.format("Failed to delete user: %s", e.getMessage()), e);
        }

        user1Session.logout();
        adminSession.logout();
    }

    protected String createUniqueName(String prefix) {
        return String.format("%s_%s%d", prefix, testName.getMethodName(), counter.incrementAndGet());
    }

    /**
     * SLING-9808 test changing password when user doesn't have rep:userManagement privilege
     */
    @Test
    public void changePasswordAsSelfGranted() throws IOException, RepositoryException {
        org.osgi.service.cm.Configuration configuration = configAdmin.getConfiguration("org.apache.sling.jackrabbit.usermanager.impl.post.ChangeUserPasswordServlet", null);
        Dictionary<String, Object> originalServiceProps = configuration.getProperties();
        ServiceReference<ChangeUserPassword> serviceReference = null;
        try {
            // update the service configuration to ensure the option is enabled
            Dictionary<String, Object> newServiceProps = replaceConfigProp(originalServiceProps, "alwaysAllowSelfChangePassword", Boolean.TRUE);
            configuration.update(newServiceProps);
            new WaitForServiceUpdated(5000, 100, bundleContext, ChangeUserPassword.class,
                    "alwaysAllowSelfChangePassword", Boolean.TRUE);

            serviceReference = bundleContext.getServiceReference(ChangeUserPassword.class);
            assertEquals(Boolean.TRUE, serviceReference.getProperty("alwaysAllowSelfChangePassword"));
            ChangeUserPassword changeUserPassword = bundleContext.getService(serviceReference);
            assertNotNull(changeUserPassword);

            // user can do the operation
            assertTrue("Should be allowed to change the user password",
                    privilegesInfo.canChangePassword(user1Session, user1.getID()));

            changeUserPassword.changePassword(user1Session,
                    user1.getID(),
                    "testPwd",
                    "testPwdChanged",
                    "testPwdChanged",
                    new ArrayList<>());
            try {
                user1Session.save();
            } catch (AccessDeniedException e) {
                logger.error(String.format("Did not expect AccessDeniedException when changing user passsword: %s", e.getMessage()), e);
                fail("Did not expect AccessDeniedException when changing user passsword: " + e.getMessage());
            }
        } finally {
            if (serviceReference != null) {
                // done with this.
                bundleContext.ungetService(serviceReference);
            }
            
            //put the original config back
            configuration.update(originalServiceProps);
            new WaitForServiceUpdated(5000, 100, bundleContext, ChangeUserPassword.class, "alwaysAllowSelfChangePassword",
                    originalServiceProps == null ? null :originalServiceProps.get("alwaysAllowSelfChangePassword"));
        }
    }

    /**
     * SLING-9808 test changing password when user doesn't have rep:userManagement privilege
     */
    @Test
    public void changePasswordAsSelfDenied() throws IOException, RepositoryException {
        org.osgi.service.cm.Configuration configuration = configAdmin.getConfiguration("org.apache.sling.jackrabbit.usermanager.impl.post.ChangeUserPasswordServlet", null);
        Dictionary<String, Object> originalServiceProps = configuration.getProperties();
        ServiceReference<ChangeUserPassword> serviceReference = null;
        try {
            // update the service configuration to ensure the option is disabled
            Dictionary<String, Object> newServiceProps = replaceConfigProp(originalServiceProps, "alwaysAllowSelfChangePassword", Boolean.FALSE);
            configuration.update(newServiceProps);
            new WaitForServiceUpdated(5000, 100, bundleContext, ChangeUserPassword.class,
                    "alwaysAllowSelfChangePassword", Boolean.FALSE);

            serviceReference = bundleContext.getServiceReference(ChangeUserPassword.class);
            assertEquals(Boolean.FALSE, serviceReference.getProperty("alwaysAllowSelfChangePassword"));
            ChangeUserPassword changeUserPassword = bundleContext.getService(serviceReference);
            assertNotNull(changeUserPassword);

            // user can't do the operation
            assertFalse("Should not be allowed to change the user password",
                    privilegesInfo.canChangePassword(user1Session, user1.getID()));

            changeUserPassword.changePassword(user1Session,
                    user1.getID(),
                    "testPwd",
                    "testPwdChanged",
                    "testPwdChanged",
                    new ArrayList<>());
            assertTrue(user1Session.hasPendingChanges());
            try {
                user1Session.save();
                fail("Expected an AccessDeniedException when changing user passsword.");
            } catch (AccessDeniedException e) {
                // expected an Access is denied exception
                Throwable cause = e.getCause();
                assertTrue(cause instanceof CommitFailedException);
                assertEquals("OakAccess0000: Access denied", cause.getMessage());
            }
        } finally {
            if (serviceReference != null) {
                // done with this.
                bundleContext.ungetService(serviceReference);
            }

            //put the original config back
            configuration.update(originalServiceProps);
            new WaitForServiceUpdated(5000, 100, bundleContext, ChangeUserPassword.class, "alwaysAllowSelfChangePassword",
                    originalServiceProps == null ? null :originalServiceProps.get("alwaysAllowSelfChangePassword"));
        }
    }

    /**
     * test changing your own password without sending the old password is not allowed
     */
    @Test
    public void changePasswordAsSelfWithoutOldPasswordFails() throws IOException, RepositoryException {
        org.osgi.service.cm.Configuration configuration = configAdmin.getConfiguration("org.apache.sling.jackrabbit.usermanager.impl.post.ChangeUserPasswordServlet", null);
        Dictionary<String, Object> originalServiceProps = configuration.getProperties();
        ServiceReference<ChangeUserPassword> serviceReference = null;
        try {
            // update the service configuration to ensure the option is enabled
            Dictionary<String, Object> newServiceProps = replaceConfigProp(originalServiceProps, "alwaysAllowSelfChangePassword", Boolean.TRUE);
            configuration.update(newServiceProps);
            new WaitForServiceUpdated(5000, 100, bundleContext, ChangeUserPassword.class,
                    "alwaysAllowSelfChangePassword", Boolean.TRUE);

            serviceReference = bundleContext.getServiceReference(ChangeUserPassword.class);
            assertEquals(Boolean.TRUE, serviceReference.getProperty("alwaysAllowSelfChangePassword"));
            ChangeUserPassword changeUserPassword = bundleContext.getService(serviceReference);
            assertNotNull(changeUserPassword);

            // user can do the operation
            assertTrue("Should be allowed to change the user password",
                    privilegesInfo.canChangePassword(user1Session, user1.getID()));

            // no oldPassword submitted
            @NotNull
            String user1Id = user1.getID();
            try {
                changeUserPassword.changePassword(user1Session,
                        user1Id,
                        null,
                        "testPwdChanged",
                        "testPwdChanged",
                        new ArrayList<>());
                fail("Expected a RepositoryException when changing user passsword.");
            } catch (RepositoryException e) {
                assertEquals("Old Password was not submitted", e.getMessage());
                user1Session.refresh(false);
            }

            // empty oldPassword submitted
            try {
                changeUserPassword.changePassword(user1Session,
                        user1Id,
                        "",
                        "testPwdChanged2",
                        "testPwdChanged2",
                        new ArrayList<>());
                fail("Expected a RepositoryException when changing user passsword.");
            } catch (RepositoryException e) {
                assertEquals("Old Password was not submitted", e.getMessage());
                user1Session.refresh(false);
            }

        } finally {
            if (serviceReference != null) {
                // done with this.
                bundleContext.ungetService(serviceReference);
            }

            //put the original config back
            configuration.update(originalServiceProps);
            new WaitForServiceUpdated(5000, 100, bundleContext, ChangeUserPassword.class, "alwaysAllowSelfChangePassword",
                    originalServiceProps == null ? null :originalServiceProps.get("alwaysAllowSelfChangePassword"));
        }
    }

    /**
     * test changing a user's password without sending the old password is allowed if the current
     * user is a member of the UserAdmin group.
     */
    @Test
    public void changePasswordAsUserAdminMemberWithoutOldPassword() throws RepositoryException {
        User user2 = null;
        ServiceReference<ChangeUserPassword> serviceReference = null;
        try {
            // create a second user to attempt the change password on
            user2 = createUser.createUser(adminSession, createUniqueName("user"), "testPwd", "testPwd",
                    Collections.emptyMap(), new ArrayList<>());
            if (adminSession.hasPendingChanges()) {
                adminSession.save();
            }

            // figure out what the user admin group name has been configured as
            serviceReference = bundleContext.getServiceReference(ChangeUserPassword.class);
            String userAdminGroup = (String)serviceReference.getProperty("user.admin.group.name");
            if (userAdminGroup == null || userAdminGroup.isEmpty()) {
                userAdminGroup = "UserAdmin"; // fallback to the default
            }

            // add user1 to the UserAdmin group
            createGroup.createGroup(adminSession, userAdminGroup,
                    Collections.singletonMap(":member", user1.getID()), new ArrayList<>());
            if (adminSession.hasPendingChanges()) {
                adminSession.save();
            }

            //make sure the UserAdmin group has the expected privileges granted
            Map<String, String> privileges = new HashMap<>();
            privileges.put(String.format("privilege@%s", Privilege.JCR_READ), "granted");
            privileges.put(String.format("privilege@%s", Privilege.JCR_READ_ACCESS_CONTROL), "granted");
            privileges.put(String.format("privilege@%s", Privilege.JCR_MODIFY_ACCESS_CONTROL), "granted");
            privileges.put(String.format("privilege@%s", PrivilegeConstants.REP_WRITE), "granted");
            privileges.put(String.format("privilege@%s", PrivilegeConstants.REP_USER_MANAGEMENT), "granted");
            modifyAce.modifyAce(adminSession, user2.getPath(), userAdminGroup,
                    privileges,
                    "first");


            // create a fresh session so changes from the adminSession are picked up
            user1Session.logout();
            user1Session = repository.login(new SimpleCredentials(user1.getID(), "testPwd".toCharArray()));
            assertNotNull("Expected user1Session to not be null", user1Session);

            ChangeUserPassword changeUserPassword = bundleContext.getService(serviceReference);
            assertNotNull(changeUserPassword);

            // user can do the operation
            assertTrue("Should be allowed to change the user password",
                    privilegesInfo.canChangePassword(user1Session, user2.getID()));

            // no oldPassword submitted
            try {
                changeUserPassword.changePassword(user1Session,
                        user2.getID(),
                        null,
                        "testPwdChanged",
                        "testPwdChanged",
                        new ArrayList<>());
            } catch (RepositoryException e) {
                fail("Did not expect a RepositoryException when changing user passsword.");
            }
            try {
                user1Session.save();
            } catch (AccessDeniedException e) {
                logger.error(String.format("Did not expect AccessDeniedException when changing user passsword: %s", e.getMessage()), e);
                fail("Did not expect AccessDeniedException when changing user passsword: " + e.getMessage());
            }

            // empty oldPassword submitted
            try {
                changeUserPassword.changePassword(user1Session,
                        user2.getID(),
                        "",
                        "testPwdChanged2",
                        "testPwdChanged2",
                        new ArrayList<>());
            } catch (RepositoryException e) {
                fail("Did not expect a RepositoryException when changing user passsword.");
            }
            try {
                user1Session.save();
            } catch (AccessDeniedException e) {
                logger.error(String.format("Did not expect AccessDeniedException when changing user passsword: %s", e.getMessage()), e);
                fail("Did not expect AccessDeniedException when changing user passsword: " + e.getMessage());
            }

        } finally {
            if (user2 != null) {
                deleteUser.deleteUser(adminSession, user2.getID(), new ArrayList<>());
            }

            if (serviceReference != null) {
                // done with this.
                bundleContext.ungetService(serviceReference);
            }
        }
    }

}
