Line data Source code
1 : // Copyright (C) 2021 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.flogger.FluentLogger; 18 : import com.google.gerrit.server.config.GerritServerConfig; 19 : import com.google.gerrit.server.config.SitePath; 20 : import com.google.gerrit.server.index.ReindexerAlreadyRunningException; 21 : import com.google.gerrit.server.index.VersionManager; 22 : import com.google.inject.Inject; 23 : import com.google.inject.Singleton; 24 : import java.io.IOException; 25 : import java.nio.file.Path; 26 : import java.util.Collection; 27 : import java.util.concurrent.Executor; 28 : import java.util.concurrent.ExecutorService; 29 : import org.eclipse.jgit.errors.ConfigInvalidException; 30 : import org.eclipse.jgit.lib.Config; 31 : import org.eclipse.jgit.lib.ProgressMonitor; 32 : import org.eclipse.jgit.lib.TextProgressMonitor; 33 : import org.eclipse.jgit.storage.file.FileBasedConfig; 34 : import org.eclipse.jgit.util.FS; 35 : 36 : @Singleton 37 : public class OnlineExternalIdCaseSensivityMigrator { 38 18 : private static final FluentLogger logger = FluentLogger.forEnclosingClass(); 39 : 40 : private Executor executor; 41 : private ExternalIdCaseSensitivityMigrator.Factory migratorFactory; 42 : private ExternalIds externalIds; 43 : private VersionManager versionManager; 44 : private Config globalConfig; 45 : private Path sitePath; 46 18 : private final TextProgressMonitor monitor = new TextProgressMonitor(); 47 : private boolean isUserNameCaseInsensitive; 48 : private boolean isUserNameCaseInsensitiveMigrationMode; 49 : 50 : @Inject 51 : public OnlineExternalIdCaseSensivityMigrator( 52 : @OnlineExternalIdCaseSensivityMigratiorExecutor ExecutorService executor, 53 : ExternalIdCaseSensitivityMigrator.Factory migratorFactory, 54 : ExternalIds externalIds, 55 : VersionManager versionManager, 56 : @GerritServerConfig Config globalConfig, 57 18 : @SitePath Path sitePath) { 58 18 : this.migratorFactory = migratorFactory; 59 18 : this.externalIds = externalIds; 60 18 : this.versionManager = versionManager; 61 18 : this.globalConfig = globalConfig; 62 18 : this.sitePath = sitePath; 63 18 : this.executor = executor; 64 18 : this.isUserNameCaseInsensitiveMigrationMode = 65 18 : globalConfig.getBoolean("auth", "userNameCaseInsensitiveMigrationMode", false); 66 18 : this.isUserNameCaseInsensitive = 67 18 : globalConfig.getBoolean("auth", "userNameCaseInsensitive", false); 68 18 : } 69 : 70 : public void migrate() { 71 1 : if (!isUserNameCaseInsensitive || !isUserNameCaseInsensitiveMigrationMode) { 72 1 : logger.atSevere().log( 73 : "External IDs online migration requires auth.userNameCaseInsensitive and" 74 : + " auth.userNameCaseInsensitiveMigrationMode to be set to true. Skipping" 75 : + " migration!"); 76 1 : return; 77 : } 78 1 : executor.execute( 79 : () -> { 80 : try { 81 1 : Collection<ExternalId> todo = externalIds.all(); 82 : try { 83 1 : monitor.beginTask("Converting external ID note names", todo.size()); 84 1 : migratorFactory 85 1 : .create(isUserNameCaseInsensitive, false) 86 1 : .migrate(todo, () -> monitor.update(1)); 87 : } finally { 88 1 : monitor.endTask(); 89 : } 90 : try { 91 1 : updateGerritConfig(); 92 1 : monitor.beginTask("Reindex accounts", ProgressMonitor.UNKNOWN); 93 1 : versionManager.startReindexer("accounts", true); 94 : } finally { 95 1 : monitor.endTask(); 96 : } 97 1 : logger.atInfo().log("External IDs migration completed!"); 98 0 : } catch (IOException | ConfigInvalidException e) { 99 0 : logger.atSevere().withCause(e).log( 100 0 : "Exception during the external ids migration, cause %s", e.getMessage()); 101 0 : } catch (ReindexerAlreadyRunningException e) { 102 0 : logger.atSevere().log("Failed to reindex external ids: %s", e.getMessage()); 103 1 : } 104 1 : }); 105 1 : } 106 : 107 : private void updateGerritConfig() throws IOException, ConfigInvalidException { 108 1 : logger.atInfo().log( 109 : "Setting auth.userNameCaseInsensitiveMigrationMode to false in gerrit.config."); 110 : 111 1 : FileBasedConfig config = 112 : new FileBasedConfig( 113 1 : globalConfig, sitePath.resolve("etc/gerrit.config").toFile(), FS.DETECTED); 114 1 : config.load(); 115 1 : config.setBoolean("auth", null, "userNameCaseInsensitiveMigrationMode", false); 116 : 117 1 : config.save(); 118 1 : } 119 : }