// Copyright (C) 2020 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.rest.project;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowCapability;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.capabilityKey;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.testsuite.change.ChangeOperations;
import com.google.gerrit.acceptance.testsuite.group.GroupOperations;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.DraftInput;
import com.google.gerrit.extensions.api.projects.BranchInfo;
import com.google.gerrit.extensions.api.projects.TagInfo;
import com.google.gerrit.extensions.api.projects.TagInput;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.notedb.Sequences;
import com.google.gerrit.testing.ConfigSuite;
import com.google.inject.Inject;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.junit.Test;

public class GetBranchIT extends AbstractDaemonTest {
  @Inject private ChangeOperations changeOperations;
  @Inject private GroupOperations groupOperations;
  @Inject private ProjectOperations projectOperations;
  @Inject private RequestScopeOperations requestScopeOperations;

  @ConfigSuite.Config
  public static Config skipFalse() {
    Config config = new Config();
    config.setBoolean("auth", null, "skipFullRefEvaluationIfAllRefsAreVisible", false);
    return config;
  }

  @Test
  public void cannotGetNonExistingBranch() {
    assertBranchNotFound(project, RefNames.fullName("non-existing"));
  }

  @Test
  public void getBranch() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    assertBranchFound(project, RefNames.fullName("master"));
  }

  @Test
  public void getBranchByShortName() throws Exception {
    requestScopeOperations.setApiUser(user.id());
    assertBranchFound(project, "master");
  }

  @Test
  public void cannotGetNonVisibleBranch() {
    String branchName = "master";

    // block read access to the branch
    projectOperations
        .project(project)
        .forUpdate()
        .add(block(Permission.READ).ref(RefNames.fullName(branchName)).group(ANONYMOUS_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());
    assertBranchNotFound(project, RefNames.fullName(branchName));
  }

  @Test
  public void cannotGetNonVisibleBranchByShortName() {
    String branchName = "master";

    // block read access to the branch
    projectOperations
        .project(project)
        .forUpdate()
        .add(block(Permission.READ).ref(RefNames.fullName(branchName)).group(ANONYMOUS_USERS))
        .update();

    requestScopeOperations.setApiUser(user.id());
    assertBranchNotFound(project, branchName);
  }

  @Test
  public void getChangeRef() throws Exception {
    // create a change
    Change.Id changeId = changeOperations.newChange().project(project).create();

    // a user without the 'Access Database' capability can see the change ref
    requestScopeOperations.setApiUser(user.id());
    String changeRef = RefNames.patchSetRef(PatchSet.id(changeId, 1));
    assertBranchFound(project, changeRef);
  }

  @Test
  public void getChangeRefOfNonVisibleChange() throws Exception {
    // create a change
    String branchName = "master";
    Change.Id changeId = changeOperations.newChange().project(project).branch(branchName).create();

    // block read access to the branch
    projectOperations
        .project(project)
        .forUpdate()
        .add(block(Permission.READ).ref(RefNames.fullName(branchName)).group(ANONYMOUS_USERS))
        .update();

    // a user without the 'Access Database' capability cannot see the change ref
    requestScopeOperations.setApiUser(user.id());
    String changeRef = RefNames.patchSetRef(PatchSet.id(changeId, 1));
    assertBranchNotFound(project, changeRef);

    // a user with the 'Access Database' capability can see the change ref
    testGetRefWithAccessDatabase(project, changeRef);
  }

  @Test
  public void getChangeEditRef() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create a change
    Change.Id changeId = changeOperations.newChange().project(project).create();

    // create a change edit by 'user'
    requestScopeOperations.setApiUser(user.id());
    gApi.changes().id(changeId.get()).edit().create();

    // every user can see their own change edit refs
    String changeEditRef = RefNames.refsEdit(user.id(), changeId, PatchSet.id(changeId, 1));
    assertBranchFound(project, changeEditRef);

    // a user without the 'Access Database' capability cannot see the change edit ref of another
    // user
    requestScopeOperations.setApiUser(user2.id());
    assertBranchNotFound(project, changeEditRef);

    // a user with the 'Access Database' capability can see the change edit ref of another user
    testGetRefWithAccessDatabase(project, changeEditRef);
  }

  @Test
  public void cannotGetChangeEditRefOfNonVisibleChange() throws Exception {
    // create a change
    String branchName = "master";
    Change.Id changeId = changeOperations.newChange().project(project).branch(branchName).create();

    // create a change edit by 'user'
    requestScopeOperations.setApiUser(user.id());
    gApi.changes().id(changeId.get()).edit().create();

    // make the change non-visible by blocking read access on the destination
    projectOperations
        .project(project)
        .forUpdate()
        .add(block(Permission.READ).ref(RefNames.fullName(branchName)).group(ANONYMOUS_USERS))
        .update();

    // user cannot see their own change edit refs if the change is no longer visible
    String changeEditRef = RefNames.refsEdit(user.id(), changeId, PatchSet.id(changeId, 1));
    assertBranchNotFound(project, changeEditRef);

    // a user with the 'Access Database' capability can see the change edit ref
    testGetRefWithAccessDatabase(project, changeEditRef);
  }

  @Test
  public void getChangeMetaRef() throws Exception {
    // create a change
    Change.Id changeId = changeOperations.newChange().project(project).create();

    // A user without the 'Access Database' capability can see the change meta ref.
    // This may be surprising, as 'Access Database' guards access to meta refs and the change meta
    // ref is a meta ref, however change meta refs have been always visible to all users that can
    // see the change and some tools rely on seeing these refs, so we have to keep the current
    // behaviour.
    requestScopeOperations.setApiUser(user.id());
    String changeMetaRef = RefNames.changeMetaRef(changeId);
    assertBranchFound(project, changeMetaRef);
  }

  @Test
  public void getRefsMetaConfig() throws Exception {
    // a non-project owner cannot get the refs/meta/config branch
    requestScopeOperations.setApiUser(user.id());
    assertBranchNotFound(project, RefNames.REFS_CONFIG);

    // a non-project owner cannot get the refs/meta/config branch even with the 'Access Database'
    // capability
    projectOperations
        .project(allProjects)
        .forUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    try {
      assertBranchNotFound(project, RefNames.REFS_CONFIG);
    } finally {
      projectOperations
          .allProjectsForUpdate()
          .remove(
              capabilityKey(GlobalCapability.ACCESS_DATABASE)
                  .group(SystemGroupBackend.REGISTERED_USERS))
          .update();
    }

    requestScopeOperations.setApiUser(user.id());

    // a project owner can get the refs/meta/config branch
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.OWNER).ref("refs/*").group(REGISTERED_USERS))
        .update();
    assertBranchFound(project, RefNames.REFS_CONFIG);
  }

  @Test
  public void getUserRefOfOtherUser() throws Exception {
    String userRef = RefNames.refsUsers(admin.id());

    // a user without the 'Access Database' capability cannot see the user ref of another user
    requestScopeOperations.setApiUser(user.id());
    assertBranchNotFound(allUsers, userRef);

    // a user with the 'Access Database' capability can see the user ref of another user
    testGetRefWithAccessDatabase(allUsers, userRef);
  }

  @Test
  public void getOwnUserRef() throws Exception {
    // every user can see the own user ref
    requestScopeOperations.setApiUser(user.id());
    assertBranchFound(allUsers, RefNames.refsUsers(user.id()));

    // TODO: every user can see the own user ref via the magic ref/users/self ref
    // requestScopeOperations.setApiUser(user.id());
    // assertBranchFound(allUsers, RefNames.REFS_USERS_SELF);
  }

  @Test
  public void getExternalIdsRefs() throws Exception {
    // a user without the 'Access Database' capability cannot see the refs/meta/external-ids ref
    requestScopeOperations.setApiUser(user.id());
    assertBranchNotFound(allUsers, RefNames.REFS_EXTERNAL_IDS);

    // a user with the 'Access Database' capability can see the refs/meta/external-ids ref
    testGetRefWithAccessDatabase(allUsers, RefNames.REFS_EXTERNAL_IDS);
  }

  @Test
  public void getGroupRef() throws Exception {
    // create a group
    AccountGroup.UUID ownerGroupUuid =
        groupOperations.newGroup().name("owner-group").addMember(admin.id()).create();
    AccountGroup.UUID testGroupUuid =
        groupOperations.newGroup().name("test-group").ownerGroupUuid(ownerGroupUuid).create();

    // a non-group owner without the 'Access Database' capability cannot see the group ref
    requestScopeOperations.setApiUser(user.id());
    String groupRef = RefNames.refsGroups(testGroupUuid);
    assertBranchNotFound(allUsers, groupRef);

    // a non-group owner with the 'Access Database' capability can see the group ref
    testGetRefWithAccessDatabase(allUsers, groupRef);

    // a group owner can see the group ref if the group ref is visible
    groupOperations.group(ownerGroupUuid).forUpdate().addMember(user.id()).update();
    assertBranchFound(allUsers, groupRef);

    // A group owner cannot see the group ref if the group ref is not visible.
    // The READ access for refs/groups/* must be blocked on All-Projects rather than All-Users.
    // This is because READ access for refs/groups/* on All-Users is by default granted to
    // REGISTERED_USERS, and if an ALLOW rule and a BLOCK rule are on the same project and ref,
    // the ALLOW rule takes precedence.
    projectOperations
        .project(allProjects)
        .forUpdate()
        .add(block(Permission.READ).ref("refs/groups/*").group(ANONYMOUS_USERS))
        .update();
    assertBranchNotFound(allUsers, groupRef);
  }

  @Test
  public void getGroupNamesRef() throws Exception {
    // a user without the 'Access Database' capability cannot see the refs/meta/group-names ref
    requestScopeOperations.setApiUser(user.id());
    assertBranchNotFound(allUsers, RefNames.REFS_GROUPNAMES);

    // a user with the 'Access Database' capability can see the refs/meta/group-names ref
    testGetRefWithAccessDatabase(allUsers, RefNames.REFS_GROUPNAMES);
  }

  @Test
  public void getDeletedGroupRef() throws Exception {
    // Create a deleted group ref. We must create a directly in the repo, since group deletion is
    // not supported yet.
    String deletedGroupRef = RefNames.refsDeletedGroups(AccountGroup.uuid("deleted-group"));
    try (TestRepository<Repository> testRepo =
        new TestRepository<>(repoManager.openRepository(allUsers))) {
      testRepo
          .branch(deletedGroupRef)
          .commit()
          .message("Some Message")
          .add("group.config", "content")
          .create();
    }

    requestScopeOperations.setApiUser(user.id());
    assertBranchNotFound(allUsers, deletedGroupRef);

    // a user with the 'Access Database' capability can see the deleted group ref
    testGetRefWithAccessDatabase(allUsers, deletedGroupRef);
  }

  @Test
  public void getDraftCommentsRef() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create a change
    String fileName = "a.txt";
    Change change = createChange("A Change", fileName, "content").getChange().change();

    // create a draft comment by the by 'user'
    requestScopeOperations.setApiUser(user.id());
    DraftInput draftInput = new DraftInput();
    draftInput.path = fileName;
    draftInput.line = 0;
    draftInput.message = "Some Comment";
    gApi.changes().id(change.getChangeId()).current().createDraft(draftInput);

    // every user can see their own draft comments refs
    // TODO: is this a bug?
    String draftCommentsRef = RefNames.refsDraftComments(change.getId(), user.id());
    assertBranchFound(allUsers, draftCommentsRef);

    // a user without the 'Access Database' capability cannot see the draft comments ref of another
    // user
    requestScopeOperations.setApiUser(user2.id());
    assertBranchNotFound(allUsers, draftCommentsRef);

    // a user with the 'Access Database' capability can see the draft comments ref of another user
    testGetRefWithAccessDatabase(allUsers, draftCommentsRef);
  }

  @Test
  public void getStarredChangesRef() throws Exception {
    TestAccount user2 = accountCreator.user2();

    // create a change
    Change change = createChange().getChange().change();

    // let user star the change
    requestScopeOperations.setApiUser(user.id());
    gApi.accounts().self().starChange(Integer.toString(change.getChangeId()));

    // every user can see their own starred changes refs
    // TODO: is this a bug?
    String starredChangesRef = RefNames.refsStarredChanges(change.getId(), user.id());
    assertBranchFound(allUsers, starredChangesRef);

    // a user without the 'Access Database' capability cannot see the starred changes ref of another
    // user
    requestScopeOperations.setApiUser(user2.id());
    assertBranchNotFound(allUsers, starredChangesRef);

    // a user with the 'Access Database' capability can see the starred changes ref of another user
    testGetRefWithAccessDatabase(allUsers, starredChangesRef);
  }

  @Test
  public void getTagRef() throws Exception {
    // create a tag
    TagInput input = new TagInput();
    input.message = "My Tag";
    input.revision = projectOperations.project(project).getHead("master").name();
    TagInfo tagInfo = gApi.projects().name(project.get()).tag("my-tag").create(input).get();

    // any user who can see the project, can see the tag
    requestScopeOperations.setApiUser(user.id());
    assertBranchFound(project, tagInfo.ref);
  }

  @Test
  public void cannotGetTagRefThatPointsToNonVisibleBranch() throws Exception {
    // create a tag
    TagInput input = new TagInput();
    input.message = "My Tag";
    input.revision = projectOperations.project(project).getHead("master").name();
    TagInfo tagInfo = gApi.projects().name(project.get()).tag("my-tag").create(input).get();

    // block read access to the branch
    projectOperations
        .project(project)
        .forUpdate()
        .add(block(Permission.READ).ref(RefNames.fullName("master")).group(ANONYMOUS_USERS))
        .update();

    // if the user cannot see the project, the tag is not visible
    requestScopeOperations.setApiUser(user.id());
    assertBranchNotFound(project, tagInfo.ref);
  }

  @Test
  public void getSymbolicRef() throws Exception {
    // 'HEAD' is visible since it points to 'master' that is visible
    requestScopeOperations.setApiUser(user.id());
    assertBranchFound(project, "HEAD");
  }

  @Test
  public void cannotGetSymbolicRefThatPointsToNonVisibleBranch() {
    // block read access to the branch to which HEAD points by default
    projectOperations
        .project(project)
        .forUpdate()
        .add(block(Permission.READ).ref(RefNames.fullName("master")).group(ANONYMOUS_USERS))
        .update();

    // since 'master' is not visible, 'HEAD' which points to 'master' is also not visible
    requestScopeOperations.setApiUser(user.id());
    assertBranchNotFound(project, "HEAD");
  }

  @Test
  public void getAccountSequenceRef() throws Exception {
    // a user without the 'Access Database' capability cannot see the refs/sequences/accounts ref
    requestScopeOperations.setApiUser(user.id());
    String accountSequenceRef = RefNames.REFS_SEQUENCES + Sequences.NAME_ACCOUNTS;
    assertBranchNotFound(allUsers, accountSequenceRef);

    // a user with the 'Access Database' capability can see the refs/sequences/accounts ref
    testGetRefWithAccessDatabase(allUsers, accountSequenceRef);
  }

  @Test
  public void getChangeSequenceRef() throws Exception {
    // a user without the 'Access Database' capability cannot see the refs/sequences/changes ref
    requestScopeOperations.setApiUser(user.id());
    String changeSequenceRef = RefNames.REFS_SEQUENCES + Sequences.NAME_CHANGES;
    assertBranchNotFound(allProjects, changeSequenceRef);

    // a user with the 'Access Database' capability can see the refs/sequences/changes ref
    testGetRefWithAccessDatabase(allProjects, changeSequenceRef);
  }

  @Test
  public void getGroupSequenceRef() throws Exception {
    // a user without the 'Access Database' capability cannot see the refs/sequences/groups ref
    requestScopeOperations.setApiUser(user.id());
    String groupSequenceRef = RefNames.REFS_SEQUENCES + Sequences.NAME_GROUPS;
    assertBranchNotFound(allUsers, groupSequenceRef);

    // a user with the 'Access Database' capability can see the refs/sequences/groups ref
    testGetRefWithAccessDatabase(allUsers, groupSequenceRef);
  }

  @Test
  public void getVersionMetaRef() throws Exception {
    // TODO: a user without the 'Access Database' capability cannot see the refs/meta/version ref
    // requestScopeOperations.setApiUser(user.id());
    // assertBranchNotFound(allProjects, RefNames.REFS_VERSION);

    // a user with the 'Access Database' capability can see the refs/meta/vaersion ref
    testGetRefWithAccessDatabase(allProjects, RefNames.REFS_VERSION);
  }

  @Test
  public void cannotGetAutoMergeRef() throws Exception {
    String file = "foo/a.txt";

    // Create a base change.
    Change.Id baseChange =
        changeOperations
            .newChange()
            .project(project)
            .branch("master")
            .file(file)
            .content("base content")
            .create();
    approve(Integer.toString(baseChange.get()));
    gApi.changes().id(baseChange.get()).current().submit();

    // Create another branch
    String branchName = "foo";
    createBranchWithRevision(
        BranchNameKey.create(project, branchName),
        projectOperations.project(project).getHead("master").name());

    // Create a change in master that touches the file.
    Change.Id changeInMaster =
        changeOperations
            .newChange()
            .project(project)
            .branch("master")
            .file(file)
            .content("master content")
            .create();
    approve(Integer.toString(changeInMaster.get()));
    gApi.changes().id(changeInMaster.get()).current().submit();

    // Create a change in the other branch and that touches the file.
    Change.Id changeInOtherBranch =
        changeOperations
            .newChange()
            .project(project)
            .branch(branchName)
            .file(file)
            .content("other content")
            .create();
    approve(Integer.toString(changeInOtherBranch.get()));
    gApi.changes().id(changeInOtherBranch.get()).current().submit();

    // Create a merge change with a conflict resolution for the file.
    Change.Id mergeChange =
        changeOperations
            .newChange()
            .project(project)
            .branch("master")
            .mergeOfButBaseOnFirst()
            .tipOfBranch("master")
            .and()
            .tipOfBranch(branchName)
            .file(file)
            .content("merged content")
            .create();

    String mergeRevision =
        changeOperations.change(mergeChange).currentPatchset().get().commitId().name();
    assertBranchNotFound(project, RefNames.refsCacheAutomerge(mergeRevision));
  }

  private void testGetRefWithAccessDatabase(Project.NameKey project, String ref)
      throws RestApiException {
    projectOperations
        .project(allProjects)
        .forUpdate()
        .add(allowCapability(GlobalCapability.ACCESS_DATABASE).group(REGISTERED_USERS))
        .update();
    try {
      requestScopeOperations.setApiUser(user.id());
      assertBranchFound(project, ref);
    } finally {
      projectOperations
          .allProjectsForUpdate()
          .remove(
              capabilityKey(GlobalCapability.ACCESS_DATABASE)
                  .group(SystemGroupBackend.REGISTERED_USERS))
          .update();
    }
  }

  private void assertBranchNotFound(Project.NameKey project, String ref) {
    ResourceNotFoundException exception =
        assertThrows(
            ResourceNotFoundException.class,
            () -> gApi.projects().name(project.get()).branch(ref).get());
    assertThat(exception).hasMessageThat().isEqualTo("Not found: " + ref);
  }

  private void assertBranchFound(Project.NameKey project, String ref) throws RestApiException {
    BranchInfo branchInfo = gApi.projects().name(project.get()).branch(ref).get();
    assertThat(branchInfo.ref).isEqualTo(RefNames.fullName(ref));
  }
}
