// 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.server.permissions;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
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.permissionKey;
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.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.config.GerritConfig;
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.common.Nullable;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.GroupDescription;
import com.google.gerrit.entities.GroupReference;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.ExternalUser;
import com.google.gerrit.server.PropertyMap;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.externalids.ExternalIdKeyFactory;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import java.util.Collection;
import java.util.stream.StreamSupport;
import javax.inject.Inject;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Test;

/** Tests that permission logic used by {@link ExternalUser} works as expected. */
public class ExternalUserPermissionIT extends AbstractDaemonTest {
  private static final AccountGroup.UUID EXTERNAL_GROUP =
      AccountGroup.uuid("company-auth:it-department");

  @Inject private ChangeOperations changeOperations;
  @Inject private ProjectOperations projectOperations;
  @Inject private PermissionBackend permissionBackend;
  @Inject private ChangeNotes.Factory changeNotesFactory;
  @Inject private ExternalUser.Factory externalUserFactory;
  @Inject private GroupOperations groupOperations;
  @Inject private ExternalIdKeyFactory externalIdKeyFactory;

  @Before
  public void setUp() {
    // Allow only read on refs/heads/master by default
    projectOperations
        .project(allProjects)
        .forUpdate()
        .remove(permissionKey(Permission.READ).ref("refs/heads/*").group(ANONYMOUS_USERS))
        .add(allow(Permission.READ).ref("refs/heads/master").group(ANONYMOUS_USERS))
        .update();
  }

  @Override
  public Module createModule() {
    /**
     * Binding a {@link GroupBackend} that pretends a user is part of a group if the external ID
     * starts with the group UUID.
     *
     * <p>Example: Users "company-auth:it-department-1" and "company-auth:it-department-2" are a
     * member of the group "company-auth:it-department"
     */
    return new AbstractModule() {
      @Override
      protected void configure() {
        DynamicSet.bind(binder(), GroupBackend.class)
            .toInstance(
                new GroupBackend() {
                  @Override
                  public boolean handles(AccountGroup.UUID uuid) {
                    return uuid.get().startsWith("company-auth:");
                  }

                  @Override
                  public GroupDescription.Basic get(AccountGroup.UUID uuid) {
                    return new GroupDescription.Basic() {
                      @Override
                      public AccountGroup.UUID getGroupUUID() {
                        return uuid;
                      }

                      @Override
                      public String getName() {
                        return uuid.get();
                      }

                      @Override
                      public String getEmailAddress() {
                        return uuid.get() + "@example.com";
                      }

                      @Override
                      @Nullable
                      public String getUrl() {
                        return null;
                      }
                    };
                  }

                  @Override
                  public Collection<GroupReference> suggest(String name, ProjectState project) {
                    throw new UnsupportedOperationException("not implemented");
                  }

                  @Override
                  public GroupMembership membershipsOf(CurrentUser user) {
                    return new GroupMembership() {
                      @Override
                      public boolean contains(AccountGroup.UUID groupId) {
                        return user.getExternalIdKeys().stream()
                            .anyMatch(e -> e.get().startsWith(groupId.get()));
                      }

                      @Override
                      public boolean containsAnyOf(Iterable<AccountGroup.UUID> groupIds) {
                        return StreamSupport.stream(groupIds.spliterator(), /* parallel= */ false)
                            .anyMatch(g -> contains(g));
                      }

                      @Override
                      public ImmutableSet<AccountGroup.UUID> intersection(
                          Iterable<AccountGroup.UUID> groupIds) {
                        return StreamSupport.stream(groupIds.spliterator(), /* parallel= */ false)
                            .filter(g -> contains(g))
                            .collect(toImmutableSet());
                      }

                      @Override
                      public ImmutableSet<AccountGroup.UUID> getKnownGroups() {
                        return ImmutableSet.of();
                      }
                    };
                  }

                  @Override
                  public boolean isVisibleToAll(AccountGroup.UUID uuid) {
                    return false;
                  }
                });
      }
    };
  }

  @Test
  public void defaultRefFilter_changeVisibilityIsAgnosticOfProvidedGroups() throws Exception {
    ExternalUser user = createUserInGroup("1", "it-department");

    Change.Id changeOnMaster = changeOperations.newChange().project(project).createV1();
    Change.Id changeOnRefsMetaConfig =
        changeOperations.newChange().project(project).branch("refs/meta/config").createV1();
    // Check that only the change on the default branch is visible
    assertThat(getVisibleRefNames(user))
        .containsExactly(
            "HEAD",
            "refs/heads/master",
            RefNames.changeMetaRef(changeOnMaster),
            RefNames.patchSetRef(PatchSet.id(changeOnMaster, 1)));
    // Grant access
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/meta/config").group(EXTERNAL_GROUP))
        .update();
    // Check that both changes are visible now
    assertThat(getVisibleRefNames(user))
        .containsExactly(
            "HEAD",
            "refs/heads/master",
            "refs/meta/config",
            RefNames.changeMetaRef(changeOnMaster),
            RefNames.patchSetRef(PatchSet.id(changeOnMaster, 1)),
            RefNames.changeMetaRef(changeOnRefsMetaConfig),
            RefNames.patchSetRef(PatchSet.id(changeOnRefsMetaConfig, 1)));
  }

