LCOV - code coverage report
Current view: top level - pgm - LocalUsernamesToLowerCase.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 0 64 0.0 %
Date: 2022-11-19 15:00:39 Functions: 0 10 0.0 %

          Line data    Source code
       1             : // Copyright (C) 2011 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.pgm;
      16             : 
      17             : import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_GERRIT;
      18             : 
      19             : import com.google.gerrit.exceptions.DuplicateKeyException;
      20             : import com.google.gerrit.extensions.config.FactoryModule;
      21             : import com.google.gerrit.lifecycle.LifecycleManager;
      22             : import com.google.gerrit.pgm.util.SiteProgram;
      23             : import com.google.gerrit.server.account.externalids.DisabledExternalIdCache;
      24             : import com.google.gerrit.server.account.externalids.ExternalId;
      25             : import com.google.gerrit.server.account.externalids.ExternalIdFactory;
      26             : import com.google.gerrit.server.account.externalids.ExternalIdNotes;
      27             : import com.google.gerrit.server.account.externalids.ExternalIds;
      28             : import com.google.gerrit.server.config.AllUsersName;
      29             : import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
      30             : import com.google.gerrit.server.git.GitRepositoryManager;
      31             : import com.google.gerrit.server.git.meta.MetaDataUpdate;
      32             : import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
      33             : import com.google.gerrit.server.schema.NoteDbSchemaVersionCheck;
      34             : import com.google.inject.Inject;
      35             : import com.google.inject.Injector;
      36             : import com.google.inject.Provider;
      37             : import java.io.IOException;
      38             : import java.util.Collection;
      39             : import java.util.Locale;
      40             : import java.util.Optional;
      41             : import org.apache.commons.lang3.StringUtils;
      42             : import org.eclipse.jgit.errors.ConfigInvalidException;
      43             : import org.eclipse.jgit.lib.ProgressMonitor;
      44             : import org.eclipse.jgit.lib.Repository;
      45             : import org.eclipse.jgit.lib.TextProgressMonitor;
      46             : 
      47             : /** Converts the local username for all accounts to lower case */
      48           0 : public class LocalUsernamesToLowerCase extends SiteProgram {
      49           0 :   private final LifecycleManager manager = new LifecycleManager();
      50           0 :   private final TextProgressMonitor monitor = new TextProgressMonitor();
      51             : 
      52             :   @Inject private GitRepositoryManager repoManager;
      53             :   @Inject private AllUsersName allUsersName;
      54             :   @Inject private Provider<MetaDataUpdate.Server> metaDataUpdateServerFactory;
      55             :   @Inject private ExternalIdNotes.FactoryNoReindex externalIdNotesFactory;
      56             :   @Inject private ExternalIdFactory externalIdFactory;
      57             :   @Inject private ExternalIds externalIds;
      58             : 
      59             :   @Override
      60             :   public int run() throws Exception {
      61           0 :     Injector dbInjector = createDbInjector();
      62           0 :     manager.add(dbInjector, dbInjector.createChildInjector(NoteDbSchemaVersionCheck.module()));
      63           0 :     manager.start();
      64           0 :     dbInjector
      65           0 :         .createChildInjector(
      66           0 :             new FactoryModule() {
      67             :               @Override
      68             :               protected void configure() {
      69           0 :                 bind(GitReferenceUpdated.class).toInstance(GitReferenceUpdated.DISABLED);
      70           0 :                 factory(MetaDataUpdate.InternalFactory.class);
      71             : 
      72             :                 // The LocalUsernamesToLowerCase program needs to access all external IDs only
      73             :                 // once to update them. After the update they are not accessed again. Hence the
      74             :                 // LocalUsernamesToLowerCase program doesn't benefit from caching external IDs and
      75             :                 // the external ID cache can be disabled.
      76           0 :                 install(DisabledExternalIdCache.module());
      77           0 :               }
      78             :             })
      79           0 :         .injectMembers(this);
      80             : 
      81           0 :     Collection<ExternalId> todo = externalIds.all();
      82           0 :     monitor.beginTask("Converting local usernames", todo.size());
      83             : 
      84           0 :     try (Repository repo = repoManager.openRepository(allUsersName)) {
      85           0 :       ExternalIdNotes extIdNotes = externalIdNotesFactory.load(repo);
      86           0 :       for (ExternalId extId : todo) {
      87           0 :         convertLocalUserToLowerCase(extIdNotes, extId);
      88           0 :         monitor.update(1);
      89           0 :       }
      90           0 :       try (MetaDataUpdate metaDataUpdate = metaDataUpdateServerFactory.get().create(allUsersName)) {
      91           0 :         metaDataUpdate.setMessage("Convert local usernames to lower case");
      92           0 :         extIdNotes.commit(metaDataUpdate);
      93             :       }
      94             :     }
      95             : 
      96           0 :     monitor.endTask();
      97             : 
      98           0 :     int exitCode = reindexAccounts();
      99           0 :     manager.stop();
     100           0 :     return exitCode;
     101             :   }
     102             : 
     103             :   private void convertLocalUserToLowerCase(ExternalIdNotes extIdNotes, ExternalId extId)
     104             :       throws DuplicateKeyException, IOException {
     105           0 :     if (extId.isScheme(SCHEME_GERRIT)) {
     106           0 :       String localUser = extId.key().id();
     107           0 :       String localUserLowerCase = localUser.toLowerCase(Locale.US);
     108           0 :       if (!localUser.equals(localUserLowerCase)) {
     109           0 :         ExternalId extIdLowerCase =
     110           0 :             externalIdFactory.create(
     111             :                 SCHEME_GERRIT,
     112             :                 localUserLowerCase,
     113           0 :                 extId.accountId(),
     114           0 :                 extId.email(),
     115           0 :                 extId.password());
     116           0 :         replaceIfNotExists(extIdNotes, extId, extIdLowerCase);
     117             :       }
     118             :     }
     119           0 :   }
     120             : 
     121             :   private void replaceIfNotExists(
     122             :       ExternalIdNotes extIdNotes, ExternalId extId, ExternalId extIdLowerCase) throws IOException {
     123             :     try {
     124           0 :       Optional<ExternalId> existingExternalId =
     125             :           extIdNotes
     126           0 :               .get(extIdLowerCase.key())
     127           0 :               .filter(eid -> eid.accountId().equals(extIdLowerCase.accountId()))
     128           0 :               .filter(eid -> StringUtils.equalsIgnoreCase(eid.email(), extId.email()))
     129           0 :               .filter(eid -> StringUtils.equalsIgnoreCase(eid.password(), extId.password()));
     130           0 :       if (existingExternalId.isPresent()) {
     131           0 :         System.err.println(
     132             :             "WARNING: external-id "
     133             :                 + extIdLowerCase
     134             :                 + " already exists with the same account-id "
     135           0 :                 + extId.accountId()
     136             :                 + " :"
     137             :                 + "removing the duplicate external-id "
     138           0 :                 + extId.key());
     139           0 :         extIdNotes.delete(extId);
     140             :       } else {
     141           0 :         extIdNotes.replace(extId, extIdLowerCase);
     142             :       }
     143           0 :     } catch (ConfigInvalidException e) {
     144           0 :       throw new IOException(
     145             :           "Unable to parse external id definition when looking for current external-id "
     146             :               + extIdLowerCase,
     147             :           e);
     148           0 :     }
     149           0 :   }
     150             : 
     151             :   private int reindexAccounts() throws Exception {
     152           0 :     monitor.beginTask("Reindex accounts", ProgressMonitor.UNKNOWN);
     153           0 :     String[] reindexArgs = {
     154           0 :       "--site-path", getSitePath().toString(), "--index", AccountSchemaDefinitions.NAME
     155             :     };
     156           0 :     System.out.println("Migration complete, reindexing accounts with:");
     157           0 :     System.out.println("  reindex " + String.join(" ", reindexArgs));
     158           0 :     Reindex reindexPgm = new Reindex();
     159           0 :     int exitCode = reindexPgm.main(reindexArgs);
     160           0 :     monitor.endTask();
     161           0 :     return exitCode;
     162             :   }
     163             : }

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