// Copyright (C) 2017 The Android Open Source Project
//
// 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 com.google.gerrit.acceptance.api.project;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.deny;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.permissionKey;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.entities.AccessSection;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.config.AccessCheckInfo;
import com.google.gerrit.extensions.api.config.AccessCheckInput;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.inject.Inject;
import java.util.List;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Test;

public class CheckAccessIT extends AbstractDaemonTest {
  @Inject private ProjectOperations projectOperations;
  @Inject private GroupOperations groupOperations;
  @Inject private AllProjectsName allProjectsName;

  private Project.NameKey normalProject;
  private Project.NameKey secretProject;
  private Project.NameKey secretRefProject;
  private TestAccount privilegedUser;

  @Before
  public void setUp() throws Exception {
    normalProject = projectOperations.newProject().create();
    secretProject = projectOperations.newProject().create();
    secretRefProject = projectOperations.newProject().create();
    AccountGroup.UUID privilegedGroupUuid =
        groupOperations.newGroup().name(name("privilegedGroup")).create();

    privilegedUser = accountCreator.create("privilegedUser", "snowden@nsa.gov", "Ed Snowden", null);
    groupOperations.group(privilegedGroupUuid).forUpdate().addMember(privilegedUser.id()).update();

    projectOperations
        .project(secretProject)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/*").group(privilegedGroupUuid))
        .add(block(Permission.READ).ref("refs/*").group(SystemGroupBackend.REGISTERED_USERS))
        .update();

    projectOperations
        .project(secretRefProject)
        .forUpdate()
        .add(deny(Permission.READ).ref("refs/*").group(SystemGroupBackend.ANONYMOUS_USERS))
        .add(allow(Permission.READ).ref("refs/heads/secret/*").group(privilegedGroupUuid))
        .add(
            block(Permission.READ)
                .ref("refs/heads/secret/*")
                .group(SystemGroupBackend.REGISTERED_USERS))
        .add(allow(Permission.READ).ref("refs/heads/*").group(SystemGroupBackend.REGISTERED_USERS))
        .update();

    // Ref permission
    projectOperations
        .project(normalProject)
        .forUpdate()
        .add(allow(Permission.VIEW_PRIVATE_CHANGES).ref("refs/*").group(privilegedGroupUuid))
        .add(allow(Permission.FORGE_SERVER).ref("refs/*").group(privilegedGroupUuid))
        .update();
  }

  @Test
  public void emptyInput() throws Exception {
    BadRequestException thrown =
        assertThrows(
            BadRequestException.class,
            () -> gApi.projects().name(normalProject.get()).checkAccess(new AccessCheckInput()));
    assertThat(thrown).hasMessageThat().contains("input requires 'account'");
  }

  @Test
  public void nonexistentPermission() throws Exception {
    AccessCheckInput in = new AccessCheckInput();
    in.account = user.email();
    in.permission = "notapermission";
    in.ref = "refs/heads/master";

    BadRequestException thrown =
        assertThrows(
            BadRequestException.class,
            () -> gApi.projects().name(normalProject.get()).checkAccess(in));
    assertThat(thrown).hasMessageThat().contains("not recognized");
  }

  @Test
  public void permissionLacksRef() throws Exception {
    AccessCheckInput in = new AccessCheckInput();
    in.account = user.email();
    in.permission = "forge_author";

    BadRequestException thrown =
        assertThrows(
            BadRequestException.class,
            () -> gApi.projects().name(normalProject.get()).checkAccess(in));
    assertThat(thrown).hasMessageThat().contains("must set 'ref'");
  }

  @Test
  public void changePermission() throws Exception {
    AccessCheckInput in = new AccessCheckInput();
    in.account = user.email();
    in.permission = "rebase";
    in.ref = "refs/heads/master";

    BadRequestException thrown =
        assertThrows(
            BadRequestException.class,
            () -> gApi.projects().name(normalProject.get()).checkAccess(in));
    assertThat(thrown).hasMessageThat().contains("recognized as ref permission");
  }

  @Test
  public void nonexistentEmail() throws Exception {
    AccessCheckInput in = new AccessCheckInput();
    in.account = "doesnotexist@invalid.com";
    in.permission = "rebase";
    in.ref = "refs/heads/master";

    UnprocessableEntityException thrown =
        assertThrows(
            UnprocessableEntityException.class,
            () -> gApi.projects().name(normalProject.get()).checkAccess(in));
    assertThat(thrown).hasMessageThat().contains("Account 'doesnotexist@invalid.com' not found");
  }

  private static class TestCase {
    AccessCheckInput input;
    String project;
    String permission;
    int want;
    List<String> expectedDebugLogs;

    static TestCase project(String mail, String project, int want, List<String> expectedDebugLogs) {
      TestCase t = new TestCase();
      t.input = new AccessCheckInput();
      t.input.account = mail;
      t.project = project;
      t.want = want;
      t.expectedDebugLogs = expectedDebugLogs;
      return t;
    }

    static TestCase projectRef(
        String mail, String project, String ref, int want, List<String> expectedDebugLogs) {
      TestCase t = new TestCase();
      t.input = new AccessCheckInput();
      t.input.account = mail;
      t.input.ref = ref;
      t.project = project;
      t.want = want;
      t.expectedDebugLogs = expectedDebugLogs;
      return t;
    }

    static TestCase projectRefPerm(
        String mail,
        String project,
        String ref,
        String permission,
        int want,
        List<String> expectedDebugLogs) {
      TestCase t = new TestCase();
      t.input = new AccessCheckInput();
      t.input.account = mail;
      t.input.ref = ref;
      t.input.permission = permission;
      t.project = project;
      t.want = want;
      t.expectedDebugLogs = expectedDebugLogs;
      return t;
    }
  }

  @Test
  public void httpGet() throws Exception {
    RestResponse rep =
        adminRestSession.get(
            "/projects/"
                + normalProject.get()
                + "/check.access"
                + "?ref=refs/heads/master&perm=viewPrivateChanges&account="
                + user.email());
    rep.assertOK();
    assertThat(rep.getEntityContent()).contains("403");
  }

  @Test
  public void accessible() throws Exception {
    List<TestCase> inputs =
        ImmutableList.of(
            // Test 1
            TestCase.projectRefPerm(
                user.email(),
                normalProject.get(),
                "refs/heads/master",
                Permission.VIEW_PRIVATE_CHANGES,
                403,
                ImmutableList.of(
                    "'user' can perform 'read' with force=false on project '"
                        + normalProject.get()
                        + "' for ref 'refs/heads/*'",
                    "'user' cannot perform 'viewPrivateChanges' with force=false on project '"
                        + normalProject.get()
                        + "' for ref 'refs/heads/master'")),
            // Test 2
            TestCase.project(
                user.email(),
                normalProject.get(),
                200,
                ImmutableList.of(
                    "'user' can perform 'read' with force=false on project '"
                        + normalProject.get()
                        + "' for ref 'refs/heads/*'")),
            // Test 3
            TestCase.project(
                user.email(),
                secretProject.get(),
                403,
                ImmutableList.of(
                    "'user' cannot perform 'read' with force=false on project '"
                        + secretProject.get()
                        + "' for ref 'refs/heads/*' because this permission is blocked",
                    "'user' cannot perform 'read' with force=false on project '"
                        + secretProject.get()
                        + "' for ref 'refs/meta/version' because this permission is blocked")),
            // Test 4
            TestCase.projectRef(
                user.email(),
                secretRefProject.get(),
                "refs/heads/secret/master",
                403,
                ImmutableList.of(
                    "'user' can perform 'read' with force=false on project '"
                        + secretRefProject.get()
                        + "' for ref 'refs/heads/*'",
                    "'user' cannot perform 'read' with force=false on project '"
                        + secretRefProject.get()
                        + "' for ref 'refs/heads/secret/master' because this permission is blocked")),
            // Test 5
            TestCase.projectRef(
                privilegedUser.email(),
                secretRefProject.get(),
                "refs/heads/secret/master",
                200,
                ImmutableList.of(
                    "'privilegedUser' can perform 'read' with force=false on project '"
                        + secretRefProject.get()
                        + "' for ref 'refs/heads/*'",
                    "'privilegedUser' can perform 'read' with force=false on project '"
                        + secretRefProject.get()
                        + "' for ref 'refs/heads/secret/master'")),
            // Test 6
            TestCase.projectRef(
                privilegedUser.email(),
                normalProject.get(),
                null,
                200,
                ImmutableList.of(
                    "'privilegedUser' can perform 'read' with force=false on project '"
                        + normalProject.get()
                        + "' for ref 'refs/heads/*'")),
            // Test 7
            TestCase.projectRef(
                privilegedUser.email(),
                secretProject.get(),
                null,
                200,
                ImmutableList.of(
                    "'privilegedUser' can perform 'read' with force=false on project '"
                        + secretProject.get()
                        + "' for ref 'refs/*'")),
            // Test 8
            TestCase.projectRefPerm(
                privilegedUser.email(),
                normalProject.get(),
                "refs/heads/master",
                Permission.VIEW_PRIVATE_CHANGES,
                200,
                ImmutableList.of(
                    "'privilegedUser' can perform 'read' with force=false on project '"
                        + normalProject.get()
                        + "' for ref 'refs/heads/*'",
                    "'privilegedUser' can perform 'viewPrivateChanges' with force=false on project '"
                        + normalProject.get()
                        + "' for ref 'refs/heads/master'")),
            // Test 9
            TestCase.projectRefPerm(
                privilegedUser.email(),
                normalProject.get(),
                "refs/heads/master",
                Permission.FORGE_SERVER,
                200,
                ImmutableList.of(
                    "'privilegedUser' can perform 'read' with force=false on project '"
                        + normalProject.get()
                        + "' for ref 'refs/heads/*'",
                    "'privilegedUser' can perform 'forgeServerAsCommitter' with force=false on project '"
                        + normalProject.get()
                        + "' for ref 'refs/heads/master'")));

    for (TestCase tc : inputs) {
      String in = newGson().toJson(tc.input);
      AccessCheckInfo info = null;

      try {
        info = gApi.projects().name(tc.project).checkAccess(tc.input);
      } catch (RestApiException e) {
        assertWithMessage(String.format("check.access(%s, %s): exception %s", tc.project, in, e))
            .fail();
      }

      int want = tc.want;
      if (want != info.status) {
        assertWithMessage(
                String.format(
                    "check.access(%s, %s) = %d, want %d", tc.project, in, info.status, want))
            .fail();
      }

      switch (want) {
        case 403:
          if (tc.permission != null) {
            assertThat(info.message).contains("lacks permission " + tc.permission);
          }
          break;
        case 404:
          assertThat(info.message).contains("does not exist");
          break;
        case 200:
          assertThat(info.message).isNull();
          break;
        default:
          assertWithMessage(String.format("unknown code %d", want)).fail();
      }

      if (!info.debugLogs.equals(tc.expectedDebugLogs)) {
        assertWithMessage(
                String.format(
                    "check.access(%s, %s) = %s, want %s",
                    tc.project, in, info.debugLogs, tc.expectedDebugLogs))
            .fail();
      }
    }
  }

  @Test
  public void noBranches() throws Exception {
    try (Repository repo = repoManager.openRepository(normalProject)) {
      RefUpdate u = repo.updateRef(RefNames.REFS_HEADS + "master");
      u.setForceUpdate(true);
      assertThat(u.delete()).isEqualTo(Result.FORCED);
    }
    AccessCheckInput input = new AccessCheckInput();
    input.account = privilegedUser.email();

    AccessCheckInfo info = gApi.projects().name(normalProject.get()).checkAccess(input);
    assertThat(info.status).isEqualTo(200);
    assertThat(info.message).contains("no branches");
  }

  @Test
  @Sandboxed
  public void noRules() throws Exception {
    normalProject = projectOperations.newProject().create();

    for (AccessSection section :
        projectOperations.project(allProjectsName).getProjectConfig().getAccessSections()) {
      if (!section.getName().startsWith(Constants.R_REFS)) {
        continue;
      }
      for (Permission permission : section.getPermissions()) {
        projectOperations
            .project(allProjectsName)
            .forUpdate()
            .remove(permissionKey(permission.getName()).ref(section.getName()).build())
            .update();
      }
    }
    AccessCheckInput input = new AccessCheckInput();
    input.account = privilegedUser.email();
    input.permission = Permission.READ;
    input.ref = "refs/heads/main";

    AccessCheckInfo info = gApi.projects().name(normalProject.get()).checkAccess(input);
    assertThat(info.status).isEqualTo(403);

    assertThat(info.debugLogs).isNotEmpty();
    assertThat(info.debugLogs.get(0)).contains("Found no rules");
  }
}
