// Copyright (C) 2016 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.gerrit.acceptance.testsuite.project.TestProjectUpdate.allow;
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;
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.server.schema.AclUtil.grant;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.google.gerrit.testing.TestActionRefUpdateContext.testRefAction;
import static com.google.gerrit.truth.ConfigSubject.assertThat;
import static com.google.gerrit.truth.MapSubject.assertThatMap;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;

import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.ExtensionRegistry;
import com.google.gerrit.acceptance.ExtensionRegistry.Registration;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.config.GerritConfig;
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.GroupDescription;
import com.google.gerrit.entities.GroupReference;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.access.AccessSectionInfo;
import com.google.gerrit.extensions.api.access.PermissionInfo;
import com.google.gerrit.extensions.api.access.PermissionRuleInfo;
import com.google.gerrit.extensions.api.access.ProjectAccessInfo;
import com.google.gerrit.extensions.api.access.ProjectAccessInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.projects.ProjectApi;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.common.WebLinkInfo;
import com.google.gerrit.extensions.config.CapabilityDefinition;
import com.google.gerrit.extensions.config.PluginProjectPermissionDefinition;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.webui.FileHistoryWebLink;
import com.google.gerrit.server.config.AllProjectsNameProvider;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.group.testing.TestGroupBackend;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.schema.GrantRevertPermission;
import com.google.inject.Inject;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Test;

public class AccessIT extends AbstractDaemonTest {

  private static final String REFS_ALL = Constants.R_REFS + "*";
  private static final String REFS_HEADS = Constants.R_HEADS + "*";
  private static final String REFS_META_VERSION = "refs/meta/version";
  private static final String REFS_DRAFTS = "refs/draft-comments/*";
  private static final String REFS_STARRED_CHANGES = "refs/starred-changes/*";

  @Inject private ProjectOperations projectOperations;
  @Inject private RequestScopeOperations requestScopeOperations;
  @Inject private ExtensionRegistry extensionRegistry;
  @Inject private GrantRevertPermission grantRevertPermission;

  private Project.NameKey newProjectName;

  @Before
  public void setUp() throws Exception {
    newProjectName = projectOperations.newProject().create();
  }

  @Test
  public void grantRevertPermission() throws Exception {
    String ref = "refs/*";
    String groupId = "global:Registered-Users";

    grantRevertPermission.execute(newProjectName);

    ProjectAccessInfo info = pApi().access();
    assertThat(info.local.containsKey(ref)).isTrue();
    AccessSectionInfo accessSectionInfo = info.local.get(ref);
    assertThat(accessSectionInfo.permissions.containsKey(Permission.REVERT)).isTrue();
    PermissionInfo permissionInfo = accessSectionInfo.permissions.get(Permission.REVERT);
    assertThat(permissionInfo.rules.containsKey(groupId)).isTrue();
    PermissionRuleInfo permissionRuleInfo = permissionInfo.rules.get(groupId);
    assertThat(permissionRuleInfo.action).isEqualTo(PermissionRuleInfo.Action.ALLOW);
  }

  @Test
  public void grantRevertPermissionByOnNewRefAndDeletingOnOldRef() throws Exception {
    String refsHeads = "refs/heads/*";
    String refsStar = "refs/*";
    String groupId = "global:Registered-Users";
    GroupReference registeredUsers = systemGroupBackend.getGroup(REGISTERED_USERS);

    try (Repository repo = repoManager.openRepository(newProjectName)) {
      MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, newProjectName, repo);
      ProjectConfig projectConfig = projectConfigFactory.read(md);
      projectConfig.upsertAccessSection(
          AccessSection.HEADS,
          heads -> {
            grant(projectConfig, heads, Permission.REVERT, registeredUsers);
          });
      md.getCommitBuilder().setAuthor(admin.newIdent());
      md.getCommitBuilder().setCommitter(admin.newIdent());
      md.setMessage("Add revert permission for all registered users\n");

      projectConfig.commit(md);
    }
    grantRevertPermission.execute(newProjectName);

    ProjectAccessInfo info = pApi().access();

    // Revert permission is removed on refs/heads/*.
    assertThat(info.local.containsKey(refsHeads)).isTrue();
    AccessSectionInfo accessSectionInfo = info.local.get(refsHeads);
    assertThat(accessSectionInfo.permissions.containsKey(Permission.REVERT)).isFalse();

