/*
 * 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.geode.management.internal.cli.commands;

import static org.apache.geode.management.internal.cli.commands.AlterQueryServiceCommand.AUTHORIZER_NAME;
import static org.apache.geode.management.internal.cli.commands.AlterQueryServiceCommand.AUTHORIZER_PARAMETERS;
import static org.apache.geode.management.internal.cli.commands.AlterQueryServiceCommand.COMMAND_NAME;
import static org.apache.geode.management.internal.cli.commands.AlterQueryServiceCommand.NO_MEMBERS_FOUND_MESSAGE;
import static org.apache.geode.management.internal.cli.commands.AlterQueryServiceCommand.SPLITTING_REGEX;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.IntStream;

import junitparams.JUnitParamsRunner;
import org.apache.commons.io.FileUtils;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;

import org.apache.geode.cache.query.internal.QueryConfigurationService;
import org.apache.geode.cache.query.security.JavaBeanAccessorMethodAuthorizer;
import org.apache.geode.cache.query.security.MethodInvocationAuthorizer;
import org.apache.geode.cache.query.security.RegExMethodAuthorizer;
import org.apache.geode.cache.query.security.RestrictedMethodAuthorizer;
import org.apache.geode.cache.query.security.UnrestrictedMethodAuthorizer;
import org.apache.geode.examples.SimpleSecurityManager;
import org.apache.geode.management.internal.cli.util.TestMethodAuthorizer;
import org.apache.geode.test.compiler.ClassBuilder;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.rules.GfshCommandRule;
import org.apache.geode.test.junit.rules.VMProvider;

@RunWith(JUnitParamsRunner.class)
public class AlterQueryServiceCommandWithSecurityDUnitTest {
  private static final Class<RestrictedMethodAuthorizer> DEFAULT_AUTHORIZER_CLASS =
      RestrictedMethodAuthorizer.class;
  private static final String TEST_AUTHORIZER_TXT = "TestMethodAuthorizer.txt";
  private static final String USER_AUTHORIZER_PARAMETERS = "param1;param2;param3";
  private static final String JAVA_BEAN_AUTHORIZER_PARAMETERS = "java.lang;java.util";
  // A regex containing a comma to confirm that '--authorizer-parameter' is correctly parsed
  private static final String REGEX_AUTHORIZER_PARAMETERS =
      "^java.util.List..{4,8}$;^java.util.Set..{4,8}$";
  private MemberVM locator;
  private List<MemberVM> servers = new ArrayList<>();

  @Rule
  public GfshCommandRule gfsh = new GfshCommandRule();

  @Rule
  public TemporaryFolder tempFolder = new TemporaryFolder();

  @Rule
  public ClusterStartupRule cluster = new ClusterStartupRule();

  @Before
  public void setUp() throws Exception {
    locator = cluster.startLocatorVM(0, l -> l.withSecurityManager(SimpleSecurityManager.class));
    int locatorPort = locator.getPort();
    IntStream.range(0, 2).forEach(i -> servers.add(i, cluster.startServerVM(i + 1, s -> s
        .withConnectionToLocator(locatorPort).withCredential("clusterManage", "clusterManage"))));
    gfsh.connectAndVerify(locator);
  }

  private String buildCommand(String authorizerName, String authorizerParameters) {
    StringBuilder commandBuilder = new StringBuilder(COMMAND_NAME);
    commandBuilder.append(" --").append(AUTHORIZER_NAME).append("=").append(authorizerName);

    if (authorizerParameters != null) {
      commandBuilder.append(" --").append(AUTHORIZER_PARAMETERS).append("=")
          .append(authorizerParameters);
    }

    return commandBuilder.toString();
  }

  private void executeAndAssertGfshCommandIsSuccessful(
      Class<? extends MethodInvocationAuthorizer> authorizerClass,
      String authorizerParameters) {
    gfsh.executeAndAssertThat(buildCommand(authorizerClass.getName(), authorizerParameters))
        .statusIsSuccess().hasTableSection().hasRowSize(servers.size());

    verifyCurrentAuthorizerClass(authorizerClass);
  }

  private void startServerAndVerifyJavaBeanAccessorMethodAuthorizer() {
    int locatorPort = locator.getPort();
    MemberVM newServer = cluster.startServerVM(servers.size() + 1, s -> s
        .withConnectionToLocator(locatorPort).withCredential("clusterManage", "clusterManage"));
    newServer.invoke(() -> {
      JavaBeanAccessorMethodAuthorizer methodAuthorizer =
          (JavaBeanAccessorMethodAuthorizer) Objects.requireNonNull(ClusterStartupRule.getCache())
              .getService(QueryConfigurationService.class).getMethodAuthorizer();
      assertThat(methodAuthorizer.getClass()).isEqualTo(JavaBeanAccessorMethodAuthorizer.class);
      Set<String> expectedParameters =
          new HashSet<>(Arrays.asList(JAVA_BEAN_AUTHORIZER_PARAMETERS.split(SPLITTING_REGEX)));
      assertThat(methodAuthorizer.getAllowedPackages()).isEqualTo(expectedParameters);
    });
  }

  private void verifyCurrentAuthorizerClass(
      Class<? extends MethodInvocationAuthorizer> authorizerClass) {
    servers.forEach(server -> server.invoke(() -> {
      MethodInvocationAuthorizer methodAuthorizer =
          Objects.requireNonNull(ClusterStartupRule.getCache())
              .getService(QueryConfigurationService.class).getMethodAuthorizer();
      assertThat(methodAuthorizer.getClass()).isEqualTo(authorizerClass);
    }));
  }

  private String getTestMethodAuthorizerFilePath() throws IOException {
    URL url = getClass().getResource(TEST_AUTHORIZER_TXT);
    File textFile = this.tempFolder.newFile(TEST_AUTHORIZER_TXT);
    FileUtils.copyURLToFile(url, textFile);

    return textFile.getAbsolutePath();
  }

  // This test verifies that the cluster starts with the default method authorizer configured, then
  // changes the currently configured authorizer to each of the out-of-the-box authorizers.
  @Test
  public void alterQueryServiceCommandUpdatesMethodAuthorizerClass() {
    verifyCurrentAuthorizerClass(DEFAULT_AUTHORIZER_CLASS);
    executeAndAssertGfshCommandIsSuccessful(UnrestrictedMethodAuthorizer.class, "");
    executeAndAssertGfshCommandIsSuccessful(JavaBeanAccessorMethodAuthorizer.class,
        JAVA_BEAN_AUTHORIZER_PARAMETERS);
    executeAndAssertGfshCommandIsSuccessful(RegExMethodAuthorizer.class,
        REGEX_AUTHORIZER_PARAMETERS);
    executeAndAssertGfshCommandIsSuccessful(RestrictedMethodAuthorizer.class, "");
  }

  @Test
  public void alterQueryServiceCommandUpdatesMethodAuthorizerParameters() {
    gfsh.executeAndAssertThat(buildCommand(JavaBeanAccessorMethodAuthorizer.class.getName(),
        JAVA_BEAN_AUTHORIZER_PARAMETERS)).statusIsSuccess().hasTableSection()
        .hasRowSize(servers.size());
    servers.forEach(server -> server.invoke(() -> {
      JavaBeanAccessorMethodAuthorizer methodAuthorizer =
          (JavaBeanAccessorMethodAuthorizer) Objects.requireNonNull(ClusterStartupRule.getCache())
              .getService(QueryConfigurationService.class).getMethodAuthorizer();
      Set<String> expectedParameters =
          new HashSet<>(Arrays.asList(JAVA_BEAN_AUTHORIZER_PARAMETERS.split(SPLITTING_REGEX)));
      assertThat(methodAuthorizer.getAllowedPackages()).isEqualTo(expectedParameters);
    }));

    gfsh.executeAndAssertThat(
        buildCommand(RegExMethodAuthorizer.class.getName(), REGEX_AUTHORIZER_PARAMETERS))
        .statusIsSuccess().hasTableSection().hasRowSize(servers.size());
    servers.forEach(server -> server.invoke(() -> {
      RegExMethodAuthorizer methodAuthorizer =
          (RegExMethodAuthorizer) Objects.requireNonNull(ClusterStartupRule.getCache())
              .getService(QueryConfigurationService.class).getMethodAuthorizer();
      Set<String> expectedParameters =
          new HashSet<>(Arrays.asList(REGEX_AUTHORIZER_PARAMETERS.split(SPLITTING_REGEX)));
      assertThat(methodAuthorizer.getAllowedPatterns()).isEqualTo(expectedParameters);
    }));
  }

  @Test
  public void alterQueryServiceCommandWithUserSpecifiedMethodAuthorizerUpdatesMethodAuthorizer()
      throws IOException {
    verifyCurrentAuthorizerClass(DEFAULT_AUTHORIZER_CLASS);
    Class<TestMethodAuthorizer> authorizerClass = TestMethodAuthorizer.class;
    String authorizerName = authorizerClass.getName();
    String classContent =
        new String(Files.readAllBytes(Paths.get(getTestMethodAuthorizerFilePath())));
    String jarFileName = "testJar.jar";
    File jarFile = tempFolder.newFile(jarFileName);
    new ClassBuilder().writeJarFromContent(authorizerName, classContent, jarFile);

    gfsh.executeAndAssertThat("deploy --jars=" + jarFile.getAbsolutePath()).statusIsSuccess();
    executeAndAssertGfshCommandIsSuccessful(TestMethodAuthorizer.class, USER_AUTHORIZER_PARAMETERS);
    servers.forEach(server -> server.invoke(() -> {
      TestMethodAuthorizer methodAuthorizer =
          (TestMethodAuthorizer) Objects.requireNonNull(ClusterStartupRule.getCache())
              .getService(QueryConfigurationService.class).getMethodAuthorizer();
      Set<String> expectedParameters =
          new HashSet<>(Arrays.asList(USER_AUTHORIZER_PARAMETERS.split(SPLITTING_REGEX)));
      Assertions.assertThat(methodAuthorizer.getParameters()).isEqualTo(expectedParameters);
    }));
  }

  @Test
  public void alterQueryServiceCommandUpdatesClusterConfigWhenNoMembersAreFound() {
    servers.forEach(VMProvider::stop);
    Class<JavaBeanAccessorMethodAuthorizer> authorizerClass =
        JavaBeanAccessorMethodAuthorizer.class;
    String authorizerName = authorizerClass.getName();

    gfsh.executeAndAssertThat(buildCommand(authorizerName, JAVA_BEAN_AUTHORIZER_PARAMETERS))
        .statusIsSuccess().hasInfoSection().hasLines().contains(NO_MEMBERS_FOUND_MESSAGE);
    startServerAndVerifyJavaBeanAccessorMethodAuthorizer();
  }

  @Test
  public void alterQueryServiceCommandDoesNotUpdateClusterConfigWhenFunctionExecutionFailsOnAllMembers() {
    String authorizerName = "badAuthorizerName";

    gfsh.executeAndAssertThat(buildCommand(authorizerName, JAVA_BEAN_AUTHORIZER_PARAMETERS))
        .statusIsError();
    locator.invoke(() -> assertThat(Objects.requireNonNull(ClusterStartupRule.getLocator())
        .getConfigurationPersistenceService().getCacheConfig(null)).isNull());
  }
}
