/*
 * 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.cache.query.security;

import static org.apache.geode.cache.query.security.RegExMethodAuthorizer.NULL_AUTHORIZER_MESSAGE;
import static org.apache.geode.cache.query.security.RegExMethodAuthorizer.NULL_CACHE_MESSAGE;
import static org.apache.geode.cache.query.security.RegExMethodAuthorizer.NULL_REGULAR_EXPRESSIONS_MESSAGE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.configuration.RegionConfig;
import org.apache.geode.internal.cache.BucketDump;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.internal.cache.PartitionedRegion;
import org.apache.geode.internal.cache.ha.HAContainerMap;
import org.apache.geode.internal.cache.persistence.query.mock.Pair;
import org.apache.geode.internal.security.SecurityService;
import org.apache.geode.internal.util.Valuable;
import org.apache.geode.security.NotAuthorizedException;
import org.apache.geode.security.ResourcePermission;
import org.apache.geode.test.junit.categories.SecurityTest;

@Category(SecurityTest.class)
public class RegExMethodAuthorizerTest {
  private InternalCache mockCache;
  private SecurityService mockSecurityService;
  private RegExMethodAuthorizer geodeRegExMatchingMethodAuthorizer;

  @Before
  public void setUp() {
    mockCache = mock(InternalCache.class);
    mockSecurityService = mock(SecurityService.class);
    when(mockCache.getSecurityService()).thenReturn(mockSecurityService);
    geodeRegExMatchingMethodAuthorizer =
        new RegExMethodAuthorizer(new RestrictedMethodAuthorizer(mockCache),
            Collections.singleton("^org\\.apache\\.geode\\..*"));
  }

  @Test
  public void constructorShouldThrowExceptionWhenCacheIsNull() {
    assertThatThrownBy(() -> new RegExMethodAuthorizer((Cache) null, Collections.emptySet()))
        .isInstanceOf(NullPointerException.class)
        .hasMessage(NULL_CACHE_MESSAGE);
  }

  @Test
  public void constructorShouldThrowExceptionWhenRestrictedMethodAuthorizerIsNull() {
    assertThatThrownBy(
        () -> new RegExMethodAuthorizer((RestrictedMethodAuthorizer) null, Collections.emptySet()))
            .isInstanceOf(NullPointerException.class)
            .hasMessage(NULL_AUTHORIZER_MESSAGE);
  }

  @Test
  public void constructorShouldThrowExceptionWhenAllowedPatternsIsNull() {
    assertThatThrownBy(() -> new RegExMethodAuthorizer(mockCache, null))
        .isInstanceOf(NullPointerException.class)
        .hasMessage(NULL_REGULAR_EXPRESSIONS_MESSAGE);

    assertThatThrownBy(
        () -> new RegExMethodAuthorizer(new RestrictedMethodAuthorizer(mockCache), null))
            .isInstanceOf(NullPointerException.class)
            .hasMessage(NULL_REGULAR_EXPRESSIONS_MESSAGE);
  }

  @Test
  public void allowedPatternsShouldBeAccessibleBuNotModifiable() {
    assertThatThrownBy(() -> geodeRegExMatchingMethodAuthorizer.getAllowedPatterns().add(".*"))
        .isInstanceOf(UnsupportedOperationException.class);
  }

  @Test
  public void authorizeShouldReturnFalseForKnownDangerousMethods() throws Exception {
    TestBean testBean = new TestBean();
    List<Method> dangerousMethods = new ArrayList<>();
    dangerousMethods.add(TestBean.class.getMethod("getClass"));
    dangerousMethods.add(TestBean.class.getMethod("readResolve"));
    dangerousMethods.add(TestBean.class.getMethod("readObjectNoData"));
    dangerousMethods.add(TestBean.class.getMethod("readObject", ObjectInputStream.class));
    dangerousMethods.add(TestBean.class.getMethod("writeReplace"));
    dangerousMethods.add(TestBean.class.getMethod("writeObject", ObjectOutputStream.class));

    dangerousMethods.forEach(method -> assertThat(
        geodeRegExMatchingMethodAuthorizer.authorize(method, testBean)).isFalse());
  }

  @Test
  public void authorizeShouldReturnFalseForGeodeMethodsThatAreNotConsideredSafeEvenIfTheyMatchTheUserRegEx()
      throws Exception {
    Set<Pair<Method, Object>> methods = new HashSet<>();
    methods.add(new Pair<>(TestBean.class.getMethod("accessor"), new TestBean()));
    methods.add(new Pair<>(TestBean.class.getMethod("mutator"), new TestBean()));
    methods.add(new Pair<>(BucketDump.class.getMethod("getValues"), mock(BucketDump.class)));
    methods.add(new Pair<>(RegionConfig.class.getMethod("getEntries"), mock(RegionConfig.class)));
    methods.add(new Pair<>(EntryEvent.class.getMethod("getKey"), mock(EntryEvent.class)));
    methods.add(new Pair<>(Valuable.class.getMethod("getValue"), mock(Valuable.class)));
    methods.add(new Pair<>(HAContainerMap.class.getMethod("containsKey", Object.class),
        mock(HAContainerMap.class)));
    methods.add(new Pair<>(HAContainerMap.class.getMethod("entrySet"), mock(HAContainerMap.class)));
    methods.add(new Pair<>(HAContainerMap.class.getMethod("get", Object.class),
        mock(HAContainerMap.class)));
    methods.add(new Pair<>(HAContainerMap.class.getMethod("keySet"), mock(HAContainerMap.class)));
    methods.add(new Pair<>(HAContainerMap.class.getMethod("values"), mock(HAContainerMap.class)));

    methods.forEach(
        pair -> assertThat(geodeRegExMatchingMethodAuthorizer.authorize(pair.getX(), pair.getY()))
            .as("For method: " + pair.getX().getName()).isFalse());
  }

  @Test
  public void authorizeShouldReturnFalseWheneverTheSecurityServiceDoesNotAllowOperationsOnTheRegion()
      throws Exception {
    Region region = mock(Region.class);
    Region localRegion = mock(LocalRegion.class);
    Region partitionedRegion = mock(PartitionedRegion.class);
    when(region.getName()).thenReturn("testRegion");
    when(localRegion.getName()).thenReturn("testRegion");
    when(partitionedRegion.getName()).thenReturn("testRegion");
    doThrow(new NotAuthorizedException("Mock Exception")).when(mockSecurityService).authorize(
        ResourcePermission.Resource.DATA, ResourcePermission.Operation.READ, "testRegion");

    List<Method> methods = new ArrayList<>();
    methods.add(Map.class.getMethod("containsKey", Object.class));
    methods.add(Map.class.getMethod("entrySet"));
    methods.add(Map.class.getMethod("get", Object.class));
    methods.add(Map.class.getMethod("keySet"));
    methods.add(Map.class.getMethod("values"));

    methods.forEach(method -> {
      assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, region)).isFalse();
      assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, localRegion)).isFalse();
      assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, partitionedRegion)).isFalse();
    });
  }

  @Test
  public void authorizeShouldReturnTrueForMapMethodsOnRegionInstancesWheneverTheSecurityServiceAllowsOperationsOnTheRegion()
      throws Exception {
    Region region = mock(Region.class);
    Region localRegion = mock(LocalRegion.class);
    Region partitionedRegion = mock(PartitionedRegion.class);

    List<Method> methods = new ArrayList<>();
    methods.add(Map.class.getMethod("containsKey", Object.class));
    methods.add(Map.class.getMethod("entrySet"));
    methods.add(Map.class.getMethod("get", Object.class));
    methods.add(Map.class.getMethod("keySet"));
    methods.add(Map.class.getMethod("values"));

    methods.forEach(method -> {
      assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, region)).isTrue();
      assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, localRegion)).isTrue();
      assertThat(geodeRegExMatchingMethodAuthorizer.authorize(method, partitionedRegion)).isTrue();
    });
  }

  @Test
  public void authorizeShouldReturnTrueForNonMatchingMethodsConsideredSafeByDefault()
      throws Exception {
    Set<Pair<Method, Object>> someSafeMethods = new HashSet<>();
    someSafeMethods.add(new Pair<>(Object.class.getMethod("toString"), new Object()));
    someSafeMethods.add(new Pair<>(Object.class.getMethod("equals", Object.class), new Object()));
    someSafeMethods.add(
        new Pair<>(Comparable.class.getMethod("compareTo", Object.class), mock(Comparable.class)));
    someSafeMethods.add(new Pair<>(Number.class.getMethod("byteValue"), new Integer("0")));
    someSafeMethods.add(new Pair<>(Date.class.getMethod("after", Date.class), new Date()));
    someSafeMethods.add(new Pair<>(String.class.getMethod("indexOf", int.class), ""));
    someSafeMethods.add(new Pair<>(Map.Entry.class.getMethod("getKey"), mock(Map.Entry.class)));
    someSafeMethods
        .add(new Pair<>(Map.class.getMethod("get", Object.class), Collections.emptyMap()));
    RegExMethodAuthorizer authorizer = new RegExMethodAuthorizer(
        new RestrictedMethodAuthorizer(mockCache), Collections.emptySet());

    someSafeMethods.forEach(pair -> assertThat(authorizer.authorize(pair.getX(), pair.getY()))
        .as("For method: " + pair.getX().getName()).isTrue());
  }

  @Test
  public void authorizeShouldReturnFalseForNonMatchingMethodsThatAreNotConsideredSafeByDefault()
      throws Exception {
    Set<Pair<Method, Object>> someNonSafeMethods = new HashSet<>();
    someNonSafeMethods.add(new Pair<>(Object.class.getMethod("wait"), new Object()));
    someNonSafeMethods.add(new Pair<>(Number.class.getMethod("notify"), new Integer("0")));
    someNonSafeMethods.add(new Pair<>(Date.class.getMethod("setYear", int.class), new Date()));
    someNonSafeMethods.add(new Pair<>(Set.class.getMethod("add", Object.class), new HashSet<>()));
    someNonSafeMethods.add(
        new Pair<>(Map.Entry.class.getMethod("setValue", Object.class), mock(Map.Entry.class)));
    someNonSafeMethods.add(
        new Pair<>(Map.class.getMethod("put", Object.class, Object.class), Collections.emptyMap()));
    RegExMethodAuthorizer authorizer = new RegExMethodAuthorizer(
        new RestrictedMethodAuthorizer(mockCache), Collections.emptySet());

    someNonSafeMethods.forEach(pair -> assertThat(authorizer.authorize(pair.getX(), pair.getY()))
        .as("For method: " + pair.getX().getName()).isFalse());
  }

  @Test
  public void authorizeShouldReturnTrueForMatchingMethods() throws Exception {
    RestrictedMethodAuthorizer defaultAuthorizer = new RestrictedMethodAuthorizer(mockCache);
    Set<String> regularExpressions =
        new HashSet<>(Arrays.asList("^java\\.lang\\..*\\.(?:wait|notify)",
            "^java\\.util\\..*\\.(?:set|put|add).*", ".*MockitoMock.*"));
    RegExMethodAuthorizer customAuthorizer =
        new RegExMethodAuthorizer(defaultAuthorizer, regularExpressions);

    Set<Pair<Method, Object>> someNonSafeMethods = new HashSet<>();
    someNonSafeMethods.add(new Pair<>(Object.class.getMethod("wait"), new Object()));
    someNonSafeMethods.add(new Pair<>(Number.class.getMethod("notify"), new Integer("0")));
    someNonSafeMethods.add(new Pair<>(Date.class.getMethod("setYear", int.class), new Date()));
    someNonSafeMethods.add(new Pair<>(Set.class.getMethod("add", Object.class), new HashSet<>()));
    someNonSafeMethods.add(
        new Pair<>(Map.Entry.class.getMethod("setValue", Object.class), mock(Map.Entry.class)));
    someNonSafeMethods
        .add(new Pair<>(Map.class.getMethod("put", Object.class, Object.class), new HashMap<>()));

    someNonSafeMethods
        .forEach(pair -> assertThat(customAuthorizer.authorize(pair.getX(), pair.getY()))
            .as("For method: " + pair.getX().getName()).isTrue());
  }

  @SuppressWarnings("unused")
  private static class TestBean implements Serializable {
    public Object writeReplace() throws ObjectStreamException {
      return new TestBean();
    }

    public void writeObject(ObjectOutputStream stream) throws IOException {
      throw new IOException();
    }

    public Object readResolve() throws ObjectStreamException {
      return new TestBean();
    }

    public void readObjectNoData() throws ObjectStreamException {}

    public void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
      if (new Random().nextBoolean()) {
        throw new IOException();
      } else {
        throw new ClassNotFoundException();
      }
    }

    public void mutator() {}

    public void accessor() {}
  }
}
