/*
 * 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.scripting.core.it;

import static org.apache.sling.testing.paxexam.SlingOptions.slingAuthForm;
import static org.apache.sling.testing.paxexam.SlingOptions.slingQuickstartOakTar;
import static org.apache.sling.testing.paxexam.SlingOptions.slingScriptingJavascript;
import static org.apache.sling.testing.paxexam.SlingOptions.versionResolver;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.ops4j.pax.exam.CoreOptions.composite;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.vmOption;
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.factoryConfiguration;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.concurrent.Callable;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.auth.AuthenticationException;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.awaitility.Awaitility;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
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.options.ModifiableCompositeOption;
import org.ops4j.pax.exam.options.extra.VMOption;
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.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Tests for SLING-10147 - verify scripting variables implementation details are not 
 * exposed to not authorized users
 */
@RunWith(Enclosed.class)
public class SLING_10147IT {

    private SLING_10147IT() {
        // private constructor to hide the implicit public one
    }

    /**
     * Base class to share the common parts of LoadedIT and NotLoadedIT
     * tests
     */
    public abstract static class BaseIT extends ScriptingCoreTestSupport {
        protected final Logger logger = LoggerFactory.getLogger(getClass());

        protected CloseableHttpClient httpClient;

        @Rule
        public TestRule watcher = new TestWatcher() {

            /* (non-Javadoc)
             * @see org.junit.rules.TestWatcher#starting(org.junit.runner.Description)
             */
            @Override
            protected void starting(Description description) {
                logger.info("Starting test: {}", description.getMethodName());
            }

            /* (non-Javadoc)
             * @see org.junit.rules.TestWatcher#finished(org.junit.runner.Description)
             */
            @Override
            protected void finished(Description description) {
               logger.info("Finished test: {}", description.getMethodName());
            }

        };

        @Before
        public void before() {
            waitForServices();

            int timeout = 15; // seconds
            RequestConfig config = RequestConfig.custom()
              .setConnectTimeout(timeout * 1000)
              .setConnectionRequestTimeout(timeout * 1000)
              .setSocketTimeout(timeout * 1000).build();
            
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create()
                    .setRedirectStrategy(new LaxRedirectStrategy())
                    .setDefaultRequestConfig(config);
            httpClient = httpClientBuilder.build();
        }

        /**
         * Wait for services to be available
         */
        protected void waitForServices() {
            final BundleContext bundleContext = FrameworkUtil.getBundle(SLING_10147IT.class).getBundleContext();
            Awaitility.await()
                .atMost(Duration.ofMinutes(5))
                .pollInterval(Duration.ofSeconds(5))
                .until(new Callable<Boolean>() {

                    private String [] servicesLists = new String[] {
                            "org.apache.sling.jcr.api.SlingRepository",
                            "org.apache.sling.engine.auth.Authenticator",
                            "org.apache.sling.api.resource.ResourceResolverFactory",
                            "org.apache.sling.api.servlets.ServletResolver",
                            "javax.script.ScriptEngineManager"
                        };

                    @Override
                    public Boolean call() throws Exception {
                        boolean foundAllServices = true;
                        for (String serviceClass : servicesLists) {
                            ServiceReference<?> serviceReference = bundleContext.getServiceReference(serviceClass);
                            if (serviceReference == null) {
                                foundAllServices = false;
                                break;
                            }
                        }
                        return foundAllServices;
                    }

                });
        }

        @After
        public void after() throws IOException {
            if (httpClient != null) {
                httpClient.close();
                httpClient = null;
            }
        }

        @Configuration
        public Option[] configuration() {
            versionResolver.setVersionFromProject("org.apache.sling", "org.apache.sling.api");
            versionResolver.setVersionFromProject("org.apache.sling", "org.apache.sling.resourceresolver");
            versionResolver.setVersionFromProject("org.apache.sling", "org.apache.sling.servlets.resolver");
            versionResolver.setVersionFromProject("org.apache.sling", "org.apache.sling.scripting.api");

            final Option webconsolesecurityprovider = mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.extensions.webconsolesecurityprovider").versionAsInProject();
            return composite(
                        slingQuickstartOakTar(String.format("target/%s", getClass().getSimpleName()), httpPort),
                        slingScriptingJavascript(),
                        slingAuthForm(),
                        baseConfiguration(),
                        mavenBundle().groupId("org.apache.httpcomponents").artifactId("httpcore-osgi").version(versionResolver),
                        mavenBundle().groupId("org.apache.httpcomponents").artifactId("httpclient-osgi").version(versionResolver),
                        webconsolesecurityprovider,
                        optionalRemoteDebug()
                    ).remove(
                        scriptingCore // remove the old version
                    ).getOptions();
        }

        /**
         * Optionally configure remote debugging on the port supplied by the "debugPort"
         * system property.
         */
        protected ModifiableCompositeOption optionalRemoteDebug() {
            VMOption option = null;
            String property = System.getProperty("debugPort");
            if (property != null) {
                option = vmOption(String.format("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=%s", property));
            }
            return composite(option);
        }

