LCOV - code coverage report
Current view: top level - server/account/externalids - ExternalIdReader.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 38 51 74.5 %
Date: 2022-11-19 15:00:39 Functions: 8 10 80.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.account.externalids;
      16             : 
      17             : import com.google.common.annotations.VisibleForTesting;
      18             : import com.google.common.collect.ImmutableSet;
      19             : import com.google.gerrit.common.Nullable;
      20             : import com.google.gerrit.entities.RefNames;
      21             : import com.google.gerrit.metrics.Description;
      22             : import com.google.gerrit.metrics.Description.Units;
      23             : import com.google.gerrit.metrics.MetricMaker;
      24             : import com.google.gerrit.metrics.Timer0;
      25             : import com.google.gerrit.server.config.AllUsersName;
      26             : import com.google.gerrit.server.config.AuthConfig;
      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.Optional;
      32             : import org.eclipse.jgit.errors.ConfigInvalidException;
      33             : import org.eclipse.jgit.lib.ObjectId;
      34             : import org.eclipse.jgit.lib.Ref;
      35             : import org.eclipse.jgit.lib.Repository;
      36             : import org.eclipse.jgit.notes.NoteMap;
      37             : import org.eclipse.jgit.revwalk.RevWalk;
      38             : 
      39             : /**
      40             :  * Class to read external IDs from NoteDb.
      41             :  *
      42             :  * <p>In NoteDb external IDs are stored in the All-Users repository in a Git Notes branch called
      43             :  * refs/meta/external-ids where the sha1 of the external ID is used as note name. Each note content
      44             :  * is a git config file that contains an external ID. It has exactly one externalId subsection with
      45             :  * an accountId and optionally email and password:
      46             :  *
      47             :  * <pre>
      48             :  * [externalId "username:jdoe"]
      49             :  *   accountId = 1003407
      50             :  *   email = jdoe@example.com
      51             :  *   password = bcrypt:4:LCbmSBDivK/hhGVQMfkDpA==:XcWn0pKYSVU/UJgOvhidkEtmqCp6oKB7
      52             :  * </pre>
      53             :  */
      54             : @Singleton
      55             : public class ExternalIdReader {
      56             :   public static ObjectId readRevision(Repository repo) throws IOException {
      57         151 :     Ref ref = repo.exactRef(RefNames.REFS_EXTERNAL_IDS);
      58         151 :     return ref != null ? ref.getObjectId() : ObjectId.zeroId();
      59             :   }
      60             : 
      61             :   public static NoteMap readNoteMap(RevWalk rw, ObjectId rev) throws IOException {
      62           2 :     if (!rev.equals(ObjectId.zeroId())) {
      63           2 :       return NoteMap.read(rw.getObjectReader(), rw.parseCommit(rev));
      64             :     }
      65           0 :     return NoteMap.newEmptyMap();
      66             :   }
      67             : 
      68             :   private final GitRepositoryManager repoManager;
      69             :   private final AllUsersName allUsersName;
      70         152 :   private boolean failOnLoad = false;
      71             :   private final Timer0 readAllLatency;
      72             :   private final Timer0 readSingleLatency;
      73             :   private final ExternalIdFactory externalIdFactory;
      74             :   private final AuthConfig authConfig;
      75             : 
      76             :   @Inject
      77             :   ExternalIdReader(
      78             :       GitRepositoryManager repoManager,
      79             :       AllUsersName allUsersName,
      80             :       MetricMaker metricMaker,
      81             :       ExternalIdFactory externalIdFactory,
      82         152 :       AuthConfig authConfig) {
      83         152 :     this.repoManager = repoManager;
      84         152 :     this.allUsersName = allUsersName;
      85         152 :     this.readAllLatency =
      86         152 :         metricMaker.newTimer(
      87             :             "notedb/read_all_external_ids_latency",
      88             :             new Description("Latency for reading all external IDs from NoteDb.")
      89         152 :                 .setCumulative()
      90         152 :                 .setUnit(Units.MILLISECONDS));
      91         152 :     this.readSingleLatency =
      92         152 :         metricMaker.newTimer(
      93             :             "notedb/read_single_external_id_latency",
      94             :             new Description("Latency for reading a single external ID from NoteDb.")
      95         152 :                 .setCumulative()
      96         152 :                 .setUnit(Units.MILLISECONDS));
      97         152 :     this.externalIdFactory = externalIdFactory;
      98         152 :     this.authConfig = authConfig;
      99         152 :   }
     100             : 
     101             :   @VisibleForTesting
     102             :   public void setFailOnLoad(boolean failOnLoad) {
     103           1 :     this.failOnLoad = failOnLoad;
     104           1 :   }
     105             : 
     106             :   public void checkReadEnabled() throws IOException {
     107         151 :     if (failOnLoad) {
     108           1 :       throw new IOException("Reading from external IDs is disabled");
     109             :     }
     110         151 :   }
     111             : 
     112             :   ObjectId readRevision() throws IOException {
     113         151 :     try (Repository repo = repoManager.openRepository(allUsersName)) {
     114         151 :       return readRevision(repo);
     115             :     }
     116             :   }
     117             : 
     118             :   /** Reads and returns all external IDs. */
     119             :   ImmutableSet<ExternalId> all() throws IOException, ConfigInvalidException {
     120           3 :     checkReadEnabled();
     121             : 
     122           3 :     try (Timer0.Context ctx = readAllLatency.start();
     123           3 :         Repository repo = repoManager.openRepository(allUsersName)) {
     124           3 :       return ExternalIdNotes.loadReadOnly(
     125             :               allUsersName,
     126             :               repo,
     127             :               null,
     128             :               externalIdFactory,
     129           3 :               authConfig.isUserNameCaseInsensitiveMigrationMode())
     130           3 :           .all();
     131             :     }
     132             :   }
     133             : 
     134             :   /**
     135             :    * Reads and returns all external IDs from the specified revision of the {@code
     136             :    * refs/meta/external-ids} branch.
     137             :    *
     138             :    * @param rev the revision from which the external IDs should be read, if {@code null} the
     139             :    *     external IDs are read from the current tip, if {@link ObjectId#zeroId()} it's assumed that
     140             :    *     the {@code refs/meta/external-ids} branch doesn't exist and the loaded external IDs will be
     141             :    *     empty
     142             :    * @return all external IDs that were read from the specified revision
     143             :    */
     144             :   ImmutableSet<ExternalId> all(@Nullable ObjectId rev) throws IOException, ConfigInvalidException {
     145         151 :     checkReadEnabled();
     146             : 
     147         151 :     try (Timer0.Context ctx = readAllLatency.start();
     148         151 :         Repository repo = repoManager.openRepository(allUsersName)) {
     149         151 :       return ExternalIdNotes.loadReadOnly(
     150             :               allUsersName,
     151             :               repo,
     152             :               rev,
     153             :               externalIdFactory,
     154         151 :               authConfig.isUserNameCaseInsensitiveMigrationMode())
     155         151 :           .all();
     156             :     }
     157             :   }
     158             : 
     159             :   /** Reads and returns the specified external ID. */
     160             :   Optional<ExternalId> get(ExternalId.Key key) throws IOException, ConfigInvalidException {
     161           0 :     checkReadEnabled();
     162             : 
     163           0 :     try (Timer0.Context ctx = readSingleLatency.start();
     164           0 :         Repository repo = repoManager.openRepository(allUsersName)) {
     165           0 :       return ExternalIdNotes.loadReadOnly(
     166             :               allUsersName,
     167             :               repo,
     168             :               null,
     169             :               externalIdFactory,
     170           0 :               authConfig.isUserNameCaseInsensitiveMigrationMode())
     171           0 :           .get(key);
     172             :     }
     173             :   }
     174             : 
     175             :   /** Reads and returns the specified external ID from the given revision. */
     176             :   Optional<ExternalId> get(ExternalId.Key key, ObjectId rev)
     177             :       throws IOException, ConfigInvalidException {
     178           0 :     checkReadEnabled();
     179             : 
     180           0 :     try (Timer0.Context ctx = readSingleLatency.start();
     181           0 :         Repository repo = repoManager.openRepository(allUsersName)) {
     182           0 :       return ExternalIdNotes.loadReadOnly(
     183             :               allUsersName,
     184             :               repo,
     185             :               rev,
     186             :               externalIdFactory,
     187           0 :               authConfig.isUserNameCaseInsensitiveMigrationMode())
     188           0 :           .get(key);
     189             :     }
     190             :   }
     191             : }

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