LCOV - code coverage report
Current view: top level - server/group/db - Groups.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 33 36 91.7 %
Date: 2022-11-19 15:00:39 Functions: 12 12 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2017 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server.group.db;
      16             : 
      17             : import com.google.common.collect.ImmutableList;
      18             : import com.google.common.collect.ImmutableSet;
      19             : import com.google.common.flogger.FluentLogger;
      20             : import com.google.gerrit.common.Nullable;
      21             : import com.google.gerrit.entities.AccountGroup;
      22             : import com.google.gerrit.entities.AccountGroupByIdAudit;
      23             : import com.google.gerrit.entities.AccountGroupMemberAudit;
      24             : import com.google.gerrit.entities.GroupReference;
      25             : import com.google.gerrit.entities.InternalGroup;
      26             : import com.google.gerrit.server.config.AllUsersName;
      27             : import com.google.gerrit.server.git.GitRepositoryManager;
      28             : import com.google.inject.Inject;
      29             : import com.google.inject.Singleton;
      30             : import java.io.IOException;
      31             : import java.util.List;
      32             : import java.util.Optional;
      33             : import java.util.stream.Stream;
      34             : import org.eclipse.jgit.errors.ConfigInvalidException;
      35             : import org.eclipse.jgit.lib.ObjectId;
      36             : import org.eclipse.jgit.lib.Ref;
      37             : import org.eclipse.jgit.lib.Repository;
      38             : 
      39             : /**
      40             :  * A database accessor for read calls related to groups.
      41             :  *
      42             :  * <p>All calls which read group related details from the database are gathered here. Other classes
      43             :  * should always use this class instead of accessing the database directly. There are a few
      44             :  * exceptions though: schema classes, wrapper classes, and classes executed during init. The latter
      45             :  * ones should use {@code GroupsOnInit} instead.
      46             :  *
      47             :  * <p>Most callers should not need to read groups directly from the database; they should use the
      48             :  * {@link com.google.gerrit.server.account.GroupCache GroupCache} instead.
      49             :  *
      50             :  * <p>If not explicitly stated, all methods of this class refer to <em>internal</em> groups.
      51             :  */
      52             : @Singleton
      53             : public class Groups {
      54         152 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      55             : 
      56             :   private final GitRepositoryManager repoManager;
      57             :   private final AllUsersName allUsersName;
      58             :   private final AuditLogReader auditLogReader;
      59             : 
      60             :   @Inject
      61             :   public Groups(
      62         152 :       GitRepositoryManager repoManager, AllUsersName allUsersName, AuditLogReader auditLogReader) {
      63         152 :     this.repoManager = repoManager;
      64         152 :     this.allUsersName = allUsersName;
      65         152 :     this.auditLogReader = auditLogReader;
      66         152 :   }
      67             : 
      68             :   /**
      69             :    * Returns the {@code InternalGroup} for the specified UUID if it exists.
      70             :    *
      71             :    * @param groupUuid the UUID of the group
      72             :    * @return the found {@code InternalGroup} if it exists, or else an empty {@code Optional}
      73             :    * @throws IOException if the group couldn't be retrieved from NoteDb
      74             :    * @throws ConfigInvalidException if the group couldn't be retrieved from NoteDb
      75             :    */
      76             :   public Optional<InternalGroup> getGroup(AccountGroup.UUID groupUuid)
      77             :       throws IOException, ConfigInvalidException {
      78           4 :     try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
      79           4 :       return getGroupFromNoteDb(allUsersName, allUsersRepo, groupUuid);
      80             :     }
      81             :   }
      82             : 
      83             :   /**
      84             :    * Returns the {@code InternalGroup} for the specified UUID and groupRefObjectId
      85             :    *
      86             :    * @param groupUuid the UUID of the group
      87             :    * @param groupRefObjectId the ref revision of this group
      88             :    * @return the found {@code InternalGroup} if it exists, or else an empty {@code Optional}
      89             :    * @throws IOException if the group couldn't be retrieved from NoteDb
      90             :    * @throws ConfigInvalidException if the group couldn't be retrieved from NoteDb
      91             :    */
      92             :   public Optional<InternalGroup> getGroup(
      93             :       AccountGroup.UUID groupUuid, @Nullable ObjectId groupRefObjectId)
      94             :       throws IOException, ConfigInvalidException {
      95         151 :     try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
      96         151 :       return getGroupFromNoteDb(allUsersName, allUsersRepo, groupUuid, groupRefObjectId);
      97             :     }
      98             :   }
      99             : 
     100             :   /**
     101             :    * Loads an internal group from NoteDb using the group UUID. This method returns the latest state
     102             :    * of the internal group.
     103             :    */
     104             :   private static Optional<InternalGroup> getGroupFromNoteDb(
     105             :       AllUsersName allUsersName, Repository allUsersRepository, AccountGroup.UUID groupUuid)
     106             :       throws IOException, ConfigInvalidException {
     107           4 :     return getGroupFromNoteDb(allUsersName, allUsersRepository, groupUuid, null);
     108             :   }
     109             : 
     110             :   /**
     111             :    * Loads an internal group from NoteDb at the revision provided as {@link ObjectId}. This method
     112             :    * is used to get a specific state of this group.
     113             :    */
     114             :   private static Optional<InternalGroup> getGroupFromNoteDb(
     115             :       AllUsersName allUsersName,
     116             :       Repository allUsersRepository,
     117             :       AccountGroup.UUID uuid,
     118             :       @Nullable ObjectId groupRefObjectId)
     119             :       throws IOException, ConfigInvalidException {
     120         151 :     GroupConfig groupConfig =
     121         151 :         GroupConfig.loadForGroup(allUsersName, allUsersRepository, uuid, groupRefObjectId);
     122         151 :     Optional<InternalGroup> loadedGroup = groupConfig.getLoadedGroup();
     123         151 :     if (loadedGroup.isPresent()) {
     124             :       // Check consistency with group name notes.
     125         151 :       GroupsNoteDbConsistencyChecker.ensureConsistentWithGroupNameNotes(
     126         151 :           allUsersRepository, loadedGroup.get());
     127             :     }
     128         151 :     return loadedGroup;
     129             :   }
     130             : 
     131             :   /**
     132             :    * Returns {@code GroupReference}s for all internal groups.
     133             :    *
     134             :    * @return a stream of the {@code GroupReference}s of all internal groups
     135             :    * @throws IOException if an error occurs while reading from NoteDb
     136             :    * @throws ConfigInvalidException if the data in NoteDb is in an incorrect format
     137             :    */
     138             :   public Stream<GroupReference> getAllGroupReferences() throws IOException, ConfigInvalidException {
     139         144 :     try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
     140         144 :       return GroupNameNotes.loadAllGroups(allUsersRepo).stream();
     141             :     }
     142             :   }
     143             : 
     144             :   /**
     145             :    * Returns all known external groups. External groups are 'known' when they are specified as a
     146             :    * subgroup of an internal group.
     147             :    *
     148             :    * @param internalGroupsRefs contains a list of all groups refs that we should inspect
     149             :    * @return a stream of the UUIDs of the known external groups
     150             :    * @throws IOException if an error occurs while reading from NoteDb
     151             :    * @throws ConfigInvalidException if the data in NoteDb is in an incorrect format
     152             :    */
     153             :   public Stream<AccountGroup.UUID> getExternalGroups(ImmutableList<Ref> internalGroupsRefs)
     154             :       throws IOException, ConfigInvalidException {
     155          20 :     try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
     156          20 :       return getExternalGroupsFromNoteDb(allUsersName, allUsersRepo, internalGroupsRefs);
     157             :     }
     158             :   }
     159             : 
     160             :   private static Stream<AccountGroup.UUID> getExternalGroupsFromNoteDb(
     161             :       AllUsersName allUsersName, Repository allUsersRepo, ImmutableList<Ref> internalGroupsRefs)
     162             :       throws IOException, ConfigInvalidException {
     163          20 :     ImmutableSet.Builder<AccountGroup.UUID> allSubgroups = ImmutableSet.builder();
     164          20 :     for (Ref internalGroupRef : internalGroupsRefs) {
     165          20 :       AccountGroup.UUID uuid = AccountGroup.UUID.fromRef(internalGroupRef.getName());
     166          20 :       if (uuid == null) {
     167           0 :         logger.atWarning().log(
     168           0 :             "Failed to get the group UUID from ref: %s", internalGroupRef.getName());
     169           0 :         continue;
     170             :       }
     171          20 :       Optional<InternalGroup> group =
     172          20 :           getGroupFromNoteDb(allUsersName, allUsersRepo, uuid, internalGroupRef.getObjectId());
     173          20 :       group.map(InternalGroup::getSubgroups).ifPresent(allSubgroups::addAll);
     174          20 :     }
     175          20 :     return allSubgroups.build().stream().filter(groupUuid -> !groupUuid.isInternalGroup());
     176             :   }
     177             : 
     178             :   /**
     179             :    * Returns the membership audit records for a given group.
     180             :    *
     181             :    * @param allUsersRepo All-Users repository.
     182             :    * @param groupUuid the UUID of the group
     183             :    * @return the audit records, in arbitrary order; empty if the group does not exist
     184             :    * @throws IOException if an error occurs while reading from NoteDb
     185             :    * @throws ConfigInvalidException if the group couldn't be retrieved from NoteDb
     186             :    */
     187             :   public List<AccountGroupMemberAudit> getMembersAudit(
     188             :       Repository allUsersRepo, AccountGroup.UUID groupUuid)
     189             :       throws IOException, ConfigInvalidException {
     190           2 :     return auditLogReader.getMembersAudit(allUsersRepo, groupUuid);
     191             :   }
     192             : 
     193             :   /**
     194             :    * Returns the subgroup audit records for a given group.
     195             :    *
     196             :    * @param repo All-Users repository.
     197             :    * @param groupUuid the UUID of the group
     198             :    * @return the audit records, in arbitrary order; empty if the group does not exist
     199             :    * @throws IOException if an error occurs while reading from NoteDb
     200             :    * @throws ConfigInvalidException if the group couldn't be retrieved from NoteDb
     201             :    */
     202             :   public List<AccountGroupByIdAudit> getSubgroupsAudit(Repository repo, AccountGroup.UUID groupUuid)
     203             :       throws IOException, ConfigInvalidException {
     204           2 :     return auditLogReader.getSubgroupsAudit(repo, groupUuid);
     205             :   }
     206             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750