    // new permission is added on refs/* with Registered-Users.
    assertThat(info.local.containsKey(refsStar)).isTrue();
    accessSectionInfo = info.local.get(refsStar);
    assertThat(accessSectionInfo.permissions.containsKey(Permission.REVERT)).isTrue();
    PermissionInfo permissionInfo = accessSectionInfo.permissions.get(Permission.REVERT);
    assertThat(permissionInfo.rules.containsKey(groupId)).isTrue();
    PermissionRuleInfo permissionRuleInfo = permissionInfo.rules.get(groupId);
    assertThat(permissionRuleInfo.action).isEqualTo(PermissionRuleInfo.Action.ALLOW);
  }

  @Test
  public void grantRevertPermissionDoesntDeleteAdminsPreferences() throws Exception {
    GroupReference registeredUsers = systemGroupBackend.getGroup(REGISTERED_USERS);
    GroupReference otherGroup = systemGroupBackend.getGroup(ANONYMOUS_USERS);

    try (Repository repo = repoManager.openRepository(newProjectName)) {
      MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, newProjectName, repo);
      ProjectConfig projectConfig = projectConfigFactory.read(md);
      projectConfig.upsertAccessSection(
          AccessSection.HEADS,
          heads -> {
            grant(projectConfig, heads, Permission.REVERT, registeredUsers);
            grant(projectConfig, heads, Permission.REVERT, otherGroup);
          });
      md.getCommitBuilder().setAuthor(admin.newIdent());
      md.getCommitBuilder().setCommitter(admin.newIdent());
      md.setMessage("Add revert permission for all registered users\n");

      projectConfig.commit(md);
    }
    projectCache.evict(newProjectName);
    ProjectAccessInfo expected = pApi().access();

    grantRevertPermission.execute(newProjectName);
    projectCache.evict(newProjectName);
    ProjectAccessInfo actual = pApi().access();
    // Permissions don't change
    assertThat(actual.local).isEqualTo(expected.local);
  }

  @Test
  public void grantRevertPermissionOnlyWorksOnce() throws Exception {
    grantRevertPermission.execute(newProjectName);
    grantRevertPermission.execute(newProjectName);

    try (Repository repo = repoManager.openRepository(newProjectName)) {
      MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, newProjectName, repo);
      ProjectConfig projectConfig = projectConfigFactory.read(md);
      AccessSection all = projectConfig.getAccessSection(AccessSection.ALL);

      Permission permission = all.getPermission(Permission.REVERT);
      assertThat(permission.getRules()).hasSize(1);
    }
  }

  @Test
  public void getDefaultInheritance() throws Exception {
    String inheritedName = pApi().access().inheritsFrom.name;
    assertThat(inheritedName).isEqualTo(AllProjectsNameProvider.DEFAULT);
  }

  private Registration newFileHistoryWebLink() {
    FileHistoryWebLink weblink =
        new FileHistoryWebLink() {
          @Override
          public WebLinkInfo getFileHistoryWebLink(
              String projectName, String revision, String fileName) {
            return new WebLinkInfo(
                "name", "imageURL", "http://view/" + projectName + "/" + fileName);
          }
        };
    return extensionRegistry.newRegistration().add(weblink);
  }

  @Test
  public void webLink() throws Exception {
    try (Registration registration = newFileHistoryWebLink()) {
      ProjectAccessInfo info = pApi().access();
      assertThat(info.configWebLinks).hasSize(1);
      assertThat(info.configWebLinks.get(0).url)
          .isEqualTo("http://view/" + newProjectName + "/project.config");
    }
  }

  @Test
  public void webLinkNoRefsMetaConfig() throws Exception {
    try (Repository repo = repoManager.openRepository(newProjectName);
        Registration registration = newFileHistoryWebLink()) {
      RefUpdate u = repo.updateRef(RefNames.REFS_CONFIG);
      u.setForceUpdate(true);
      testRefAction(() -> assertThat(u.delete()).isEqualTo(Result.FORCED));

      // This should not crash.
      @SuppressWarnings("unused")
      var unused = pApi().access();
    }
  }

  @Test
  public void addAccessSection() throws Exception {
    RevCommit initialHead = projectOperations.project(newProjectName).getHead(RefNames.REFS_CONFIG);

    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi().access(accessInput);

    assertThat(pApi().access().local).isEqualTo(accessInput.add);

    RevCommit updatedHead = projectOperations.project(newProjectName).getHead(RefNames.REFS_CONFIG);
    eventRecorder.assertRefUpdatedEvents(
        newProjectName.get(), RefNames.REFS_CONFIG, null, initialHead, initialHead, updatedHead);
  }

  @Test
  public void addDuplicatedAccessSection_doesNotAddDuplicateEntry() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    // Update project config. Record the file content and the refs_config object ID
    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi().access(accessInput);
    ObjectId refsConfigId =
        projectOperations.project(newProjectName).getHead(RefNames.REFS_CONFIG).getId();
    List<String> projectConfigLines =
        Arrays.asList(projectOperations.project(newProjectName).getConfig().toText().split("\n"));
    assertThat(projectConfigLines)
        .containsExactly(
            "[submit]",
            "\taction = inherit",
            "[access \"refs/heads/*\"]",
            "\tlabel-Code-Review = deny group Registered Users",
            "\tlabel-Code-Review = -1..+1 group Project Owners",
            "\tpush = group Registered Users");

    // Apply the same update once more. Make sure that the file content and the ref did not change
    pApi().access(accessInput);

    List<String> newProjectConfigLines =
        Arrays.asList(projectOperations.project(newProjectName).getConfig().toText().split("\n"));
    ObjectId newRefsConfigId =
        projectOperations.project(newProjectName).getHead(RefNames.REFS_CONFIG).getId();
    assertThat(projectConfigLines).isEqualTo(newProjectConfigLines);
    assertThat(refsConfigId).isEqualTo(newRefsConfigId);
  }

  @Test
  public void addAccessSectionForPluginPermission() throws Exception {
    try (Registration registration =
        extensionRegistry
            .newRegistration()
            .add(
                new PluginProjectPermissionDefinition() {
                  @Override
                  public String getDescription() {
                    return "A Plugin Project Permission";
                  }
                },
                "fooPermission")) {
      ProjectAccessInput accessInput = newProjectAccessInput();
      AccessSectionInfo accessSectionInfo = newAccessSectionInfo();

      PermissionInfo foo = newPermissionInfo();
      PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
      foo.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
      accessSectionInfo.permissions.put(
          "plugin-" + ExtensionRegistry.PLUGIN_NAME + "-fooPermission", foo);

      accessInput.add.put(REFS_HEADS, accessSectionInfo);
      ProjectAccessInfo updatedAccessSectionInfo = pApi().access(accessInput);
      assertThat(updatedAccessSectionInfo.local).isEqualTo(accessInput.add);

      assertThat(pApi().access().local).isEqualTo(accessInput.add);
    }
  }

  @Test
  public void addAccessSectionWithInvalidPermission() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    PermissionInfo push = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    push.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSectionInfo.permissions.put("Invalid Permission", push);

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    BadRequestException ex =
        assertThrows(BadRequestException.class, () -> pApi().access(accessInput));
    assertThat(ex).hasMessageThat().isEqualTo("Unknown permission: Invalid Permission");
  }

  @Test
  public void addAccessSectionWithInvalidLabelPermission() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    PermissionInfo push = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    push.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSectionInfo.permissions.put("label-Invalid Permission", push);

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    BadRequestException ex =
        assertThrows(BadRequestException.class, () -> pApi().access(accessInput));
    assertThat(ex).hasMessageThat().isEqualTo("Unknown permission: label-Invalid Permission");
  }

  @Test
  public void addAccessSectionWithInvalidLabelRange_minGreaterThanMax() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    PermissionInfo permissionInfo = newPermissionInfo();
    PermissionRuleInfo permissionRuleInfo =
        new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    permissionInfo.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), permissionRuleInfo);
    permissionRuleInfo.min = 1;
    permissionRuleInfo.max = -1;
    accessSectionInfo.permissions.put("label-Code-Review", permissionInfo);

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    BadRequestException ex =
        assertThrows(BadRequestException.class, () -> pApi().access(accessInput));
    assertThat(ex)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "Invalid range for permission rule that assigns label-Code-Review to group %s"
                    + " on ref refs/heads/*: 1..-1 (min must be <= max)",
                SystemGroupBackend.REGISTERED_USERS.get()));
  }

  @Test
  public void addAccessSectionWithInvalidLabelRange_minSetMaxMissing() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    PermissionInfo permissionInfo = newPermissionInfo();
    PermissionRuleInfo permissionRuleInfo =
        new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    permissionInfo.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), permissionRuleInfo);
    permissionRuleInfo.min = -1;
    accessSectionInfo.permissions.put("label-Code-Review", permissionInfo);

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    BadRequestException ex =
        assertThrows(BadRequestException.class, () -> pApi().access(accessInput));
    assertThat(ex)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "Invalid range for permission rule that assigns label-Code-Review to group %s"
                    + " on ref refs/heads/*: -1.. (max is required if min is set)",
                SystemGroupBackend.REGISTERED_USERS.get()));
  }

  @Test
  public void addAccessSectionWithInvalidLabelRange_maxSetMinMissing() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    PermissionInfo permissionInfo = newPermissionInfo();
    PermissionRuleInfo permissionRuleInfo =
        new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    permissionInfo.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), permissionRuleInfo);
    permissionRuleInfo.max = 1;
    accessSectionInfo.permissions.put("label-Code-Review", permissionInfo);

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    BadRequestException ex =
        assertThrows(BadRequestException.class, () -> pApi().access(accessInput));
    assertThat(ex)
        .hasMessageThat()
        .isEqualTo(
            String.format(
                "Invalid range for permission rule that assigns label-Code-Review to group %s"
                    + " on ref refs/heads/*: ..1 (min is required if max is set)",
                SystemGroupBackend.REGISTERED_USERS.get()));
  }

  @Test
  public void createAccessChangeNop() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    assertThrows(BadRequestException.class, () -> pApi().accessChange(accessInput));
  }

  @Test
  public void createAccessChangeEmptyConfig() throws Exception {
    try (Repository repo = repoManager.openRepository(newProjectName)) {
      RefUpdate ru = repo.updateRef(RefNames.REFS_CONFIG);
      ru.setForceUpdate(true);
      testRefAction(() -> assertThat(ru.delete()).isEqualTo(Result.FORCED));

      ProjectAccessInput accessInput = newProjectAccessInput();
      AccessSectionInfo accessSection = newAccessSectionInfo();
      PermissionInfo read = newPermissionInfo();
      PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.BLOCK, false);
      read.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
      accessSection.permissions.put(Permission.READ, read);
      accessInput.add.put(REFS_HEADS, accessSection);

      ChangeInfo out = pApi().accessChange(accessInput);
      assertThat(out.status).isEqualTo(ChangeStatus.NEW);
    }
  }

  @Test
  public void createAccessChange() throws Exception {
    projectOperations
        .project(newProjectName)
        .forUpdate()
        .add(allow(Permission.READ).ref(RefNames.REFS_CONFIG).group(REGISTERED_USERS))
        .update();

    // User can see the branch
    requestScopeOperations.setApiUser(user.id());
    @SuppressWarnings("unused")
    var unused = pApi().branch("refs/heads/master").get();

    ProjectAccessInput accessInput = newProjectAccessInput();

    AccessSectionInfo accessSection = newAccessSectionInfo();

    // Deny read to registered users.
    PermissionInfo read = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    read.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    read.exclusive = true;
    accessSection.permissions.put(Permission.READ, read);
    accessInput.add.put(REFS_HEADS, accessSection);

    requestScopeOperations.setApiUser(user.id());
    ChangeInfo out = pApi().accessChange(accessInput);

    assertThat(out.project).isEqualTo(newProjectName.get());
    assertThat(out.branch).isEqualTo(RefNames.REFS_CONFIG);
    assertThat(out.status).isEqualTo(ChangeStatus.NEW);
    assertThat(out.submitted).isNull();

    requestScopeOperations.setApiUser(admin.id());

    ChangeInfo c = gApi.changes().id(out._number).get(MESSAGES);
    assertThat(c.messages.stream().map(m -> m.message)).containsExactly("Uploaded patch set 1");

    ReviewInput reviewIn = new ReviewInput();
    reviewIn.label("Code-Review", (short) 2);
    gApi.changes().id(out._number).current().review(reviewIn);
    gApi.changes().id(out._number).current().submit();

    // check that the change took effect.
    requestScopeOperations.setApiUser(user.id());
    assertThrows(ResourceNotFoundException.class, () -> pApi().branch("refs/heads/master").get());

    // Restore.
    accessInput.add.clear();
    accessInput.remove.put(REFS_HEADS, accessSection);
    requestScopeOperations.setApiUser(user.id());

    requestScopeOperations.setApiUser(admin.id());
    out = pApi().accessChange(accessInput);

    gApi.changes().id(out._number).current().review(reviewIn);
    gApi.changes().id(out._number).current().submit();

    // Now it works again.
    requestScopeOperations.setApiUser(user.id());
    unused = pApi().branch("refs/heads/master").get();
  }

  @Test
  public void removePermission() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi().access(accessInput);

    // Remove specific permission
    AccessSectionInfo accessSectionToRemove = newAccessSectionInfo();
    accessSectionToRemove.permissions.put(
        Permission.LABEL + LabelId.CODE_REVIEW, newPermissionInfo());
    ProjectAccessInput removal = newProjectAccessInput();
    removal.remove.put(REFS_HEADS, accessSectionToRemove);
    pApi().access(removal);

    // Remove locally
    accessInput.add.get(REFS_HEADS).permissions.remove(Permission.LABEL + LabelId.CODE_REVIEW);

    // Check
    assertThat(pApi().access().local).isEqualTo(accessInput.add);
  }

  @Test
  public void removePermissionRule() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi().access(accessInput);

    // Remove specific permission rule
    AccessSectionInfo accessSectionToRemove = newAccessSectionInfo();
    PermissionInfo codeReview = newPermissionInfo();
    codeReview.label = LabelId.CODE_REVIEW;
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    codeReview.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSectionToRemove.permissions.put(Permission.LABEL + LabelId.CODE_REVIEW, codeReview);
    ProjectAccessInput removal = newProjectAccessInput();
    removal.remove.put(REFS_HEADS, accessSectionToRemove);
    pApi().access(removal);

    // Remove locally
    accessInput
        .add
        .get(REFS_HEADS)
        .permissions
        .get(Permission.LABEL + LabelId.CODE_REVIEW)
        .rules
        .remove(SystemGroupBackend.REGISTERED_USERS.get());

    // Check
    assertThat(pApi().access().local).isEqualTo(accessInput.add);
  }

  @Test
  public void removePermissionRuleForNonExistingeExternalGroup() throws Exception {
    // Register a group backend with an external group
    TestGroupBackend testGroupBackend = new TestGroupBackend();
    GroupDescription.Basic externalGroup = testGroupBackend.create("External Group");
    try (ExtensionRegistry.Registration registration =
        extensionRegistry.newRegistration().add(testGroupBackend)) {
      // Add a permission for the external group.
      ProjectAccessInput accessInput = newProjectAccessInput();
      AccessSectionInfo accessSectionInfo = newAccessSectionInfo();
      PermissionInfo push = newPermissionInfo();
      PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
      push.rules.put(externalGroup.getGroupUUID().get(), pri);
      accessSectionInfo.permissions.put(Permission.PUSH, push);
      accessInput.add.put(REFS_HEADS, accessSectionInfo);
      pApi().access(accessInput);
      assertThat(pApi().access().local).isNotEmpty();

      // Remove the external group.
      testGroupBackend.remove(externalGroup.getGroupUUID());

      // Remove the permission rule for the external group that no longer exists.
      AccessSectionInfo accessSectionToRemove = newAccessSectionInfo();
      push = newPermissionInfo();
      pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
      push.rules.put(externalGroup.getGroupUUID().get(), pri);
      accessSectionToRemove.permissions.put(Permission.PUSH, push);
      ProjectAccessInput removal = newProjectAccessInput();
      removal.remove.put(REFS_HEADS, accessSectionToRemove);
      pApi().access(removal);
      assertThat(pApi().access().local).isEmpty();
    }
  }

  @Test
  public void removePermissionRulesAndCleanupEmptyEntries() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi().access(accessInput);

    // Remove specific permission rules
    AccessSectionInfo accessSectionToRemove = newAccessSectionInfo();
    PermissionInfo codeReview = newPermissionInfo();
    codeReview.label = LabelId.CODE_REVIEW;
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    codeReview.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    codeReview.rules.put(SystemGroupBackend.PROJECT_OWNERS.get(), pri);
    accessSectionToRemove.permissions.put(Permission.LABEL + LabelId.CODE_REVIEW, codeReview);
    ProjectAccessInput removal = newProjectAccessInput();
    removal.remove.put(REFS_HEADS, accessSectionToRemove);
    pApi().access(removal);

    // Remove locally
    accessInput.add.get(REFS_HEADS).permissions.remove(Permission.LABEL + LabelId.CODE_REVIEW);

    // Check
    assertThat(pApi().access().local).isEqualTo(accessInput.add);
  }

  @Test
  public void getPermissionsWithDisallowedUser() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createAccessSectionInfoDenyAll();

    // Disallow READ
    accessInput.add.put(REFS_META_VERSION, accessSectionInfo);
    accessInput.add.put(REFS_DRAFTS, accessSectionInfo);
    accessInput.add.put(REFS_STARRED_CHANGES, accessSectionInfo);
    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi().access(accessInput);

    requestScopeOperations.setApiUser(user.id());
    assertThrows(ResourceNotFoundException.class, () -> pApi().access());
  }

  @Test
  public void setPermissionsWithDisallowedUser() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createAccessSectionInfoDenyAll();

    // Disallow READ
    accessInput.add.put(REFS_META_VERSION, accessSectionInfo);
    accessInput.add.put(REFS_DRAFTS, accessSectionInfo);
    accessInput.add.put(REFS_STARRED_CHANGES, accessSectionInfo);
    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    pApi().access(accessInput);

    // Create a change to apply
    ProjectAccessInput accessInfoToApply = newProjectAccessInput();
    AccessSectionInfo accessSectionInfoToApply = createDefaultAccessSectionInfo();
    accessInfoToApply.add.put(REFS_HEADS, accessSectionInfoToApply);

    requestScopeOperations.setApiUser(user.id());
    assertThrows(ResourceNotFoundException.class, () -> pApi().access());
  }

  @Test
  public void permissionsGroupMap() throws Exception {
    // Add initial permission set
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSection = newAccessSectionInfo();

    PermissionInfo push = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    push.rules.put(SystemGroupBackend.PROJECT_OWNERS.get(), pri);
    accessSection.permissions.put(Permission.PUSH, push);

    PermissionInfo read = newPermissionInfo();
    pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    read.rules.put(SystemGroupBackend.ANONYMOUS_USERS.get(), pri);
    accessSection.permissions.put(Permission.READ, read);

    accessInput.add.put(REFS_ALL, accessSection);
    ProjectAccessInfo result = pApi().access(accessInput);
    assertThatMap(result.groups)
        .keys()
        .containsExactly(
            SystemGroupBackend.PROJECT_OWNERS.get(), SystemGroupBackend.ANONYMOUS_USERS.get());

    // Check the name, which is what the UI cares about; exhaustive
    // coverage of GroupInfo should be in groups REST API tests.
    assertThat(result.groups.get(SystemGroupBackend.PROJECT_OWNERS.get()).name)
        .isEqualTo("Project Owners");
    // Strip the ID, since it is in the key.
    assertThat(result.groups.get(SystemGroupBackend.PROJECT_OWNERS.get()).id).isNull();

    // Get call returns groups too.
    ProjectAccessInfo loggedInResult = pApi().access();
    assertThatMap(loggedInResult.groups)
        .keys()
        .containsExactly(
            SystemGroupBackend.PROJECT_OWNERS.get(), SystemGroupBackend.ANONYMOUS_USERS.get());

    GroupInfo owners = loggedInResult.groups.get(SystemGroupBackend.PROJECT_OWNERS.get());
    assertThat(owners.name).isEqualTo("Project Owners");
    assertThat(owners.id).isNull();
    assertThat(owners.members).isNull();
    assertThat(owners.includes).isNull();

    // PROJECT_OWNERS is invisible to anonymous user, but GetAccess disregards visibility.
    requestScopeOperations.setApiUserAnonymous();
    ProjectAccessInfo anonResult = pApi().access();
    assertThatMap(anonResult.groups)
        .keys()
        .containsExactly(
            SystemGroupBackend.PROJECT_OWNERS.get(), SystemGroupBackend.ANONYMOUS_USERS.get());
  }

  @Test
  public void updateParentAsUser() throws Exception {
    // Create child
    String newParentProjectName = projectOperations.newProject().create().get();

    // Set new parent
    ProjectAccessInput accessInput = newProjectAccessInput();
    accessInput.parent = newParentProjectName;

    requestScopeOperations.setApiUser(user.id());
    AuthException thrown = assertThrows(AuthException.class, () -> pApi().access(accessInput));
    assertThat(thrown).hasMessageThat().contains("administrate server not permitted");
  }

  @Test
  public void updateParentAsAdministrator() throws Exception {
    // Create parent
    String newParentProjectName = projectOperations.newProject().create().get();

    // Set new parent
    ProjectAccessInput accessInput = newProjectAccessInput();
    accessInput.parent = newParentProjectName;

    pApi().access(accessInput);

    assertThat(pApi().access().inheritsFrom.name).isEqualTo(newParentProjectName);
  }

  @Test
  public void addGlobalCapabilityAsUser() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultGlobalCapabilitiesAccessSectionInfo();

    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    requestScopeOperations.setApiUser(user.id());
    assertThrows(
        AuthException.class, () -> gApi.projects().name(allProjects.get()).access(accessInput));
  }

  @Test
  public void addGlobalCapabilityAsAdmin() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultGlobalCapabilitiesAccessSectionInfo();

    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    ProjectAccessInfo updatedAccessSectionInfo =
        gApi.projects().name(allProjects.get()).access(accessInput);
    assertThatMap(updatedAccessSectionInfo.local.get(AccessSection.GLOBAL_CAPABILITIES).permissions)
        .keys()
        .containsAtLeastElementsIn(accessSectionInfo.permissions.keySet());
  }

  @Test
  public void addPluginGlobalCapability() throws Exception {
    try (Registration registration =
        extensionRegistry
            .newRegistration()
            .add(
                new CapabilityDefinition() {
                  @Override
                  public String getDescription() {
                    return "A Plugin Global Capability";
                  }
                },
                "fooCapability")) {
      ProjectAccessInput accessInput = newProjectAccessInput();
      AccessSectionInfo accessSectionInfo = newAccessSectionInfo();

      PermissionInfo foo = newPermissionInfo();
      PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
      foo.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
      accessSectionInfo.permissions.put(ExtensionRegistry.PLUGIN_NAME + "-fooCapability", foo);

      accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

      ProjectAccessInfo updatedAccessSectionInfo =
          gApi.projects().name(allProjects.get()).access(accessInput);
      assertThatMap(
              updatedAccessSectionInfo.local.get(AccessSection.GLOBAL_CAPABILITIES).permissions)
          .keys()
          .containsAtLeastElementsIn(accessSectionInfo.permissions.keySet());
    }
  }

  @Test
  public void addPermissionAsGlobalCapability() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = newAccessSectionInfo();

    PermissionInfo push = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    push.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSectionInfo.permissions.put(Permission.PUSH, push);

    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);
    BadRequestException ex =
        assertThrows(
            BadRequestException.class,
            () -> gApi.projects().name(allProjects.get()).access(accessInput));
    assertThat(ex).hasMessageThat().isEqualTo("Unknown global capability: " + Permission.PUSH);
  }

  @Test
  public void addInvalidGlobalCapability() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultGlobalCapabilitiesAccessSectionInfo();

    PermissionInfo permissionInfo = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    permissionInfo.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSectionInfo.permissions.put("Invalid Global Capability", permissionInfo);

    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);
    BadRequestException ex =
        assertThrows(
            BadRequestException.class,
            () -> gApi.projects().name(allProjects.get()).access(accessInput));
    assertThat(ex)
        .hasMessageThat()
        .isEqualTo("Unknown global capability: Invalid Global Capability");
  }

  @Test
  public void addGlobalCapabilityForNonRootProject() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultGlobalCapabilitiesAccessSectionInfo();

    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    assertThrows(BadRequestException.class, () -> pApi().access(accessInput));
  }

  @Test
  public void addNonGlobalCapabilityToGlobalCapabilities() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = newAccessSectionInfo();

    PermissionInfo permissionInfo = newPermissionInfo();
    permissionInfo.rules.put(adminGroupUuid().get(), null);
    accessSectionInfo.permissions.put(Permission.PUSH, permissionInfo);

    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);
    assertThrows(
        BadRequestException.class,
        () -> gApi.projects().name(allProjects.get()).access(accessInput));
  }

  @Test
  public void removeGlobalCapabilityAsUser() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultGlobalCapabilitiesAccessSectionInfo();

    accessInput.remove.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    requestScopeOperations.setApiUser(user.id());
    assertThrows(
        AuthException.class, () -> gApi.projects().name(allProjects.get()).access(accessInput));
  }

  @Test
  public void removeGlobalCapabilityAsAdmin() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = newAccessSectionInfo();

    PermissionInfo permissionInfo = newPermissionInfo();
    permissionInfo.rules.put(adminGroupUuid().get(), null);
    accessSectionInfo.permissions.put(GlobalCapability.ACCESS_DATABASE, permissionInfo);

    // Add and validate first as removing existing privileges such as
    // administrateServer would break upcoming tests
    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    ProjectAccessInfo updatedProjectAccessInfo =
        gApi.projects().name(allProjects.get()).access(accessInput);
    assertThatMap(updatedProjectAccessInfo.local.get(AccessSection.GLOBAL_CAPABILITIES).permissions)
        .keys()
        .containsAtLeastElementsIn(accessSectionInfo.permissions.keySet());

    // Remove
    accessInput.add.clear();
    accessInput.remove.put(AccessSection.GLOBAL_CAPABILITIES, accessSectionInfo);

    updatedProjectAccessInfo = gApi.projects().name(allProjects.get()).access(accessInput);
    assertThatMap(updatedProjectAccessInfo.local.get(AccessSection.GLOBAL_CAPABILITIES).permissions)
        .keys()
        .containsNoneIn(accessSectionInfo.permissions.keySet());
  }

  @Test
  public void unknownPermissionRemainsUnchanged() throws Exception {
    String access = "access";
    String unknownPermission = "unknownPermission";
    String registeredUsers = "group Registered Users";
    String refsFor = "refs/for/*";
    // Clone repository to forcefully add permission
    TestRepository<InMemoryRepository> allProjectsRepo = cloneProject(allProjects, admin);

    // Fetch permission ref
    GitUtil.fetch(allProjectsRepo, "refs/meta/config:cfg");
    allProjectsRepo.reset("cfg");

    // Load current permissions
    String config =
        gApi.projects()
            .name(allProjects.get())
            .branch(RefNames.REFS_CONFIG)
            .file(ProjectConfig.PROJECT_CONFIG)
            .asString();

    // Append and push unknown permission
    Config cfg = new Config();
    cfg.fromText(config);
    cfg.setString(access, refsFor, unknownPermission, registeredUsers);
    config = cfg.toText();
    PushOneCommit push =
        pushFactory.create(
            admin.newIdent(), allProjectsRepo, "Subject", ProjectConfig.PROJECT_CONFIG, config);
    push.to(RefNames.REFS_CONFIG).assertOkStatus();

    // Verify that unknownPermission is present
    config =
        gApi.projects()
            .name(allProjects.get())
            .branch(RefNames.REFS_CONFIG)
            .file(ProjectConfig.PROJECT_CONFIG)
            .asString();
    cfg.fromText(config);
    assertThat(cfg).stringValue(access, refsFor, unknownPermission).isEqualTo(registeredUsers);

    // Make permission change through API
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();
    accessInput.add.put(refsFor, accessSectionInfo);
    gApi.projects().name(allProjects.get()).access(accessInput);
    accessInput.add.clear();
    accessInput.remove.put(refsFor, accessSectionInfo);
    gApi.projects().name(allProjects.get()).access(accessInput);

    // Verify that unknownPermission is still present
    config =
        gApi.projects()
            .name(allProjects.get())
            .branch(RefNames.REFS_CONFIG)
            .file(ProjectConfig.PROJECT_CONFIG)
            .asString();
    cfg.fromText(config);
    assertThat(cfg).stringValue(access, refsFor, unknownPermission).isEqualTo(registeredUsers);
  }

  @Test
  public void allUsersCanOnlyInheritFromAllProjects() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    accessInput.parent = project.get();
    BadRequestException thrown =
        assertThrows(
            BadRequestException.class,
            () -> gApi.projects().name(allUsers.get()).access(accessInput));
    assertThat(thrown)
        .hasMessageThat()
        .contains(allUsers.get() + " must inherit from " + allProjects.get());
  }

  @Test
  public void syncCreateGroupPermission_addAndRemoveCreateGroupCapability() throws Exception {
    // Grant CREATE_GROUP to Registered Users
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSection = newAccessSectionInfo();
    PermissionInfo createGroup = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    createGroup.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSection.permissions.put(GlobalCapability.CREATE_GROUP, createGroup);
    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSection);
    gApi.projects().name(allProjects.get()).access(accessInput);

    // Assert that the permission was synced from All-Projects (global) to All-Users (ref)
    Map<String, AccessSectionInfo> local = gApi.projects().name("All-Users").access().local;
    assertThatMap(local).keys().contains(RefNames.REFS_GROUPS + "*");
    Map<String, PermissionInfo> permissions = local.get(RefNames.REFS_GROUPS + "*").permissions;
    // READ is the default permission and should be preserved by the syncer
    assertThatMap(permissions).keys().containsExactly(Permission.READ, Permission.CREATE);
    Map<String, PermissionRuleInfo> rules = permissions.get(Permission.CREATE).rules;
    assertThatMap(rules).values().containsExactly(pri);

    // Revoke the permission
    accessInput.add.clear();
    accessInput.remove.put(AccessSection.GLOBAL_CAPABILITIES, accessSection);
    gApi.projects().name(allProjects.get()).access(accessInput);

    // Assert that the permission was synced from All-Projects (global) to All-Users (ref)
    Map<String, AccessSectionInfo> local2 = gApi.projects().name("All-Users").access().local;
    assertThatMap(local2).keys().contains(RefNames.REFS_GROUPS + "*");
    Map<String, PermissionInfo> permissions2 = local2.get(RefNames.REFS_GROUPS + "*").permissions;
    // READ is the default permission and should be preserved by the syncer
    assertThatMap(permissions2).keys().containsExactly(Permission.READ);
  }

  @Test
  public void syncCreateGroupPermission_addCreateGroupCapabilityToMultipleGroups()
      throws Exception {
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);

    // Grant CREATE_GROUP to Registered Users
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSection = newAccessSectionInfo();
    PermissionInfo createGroup = newPermissionInfo();
    createGroup.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSection.permissions.put(GlobalCapability.CREATE_GROUP, createGroup);
    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSection);
    gApi.projects().name(allProjects.get()).access(accessInput);

    // Grant CREATE_GROUP to Administrators
    accessInput = newProjectAccessInput();
    accessSection = newAccessSectionInfo();
    createGroup = newPermissionInfo();
    createGroup.rules.put(adminGroupUuid().get(), pri);
    accessSection.permissions.put(GlobalCapability.CREATE_GROUP, createGroup);
    accessInput.add.put(AccessSection.GLOBAL_CAPABILITIES, accessSection);
    gApi.projects().name(allProjects.get()).access(accessInput);

    // Assert that the permissions were synced from All-Projects (global) to All-Users (ref)
    Map<String, AccessSectionInfo> local = gApi.projects().name("All-Users").access().local;
    assertThatMap(local).keys().contains(RefNames.REFS_GROUPS + "*");
    Map<String, PermissionInfo> permissions = local.get(RefNames.REFS_GROUPS + "*").permissions;
    // READ is the default permission and should be preserved by the syncer
    assertThatMap(permissions).keys().containsExactly(Permission.READ, Permission.CREATE);
    Map<String, PermissionRuleInfo> rules = permissions.get(Permission.CREATE).rules;
    assertThatMap(rules)
        .keys()
        .containsExactly(SystemGroupBackend.REGISTERED_USERS.get(), adminGroupUuid().get());
    assertThat(rules.get(SystemGroupBackend.REGISTERED_USERS.get())).isEqualTo(pri);
    assertThat(rules.get(adminGroupUuid().get())).isEqualTo(pri);
  }

  @Test
  public void addAccessSectionForInvalidRef() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    // 'refs/heads/stable_*' is invalid, correct would be '^refs/heads/stable_.*'
    String invalidRef = Constants.R_HEADS + "stable_*";
    accessInput.add.put(invalidRef, accessSectionInfo);

    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> pApi().access(accessInput));
    assertThat(thrown).hasMessageThat().contains("Invalid Name: " + invalidRef);
  }

  @Test
  public void createAccessChangeWithAccessSectionForInvalidRef() throws Exception {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    // 'refs/heads/stable_*' is invalid, correct would be '^refs/heads/stable_.*'
    String invalidRef = Constants.R_HEADS + "stable_*";
    accessInput.add.put(invalidRef, accessSectionInfo);

    BadRequestException thrown =
        assertThrows(BadRequestException.class, () -> pApi().accessChange(accessInput));
    assertThat(thrown).hasMessageThat().contains("Invalid Name: " + invalidRef);
  }

  @Test
  public void grantAllowAndDenyForSameGroup() throws Exception {
    GroupReference registeredUsers = systemGroupBackend.getGroup(REGISTERED_USERS);
    String access = "access";
    List<String> allowThenDeny =
        asList(registeredUsers.toConfigValue(), "deny " + registeredUsers.toConfigValue());
    // Clone repository to forcefully add permission
    TestRepository<InMemoryRepository> allProjectsRepo = cloneProject(allProjects, admin);

    // Fetch permission ref
    GitUtil.fetch(allProjectsRepo, "refs/meta/config:cfg");
    allProjectsRepo.reset("cfg");

    // Load current permissions
    String config =
        gApi.projects()
            .name(allProjects.get())
            .branch(RefNames.REFS_CONFIG)
            .file(ProjectConfig.PROJECT_CONFIG)
            .asString();

    // Append and push allowThenDeny permissions
    Config cfg = new Config();
    cfg.fromText(config);
    cfg.setStringList(access, AccessSection.HEADS, Permission.READ, allowThenDeny);
    config = cfg.toText();
    PushOneCommit push =
        pushFactory.create(
            admin.newIdent(), allProjectsRepo, "Subject", ProjectConfig.PROJECT_CONFIG, config);
    push.to(RefNames.REFS_CONFIG).assertOkStatus();

    ProjectAccessInfo pai = gApi.projects().name(allProjects.get()).access();
    Map<String, AccessSectionInfo> local = pai.local;
    AccessSectionInfo heads = local.get(AccessSection.HEADS);
    Map<String, PermissionInfo> permissions = heads.permissions;
    PermissionInfo read = permissions.get(Permission.READ);
    Map<String, PermissionRuleInfo> rules = read.rules;
    assertEquals(
        rules.get(registeredUsers.getUUID().get()),
        new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false));
  }

  @Test
  public void grantDenyAndAllowForSameGroup() throws Exception {
    GroupReference registeredUsers = systemGroupBackend.getGroup(REGISTERED_USERS);
    String access = "access";
    List<String> denyThenAllow =
        asList("deny " + registeredUsers.toConfigValue(), registeredUsers.toConfigValue());
    // Clone repository to forcefully add permission
    TestRepository<InMemoryRepository> allProjectsRepo = cloneProject(allProjects, admin);

    // Fetch permission ref
    GitUtil.fetch(allProjectsRepo, "refs/meta/config:cfg");
    allProjectsRepo.reset("cfg");

    // Load current permissions
    String config =
        gApi.projects()
            .name(allProjects.get())
            .branch(RefNames.REFS_CONFIG)
            .file(ProjectConfig.PROJECT_CONFIG)
            .asString();

    // Append and push denyThenAllow permissions
    Config cfg = new Config();
    cfg.fromText(config);
    cfg.setStringList(access, AccessSection.HEADS, Permission.READ, denyThenAllow);
    config = cfg.toText();
    PushOneCommit push =
        pushFactory.create(
            admin.newIdent(), allProjectsRepo, "Subject", ProjectConfig.PROJECT_CONFIG, config);
    push.to(RefNames.REFS_CONFIG).assertOkStatus();

    ProjectAccessInfo pai = gApi.projects().name(allProjects.get()).access();
    Map<String, AccessSectionInfo> local = pai.local;
    AccessSectionInfo heads = local.get(AccessSection.HEADS);
    Map<String, PermissionInfo> permissions = heads.permissions;
    PermissionInfo read = permissions.get(Permission.READ);
    Map<String, PermissionRuleInfo> rules = read.rules;
    assertEquals(
        rules.get(registeredUsers.getUUID().get()),
        new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false));
  }

  @Test
  public void canUpdateConfigWithoutCreatingChangeNullByDefault() throws Exception {
    assertThat(pApi().access().requireChangeForConfigUpdate).isNull();
    assertThat(gApi.projects().name(allProjects.get()).access().requireChangeForConfigUpdate)
        .isNull();
  }

  @Test
  @GerritConfig(name = "gerrit.requireChangeForConfigUpdate", value = "true")
  public void canUpdateConfigWithoutCreatingChangeUsesConfigValue() throws Exception {
    assertThat(pApi().access().requireChangeForConfigUpdate).isTrue();
    assertThat(gApi.projects().name(allProjects.get()).access().requireChangeForConfigUpdate)
        .isTrue();
  }

  @Test
  @GerritConfig(name = "gerrit.requireChangeForConfigUpdate", value = "true")
  public void requireChangeForConfigUpdate_postAccessRejected() {
    ProjectAccessInput accessInput = newProjectAccessInput();
    AccessSectionInfo accessSectionInfo = createDefaultAccessSectionInfo();

    accessInput.add.put(REFS_HEADS, accessSectionInfo);
    MethodNotAllowedException e =
        assertThrows(MethodNotAllowedException.class, () -> pApi().access(accessInput));
    assertThat(e.getMessage()).contains("Updating project config without review is disabled");
  }

  private ProjectApi pApi() throws Exception {
    return gApi.projects().name(newProjectName.get());
  }

  private ProjectAccessInput newProjectAccessInput() {
    ProjectAccessInput p = new ProjectAccessInput();
    p.add = new HashMap<>();
    p.remove = new HashMap<>();
    return p;
  }

  private PermissionInfo newPermissionInfo() {
    PermissionInfo p = new PermissionInfo(null, null);
    p.rules = new HashMap<>();
    return p;
  }

  private AccessSectionInfo newAccessSectionInfo() {
    AccessSectionInfo a = new AccessSectionInfo();
    a.permissions = new HashMap<>();
    return a;
  }

  private AccessSectionInfo createDefaultAccessSectionInfo() {
    AccessSectionInfo accessSection = newAccessSectionInfo();

    PermissionInfo push = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    push.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSection.permissions.put(Permission.PUSH, push);

    PermissionInfo codeReview = newPermissionInfo();
    codeReview.label = LabelId.CODE_REVIEW;
    pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    codeReview.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);

    pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    pri.max = 1;
    pri.min = -1;
    codeReview.rules.put(SystemGroupBackend.PROJECT_OWNERS.get(), pri);
    accessSection.permissions.put(Permission.LABEL + LabelId.CODE_REVIEW, codeReview);

    return accessSection;
  }

  private AccessSectionInfo createDefaultGlobalCapabilitiesAccessSectionInfo() {
    AccessSectionInfo accessSection = newAccessSectionInfo();

    PermissionInfo email = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.ALLOW, false);
    email.rules.put(SystemGroupBackend.REGISTERED_USERS.get(), pri);
    accessSection.permissions.put(GlobalCapability.EMAIL_REVIEWERS, email);

    return accessSection;
  }

  private AccessSectionInfo createAccessSectionInfoDenyAll() {
    AccessSectionInfo accessSection = newAccessSectionInfo();

    PermissionInfo read = newPermissionInfo();
    PermissionRuleInfo pri = new PermissionRuleInfo(PermissionRuleInfo.Action.DENY, false);
    read.rules.put(SystemGroupBackend.ANONYMOUS_USERS.get(), pri);
    accessSection.permissions.put(Permission.READ, read);

    return accessSection;
  }
}