        protected void checkContentType(CloseableHttpResponse response ,String expected) {
            // Remove whatever follows semicolon in content-type
            HttpEntity entity = response.getEntity();
            Header contentTypeHeader = entity.getContentType();
            String contentType = contentTypeHeader == null ? null : contentTypeHeader.getValue();
            if (contentType != null) {
                contentType = contentType.split(";")[0].trim();
            }
            // check for match
            assertEquals(expected, contentType);
        }
        
    }

    /**
     * Verify that when authorized that the scripting variables is accessible
     */
    @RunWith(PaxExam.class)
    @ExamReactorStrategy(PerClass.class)
    public static class AuthorizedIT extends BaseIT {

        @Test
        public void testGetSlingBindingsVariablesListJsonWithAuthorizedUser() throws IOException, AuthenticationException {
            // make GET request and verify it returned a 200 ok 
            HttpGet request = new HttpGet(String.format("http://localhost:%d/.SLING_availablebindings.json?extension=esp", httpPort()));
            // pre-emptive basic authentication
            request.addHeader(new BasicScheme().authenticate(new UsernamePasswordCredentials("admin", "admin"), request, null));
            
            if (logger.isInfoEnabled()) {
                logger.info("Executing GET Request to: {}", request.getURI());
            }
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Response Content\r\n: {}", IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8));
                }
                // should have passed all security checks and returned the JSON payload
                assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode());
                checkContentType(response, "application/json");
            }
        }
    }
    
    /**
     * Verify that when not authorized that the scripting variables is not accessible
     */
    @RunWith(PaxExam.class)
    @ExamReactorStrategy(PerClass.class)
    public static class NotAuthorizedIT extends BaseIT {

        @Configuration
        @Override
        public Option[] configuration() {
            return composite(super.configuration())
                    .add(// testing - add a user to use to login and verify
                         factoryConfiguration("org.apache.sling.jcr.repoinit.RepositoryInitializer")
                            .put("scripts", new String[] {
                                    "create user sling10147 with password sling10147"
                                })
                            .asOption()
                        )
                    .getOptions();
        }

        @Test
        public void testGetSlingBindingsVariablesListJsonWithNotAuthorizedUser() throws IOException, AuthenticationException {
            // make GET request and verify it is denied for user without sufficient rights 
            HttpGet request = new HttpGet(String.format("http://localhost:%d/.SLING_availablebindings.json?extension=esp", httpPort()));
            // pre-emptive basic authentication
            request.addHeader(new BasicScheme().authenticate(new UsernamePasswordCredentials("sling10147", "sling10147"), request, null));

            if (logger.isInfoEnabled()) {
                logger.info("Executing GET Request to: {}", request.getURI());
            }
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Response Content\r\n: {}", IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8));
                }
                // should have been denied access by WebConsoleSecurityProvider2 service access not granted to the user
                assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatusLine().getStatusCode());
                checkContentType(response, "text/html");
            }
        }

        @Test
        public void testGetSlingBindingsVariablesListJsonWithAnonymousUser() throws IOException, AuthenticationException {
            // make GET request and verify it returned a forms login page challenge 
            HttpGet request = new HttpGet(String.format("http://localhost:%d/.SLING_availablebindings.json?extension=esp", httpPort()));

            if (logger.isInfoEnabled()) {
                logger.info("Executing GET Request to: {}", request.getURI());
            }
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                String content = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
                if (logger.isInfoEnabled()) {
                    logger.info("Response Content\r\n: {}", content);
                }
                // should have been challenged for authentication by the WebConsoleSecurity2#authenitcate call
                assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode());
                checkContentType(response, "text/html");
                assertTrue("Expected forms based login page", content.contains("Login to Apache Sling"));
            }
        }
    }

    /**
     * Verify that when no WebConsoleSecurityProvider2 service is available that
     * the scripting variables is not accessible
     */
    @RunWith(PaxExam.class)
    @ExamReactorStrategy(PerClass.class)
    public static class HasNoWebConsoleSecurityProvider2IT extends BaseIT {

        @Configuration
        @Override
        public Option[] configuration() {
            // remove the security provider bundle from the configuration
            final Option webconsolesecurityprovider = mavenBundle().groupId("org.apache.sling").artifactId("org.apache.sling.extensions.webconsolesecurityprovider").versionAsInProject();
            return composite(super.configuration())
                    .remove(webconsolesecurityprovider)
                    .getOptions();
        }

        @Test
        public void testGetSlingBindingsVariablesListJsonWithoutWebConsoleSecurityProvider2() throws IOException, AuthenticationException {
            // make GET request and verify it returned a 403 error 
            HttpGet request = new HttpGet(String.format("http://localhost:%d/.SLING_availablebindings.json?extension=esp", httpPort()));
            // pre-emptive basic authentication
            request.addHeader(new BasicScheme().authenticate(new UsernamePasswordCredentials("admin", "admin"), request, null));

            if (logger.isInfoEnabled()) {
                logger.info("Executing GET Request to: {}", request.getURI());
            }
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Response Content\r\n: {}", IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8));
                }
                // should have failed fast due to the missing WebConsoleSecurityProvider2 service
                assertEquals(HttpServletResponse.SC_FORBIDDEN, response.getStatusLine().getStatusCode());
                checkContentType(response, "text/html");
            }
        }

    }

}
