// Copyright (C) 2018 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.git;

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.git.testing.PushResultSubject.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static java.util.stream.Collectors.toList;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.acceptance.AbstractDaemonTest;
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.AccessSection;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.inject.Inject;
import java.util.Arrays;
import java.util.function.Consumer;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.BlobBasedConfig;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
import org.eclipse.jgit.transport.TrackingRefUpdate;
import org.junit.Before;
import org.junit.Test;

public class PushPermissionsIT extends AbstractDaemonTest {
  @Inject private ProjectOperations projectOperations;
  @Inject private RequestScopeOperations requestScopeOperations;

  @Before
  public void setUp() throws Exception {
    try (ProjectConfigUpdate u = updateProject(allProjects)) {
      ProjectConfig cfg = u.getConfig();

      // Remove push-related permissions, so they can be added back individually by test methods.
      removeAllBranchPermissions(
          cfg,
          Permission.ADD_PATCH_SET,
          Permission.CREATE,
          Permission.DELETE,
          Permission.PUSH,
          Permission.PUSH_MERGE,
          Permission.SUBMIT);
      removeAllGlobalCapabilities(cfg, GlobalCapability.ADMINISTRATE_SERVER);
      u.save();
    }

    // Include some auxiliary permissions.
    projectOperations
        .allProjectsForUpdate()
        .add(allow(Permission.FORGE_AUTHOR).ref("refs/*").group(REGISTERED_USERS))
        .add(allow(Permission.FORGE_COMMITTER).ref("refs/*").group(REGISTERED_USERS))
        .update();
  }

  @Test
  public void mixingMagicAndRegularPush() throws Exception {
    testRepo.branch("HEAD").commit().create();
    PushResult r = push("HEAD:refs/heads/master", "HEAD:refs/for/master");

    String msg = "cannot combine normal pushes and magic pushes";
    assertThat(r.getRemoteUpdate("refs/heads/master").getStatus()).isNotEqualTo(Status.OK);
    assertThat(r.getRemoteUpdate("refs/for/master").getStatus()).isNotEqualTo(Status.OK);
    assertThat(r.getRemoteUpdate("refs/for/master").getMessage()).isEqualTo(msg);
  }

