// 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.assert_;
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.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.TestAccount;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.common.data.Permission;
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.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.inject.Inject;
import java.util.List;
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;

  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");
    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;

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

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

    static TestCase projectRefPerm(
        String mail, String project, String ref, String permission, int want) {
      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;
      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(
            TestCase.projectRefPerm(
                user.email(),
                normalProject.get(),
                "refs/heads/master",
                Permission.VIEW_PRIVATE_CHANGES,
                403),
            TestCase.project(user.email(), normalProject.get(), 200),
            TestCase.project(user.email(), secretProject.get(), 403),
            TestCase.projectRef(
                user.email(), secretRefProject.get(), "refs/heads/secret/master", 403),
            TestCase.projectRef(
                privilegedUser.email(), secretRefProject.get(), "refs/heads/secret/master", 200),
            TestCase.projectRef(privilegedUser.email(), normalProject.get(), null, 200),
            TestCase.projectRef(privilegedUser.email(), secretProject.get(), null, 200),
            TestCase.projectRef(privilegedUser.email(), secretProject.get(), null, 200),
            TestCase.projectRefPerm(
                privilegedUser.email(),
                normalProject.get(),
                "refs/heads/master",
                Permission.VIEW_PRIVATE_CHANGES,
                200),
            TestCase.projectRefPerm(
                privilegedUser.email(),
                normalProject.get(),
                "refs/heads/master",
                Permission.FORGE_SERVER,
                200));

    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) {
        assert_().fail(String.format("check.access(%s, %s): exception %s", tc.project, in, e));
      }

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

      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:
          assert_().fail(String.format("unknown code %d", want));
      }
    }
  }

  @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");
  }
}