  @Test
  public void defaultRefFilter_refVisibilityIsAgnosticOfProvidedGroups() throws Exception {
    ExternalUser user = createUserInGroup("1", "it-department");
    // Check that refs/meta/config isn't visible by default
    assertThat(getVisibleRefNames(user)).containsExactly("HEAD", "refs/heads/master");
    // Grant access
    projectOperations
        .project(project)
        .forUpdate()
        .add(allow(Permission.READ).ref("refs/meta/config").group(EXTERNAL_GROUP))
        .update();
    // Check that refs/meta/config became visible
    assertThat(getVisibleRefNames(user))
        .containsExactly("HEAD", "refs/heads/master", "refs/meta/config");
  }

  @Test
  public void changeVisibility_changeOnInvisibleBranchNotVisible() throws Exception {
    // Create a change that is not visible to members of 'externalGroup'
    Change.Id invisibleChange =
        changeOperations.newChange().project(project).branch("refs/meta/config").createV1();
    ExternalUser user = createUserInGroup("1", "it-department");
    AuthException thrown =
        assertThrows(
            AuthException.class,
            () ->
                permissionBackend
                    .user(user)
                    .change(changeNotesFactory.create(project, invisibleChange))
                    .check(ChangePermission.READ));
    assertThat(thrown).hasMessageThat().isEqualTo("read not permitted");
  }

  @Test
  public void changeVisibility_changeOnBranchVisibleToAnonymousIsVisible() throws Exception {
    Change.Id changeId = changeOperations.newChange().project(project).createV1();
    ExternalUser user = createUserInGroup("1", "it-department");
    permissionBackend
        .user(user)
        .change(changeNotesFactory.create(project, changeId))
        .check(ChangePermission.READ);
  }

  @Test
  public void changeVisibility_changeOnBranchVisibleToRegisteredUsersIsVisible() throws Exception {
    Change.Id changeId = changeOperations.newChange().project(project).createV1();
    ExternalUser user = createUserInGroup("1", "it-department");
    blockAnonymousRead();
    permissionBackend
        .user(user)
        .change(changeNotesFactory.create(project, changeId))
        .check(ChangePermission.READ);
  }

  @Test
  public void externalUser_isContainedInternalGroupThatContainsExternalGroup() {
    AccountGroup.UUID internalGroup =
        groupOperations.newGroup().addSubgroup(EXTERNAL_GROUP).create();
    ExternalUser user = createUserInGroup("1", "it-department");
    assertThat(user.getEffectiveGroups().contains(internalGroup)).isTrue();
    assertThat(user.getEffectiveGroups().contains(EXTERNAL_GROUP)).isTrue();
    assertThat(user.getEffectiveGroups().contains(REGISTERED_USERS)).isTrue();
    assertThat(user.getEffectiveGroups().contains(ANONYMOUS_USERS)).isTrue();
  }

  @GerritConfig(name = "groups.includeExternalUsersInRegisteredUsersGroup", value = "true")
  @Test
  public void externalUser_isContainedInRegisteredUsersIfConfigured() {
    ExternalUser user = createUserInGroup("1", "it-department");
    assertThat(user.getEffectiveGroups().contains(REGISTERED_USERS)).isTrue();
  }

  @GerritConfig(name = "groups.includeExternalUsersInRegisteredUsersGroup", value = "false")
  @Test
  public void externalUser_isNotContainedInRegisteredUsersIfNotConfigured() {
    ExternalUser user = createUserInGroup("1", "it-department");
    assertThat(user.getEffectiveGroups().contains(REGISTERED_USERS)).isFalse();
  }

  private ImmutableList<String> getVisibleRefNames(CurrentUser user) throws Exception {
    try (Repository repo = repoManager.openRepository(project)) {
      return permissionBackend
          .user(user)
          .project(project)
          .filter(
              repo.getRefDatabase().getRefs(), repo, PermissionBackend.RefFilterOptions.defaults())
          .stream()
          .map(Ref::getName)
          .collect(toImmutableList());
    }
  }

  ExternalUser createUserInGroup(String userId, String groupId) {
    return externalUserFactory.create(
        ImmutableSet.of(),
        ImmutableSet.of(externalIdKeyFactory.parse("company-auth:" + groupId + "-" + userId)),
        PropertyMap.EMPTY);
  }
}