  @Test
  public void pushNewCommitsRequiresPushPermission() throws Exception {
    RevCommit commit = testRepo.branch("HEAD").commit().create();
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.CREATE).ref("refs/*").group(REGISTERED_USERS))
        .update();

    PushResult r = push("HEAD:refs/heads/newbranch");

    String msg =
        String.format(
            "prohibited by Gerrit: Unable to resolve object '%s'. Check that the object exists on"
                + " the server or get update permission to create new commit objects.",
            commit);
    RemoteRefUpdate rru = r.getRemoteUpdate("refs/heads/newbranch");
    assertThat(rru.getStatus()).isNotEqualTo(Status.OK);
    assertThat(rru.getMessage()).isEqualTo(msg);

    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.PUSH).ref("refs/*").group(REGISTERED_USERS))
        .update();
    RemoteRefUpdate success =
        push("HEAD:refs/heads/newbranch").getRemoteUpdate("refs/heads/newbranch");
    assertThat(success.getStatus()).isEqualTo(Status.OK);
  }

  @Test
  public void fastForwardUpdateDenied() throws Exception {
    testRepo.branch("HEAD").commit().create();
    PushResult r = push("HEAD:refs/heads/master");
    assertThat(r)
        .onlyRef("refs/heads/master")
        .isRejected("prohibited by Gerrit: not permitted: update");
    assertThat(r)
        .hasMessages(
            "error: branch refs/heads/master:",
            "Push to refs/for/master to create a review, or get 'Push' rights to update the"
                + " branch.",
            "User: admin",
            "Contact an administrator to fix the permissions");
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void nonFastForwardUpdateDenied() throws Exception {
    ObjectId commit = testRepo.commit().create();
    PushResult r = push("+" + commit.name() + ":refs/heads/master");
    assertThat(r)
        .onlyRef("refs/heads/master")
        .isRejected("prohibited by Gerrit: not permitted: force update");
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void deleteDenied() throws Exception {
    PushResult r = push(":refs/heads/master");
    assertThat(r)
        .onlyRef("refs/heads/master")
        .isRejected("prohibited by Gerrit: not permitted: delete");
    assertThat(r)
        .hasMessages(
            "error: branch refs/heads/master:",
            "You need 'Delete Reference' rights or 'Push' rights with the ",
            "'Force Push' flag set to delete references.",
            "User: admin",
            "Contact an administrator to fix the permissions");
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void createDenied() throws Exception {
    testRepo.branch("HEAD").commit().create();
    PushResult r = push("HEAD:refs/heads/newbranch");
    assertThat(r)
        .onlyRef("refs/heads/newbranch")
        .isRejected("prohibited by Gerrit: not permitted: create");
    assertThat(r).containsMessages("You need 'Create' rights to create new references.");
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void createDeniedIfUserCantRead() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(block(Permission.READ).ref("refs/*").group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref("refs/*").group(REGISTERED_USERS))
        .update();
    testRepo.branch("HEAD").commit().create();
    PushResult r = push("HEAD:refs/for/master");
    assertThat(r)
        .onlyRef("refs/for/master")
        .isRejected("prohibited by Gerrit: not permitted: read on refs/heads/master");
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void groupRefsByMessage() throws Exception {
    try (Repository repo = repoManager.openRepository(project);
        TestRepository<Repository> tr = new TestRepository<>(repo)) {
      tr.branch("foo").commit().create();
      tr.branch("bar").commit().create();
    }

    testRepo.branch("HEAD").commit().create();
    PushResult r = push(":refs/heads/foo", ":refs/heads/bar", "HEAD:refs/heads/master");
    assertThat(r).ref("refs/heads/foo").isRejected("prohibited by Gerrit: not permitted: delete");
    assertThat(r).ref("refs/heads/bar").isRejected("prohibited by Gerrit: not permitted: delete");
    assertThat(r)
        .ref("refs/heads/master")
        .isRejected("prohibited by Gerrit: not permitted: update");
    assertThat(r)
        .hasMessages(
            "error: branches refs/heads/foo, refs/heads/bar:",
            "You need 'Delete Reference' rights or 'Push' rights with the ",
            "'Force Push' flag set to delete references.",
            "error: branch refs/heads/master:",
            "Push to refs/for/master to create a review, or get 'Push' rights to update the"
                + " branch.",
            "User: admin",
            "Contact an administrator to fix the permissions");
  }

  @Test
  public void readOnlyProjectRejectedBeforeTestingPermissions() throws Exception {
    try (Repository repo = repoManager.openRepository(project)) {
      try (ProjectConfigUpdate u = updateProject(project)) {
        u.getConfig().updateProject(p -> p.setState(ProjectState.READ_ONLY));
        u.save();
      }
    }

    PushResult r = push(":refs/heads/master");
    assertThat(r)
        .onlyRef("refs/heads/master")
        .isRejected("prohibited by Gerrit: project state does not permit write");
    assertThat(r).hasNoMessages();
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void refsMetaConfigUpdateRequiresProjectOwner() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.PUSH).ref("refs/meta/config").group(REGISTERED_USERS))
        .update();

    forceFetch("refs/meta/config");
    ObjectId commit = testRepo.branch("refs/meta/config").commit().create();
    PushResult r = push(commit.name() + ":refs/meta/config");
    assertThat(r)
        .onlyRef("refs/meta/config")
        // ReceiveCommits theoretically has a different message when a WRITE_CONFIG check fails, but
        // it never gets there, since DefaultPermissionBackend special-cases refs/meta/config and
        // denies UPDATE if the user is not a project owner.
        .isRejected("prohibited by Gerrit: not permitted: update");
    assertThat(r)
        .hasMessages(
            "error: branch refs/meta/config:",
            "Configuration changes can only be pushed by project owners",
            "who also have 'Push' rights on refs/meta/config",
            "User: admin",
            "Contact an administrator to fix the permissions");
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));

    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.OWNER).ref("refs/*").group(REGISTERED_USERS))
        .update();

    // Re-fetch refs/meta/config from the server because the grant changed it, and we want a
    // fast-forward.
    forceFetch("refs/meta/config");
    commit = testRepo.branch("refs/meta/config").commit().create();

    assertThat(push(commit.name() + ":refs/meta/config")).onlyRef("refs/meta/config").isOk();
  }

  @Test
  public void createChangeDenied() throws Exception {
    testRepo.branch("HEAD").commit().create();
    PushResult r = push("HEAD:refs/for/master");
    assertThat(r)
        .onlyRef("refs/for/master")
        .isRejected("prohibited by Gerrit: not permitted: create change on refs/heads/master");
    assertThat(r)
        .containsMessages(
            "error: branch refs/for/master:",
            "You need 'Create Change' rights to upload code review requests.",
            "Verify that you are pushing to the right branch.");
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void updateBySubmitDenied() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.PUSH).ref("refs/for/refs/heads/*").group(REGISTERED_USERS))
        .update();

    ObjectId commit =
        testRepo.branch("HEAD").commit().message("test commit").insertChangeId().create();
    assertThat(push("HEAD:refs/for/master")).onlyRef("refs/for/master").isOk();
    gApi.changes().id(commit.name()).current().review(ReviewInput.approve());

    PushResult r = push("HEAD:refs/for/master%submit");
    assertThat(r)
        .onlyRef("refs/for/master%submit")
        .isRejected("prohibited by Gerrit: not permitted: update by submit on refs/heads/master");
    assertThat(r)
        .containsMessages(
            "You need 'Submit' rights on refs/for/ to submit changes during change upload.");
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void addPatchSetDenied() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.PUSH).ref("refs/for/refs/heads/*").group(REGISTERED_USERS))
        .update();
    requestScopeOperations.setApiUser(user.id());
    ChangeInput ci = new ChangeInput();
    ci.project = project.get();
    ci.branch = "master";
    ci.subject = "A change";
    Change.Id id = Change.id(gApi.changes().create(ci).get()._number);

    requestScopeOperations.setApiUser(admin.id());
    ObjectId ps1Id = forceFetch(PatchSet.id(id, 1).toRefName());
    ObjectId ps2Id = testRepo.amend(ps1Id).add("file", "content").create();
    PushResult r = push(ps2Id.name() + ":refs/for/master");
    // Admin had ADD_PATCH_SET removed in setup.
    assertThat(r)
        .onlyRef("refs/for/master")
        .isRejected("cannot add patch set to " + id.get() + ".");
    assertThat(r).hasNoMessages();
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void skipValidationDenied() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.PUSH).ref("refs/heads/*").group(REGISTERED_USERS))
        .update();

    testRepo.branch("HEAD").commit().create();
    PushResult r =
        push(c -> c.setPushOptions(ImmutableList.of("skip-validation")), "HEAD:refs/heads/master");
    assertThat(r)
        .onlyRef("refs/heads/master")
        .isRejected("prohibited by Gerrit: not permitted: skip validation");
    assertThat(r)
        .containsMessages(
            "You need 'Forge Author', 'Forge Server', 'Forge Committer'",
            "and 'Push Merge' rights to skip validation.");
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void accessDatabaseForNoteDbDenied() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.PUSH).ref("refs/heads/*").group(REGISTERED_USERS))
        .update();

    testRepo.branch("HEAD").commit().create();
    PushResult r =
        push(
            c -> c.setPushOptions(ImmutableList.of("notedb=allow")),
            "HEAD:refs/changes/34/1234/meta");
    // Same rejection message regardless of whether NoteDb is actually enabled.
    assertThat(r)
        .onlyRef("refs/changes/34/1234/meta")
        .isRejected("NoteDb update requires access database permission");
    assertThat(r).hasNoMessages();
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void administrateServerForUpdateParentDenied() throws Exception {
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.PUSH).ref("refs/meta/config").group(REGISTERED_USERS))
        .add(allow(Permission.OWNER).ref("refs/*").group(REGISTERED_USERS))
        .update();

    String project2 = name("project2");
    projectOperations.newProject().name(project2).create();

    ObjectId oldId = forceFetch("refs/meta/config");

    Config cfg = new BlobBasedConfig(null, testRepo.getRepository(), oldId, "project.config");
    cfg.setString("access", null, "inheritFrom", project2);
    ObjectId newId =
        testRepo.branch("refs/meta/config").commit().add("project.config", cfg.toText()).create();

    PushResult r = push(newId.name() + ":refs/meta/config");
    assertThat(r)
        .onlyRef("refs/meta/config")
        .isRejected("invalid project configuration: only Gerrit admin can set parent");
    assertThat(r).hasNoMessages();
    assertThat(r).hasProcessed(ImmutableMap.of("refs", 1));
  }

  @Test
  public void pushTreeIsNotAllowed() throws Exception {
    RevCommit commit = testRepo.branch("HEAD").commit().create();
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.CREATE).ref("refs/*").group(REGISTERED_USERS))
        .add(allow(Permission.PUSH).ref("refs/*").group(REGISTERED_USERS))
        .update();

    // We use "refs/main" instead of "refs/heads/main", because the latter only allows commits.
    {
      // An extra colon (:) makes it a tree reference
      PushResult r = push(commit.getId().getName() + "::refs/main");
      RemoteRefUpdate refUpdate = r.getRemoteUpdates().stream().findFirst().get();
      assertThat(refUpdate.getStatus()).isEqualTo(Status.REJECTED_OTHER_REASON);
      assertThat(refUpdate.getMessage()).contains("is neither Commit or Tag");
    }

    {
      PushResult r = push(commit.getTree().getId().getName() + ":refs/main");
      RemoteRefUpdate refUpdate = r.getRemoteUpdates().stream().findFirst().get();
      assertThat(refUpdate.getStatus()).isEqualTo(Status.REJECTED_OTHER_REASON);
      assertThat(refUpdate.getMessage()).contains("is neither Commit or Tag");
    }
  }

  private static void removeAllBranchPermissions(ProjectConfig cfg, String... permissions) {
    for (AccessSection s : cfg.getAccessSections()) {
      if (s.getName().startsWith("refs/heads/")
          || s.getName().startsWith("refs/for/")
          || s.getName().equals("refs/*")) {
        cfg.upsertAccessSection(
            s.getName(),
            updatedSection -> {
              Arrays.stream(permissions).forEach(p -> updatedSection.remove(Permission.builder(p)));
            });
      }
    }
  }

  private static void removeAllGlobalCapabilities(ProjectConfig cfg, String... capabilities) {
    Arrays.stream(capabilities)
        .forEach(
            c ->
                cfg.upsertAccessSection(
                    AccessSection.GLOBAL_CAPABILITIES,
                    as -> {
                      as.upsertPermission(c).clearRules();
                    }));
  }

  private PushResult push(String... refSpecs) throws Exception {
    return push(c -> {}, refSpecs);
  }

  private PushResult push(Consumer<PushCommand> setUp, String... refSpecs) throws Exception {
    PushCommand cmd =
        testRepo
            .git()
            .push()
            .setRemote("origin")
            .setRefSpecs(Arrays.stream(refSpecs).map(RefSpec::new).collect(toList()));
    setUp.accept(cmd);
    Iterable<PushResult> results = cmd.call();
    assertWithMessage("expected 1 PushResult").that(results).hasSize(1);
    return results.iterator().next();
  }

  private ObjectId forceFetch(String ref) throws Exception {
    TrackingRefUpdate u =
        testRepo.git().fetch().setRefSpecs("+" + ref + ":" + ref).call().getTrackingRefUpdate(ref);
    assertThat(u).isNotNull();
    switch (u.getResult()) {
      case NEW:
      case FAST_FORWARD:
      case FORCED:
        break;
      case IO_FAILURE:
      case LOCK_FAILURE:
      case NOT_ATTEMPTED:
      case NO_CHANGE:
      case REJECTED:
      case REJECTED_CURRENT_BRANCH:
      case REJECTED_MISSING_OBJECT:
      case REJECTED_OTHER_REASON:
      case RENAMED:
      default:
        assertWithMessage("fetch failed to update local %s: %s", ref, u.getResult()).fail();
        break;
    }
    return u.getNewObjectId();
  }
}
