diff --git a/core/src/main/java/hudson/model/User.java b/core/src/main/java/hudson/model/User.java index a3ee3abffb9c..d6b0a4a25ce8 100644 --- a/core/src/main/java/hudson/model/User.java +++ b/core/src/main/java/hudson/model/User.java @@ -52,12 +52,15 @@ import jakarta.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -67,12 +70,14 @@ import java.util.function.Predicate; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Pattern; import jenkins.model.IdStrategy; import jenkins.model.Jenkins; import jenkins.model.Loadable; import jenkins.model.ModelObjectWithContextMenu; import jenkins.scm.RunWithSCM; import jenkins.search.SearchGroup; +import jenkins.security.HMACConfidentialKey; import jenkins.security.ImpersonatingUserDetailsService2; import jenkins.security.LastGrantedAuthoritiesProperty; import jenkins.security.UserDetailsCache; @@ -174,7 +179,7 @@ public class User extends AbstractModelObject implements AccessControlled, Descr @SuppressFBWarnings(value = "SS_SHOULD_BE_STATIC", justification = "Reserved for future use") private final int version = 10; // Not currently used, but it may be helpful in the future to store a version. - private String id; + String id; private volatile String fullName; private volatile String description; @@ -185,6 +190,8 @@ public class User extends AbstractModelObject implements AccessControlled, Descr XSTREAM.alias("user", User.class); } + private User() {} + private User(String id, String fullName) { this.id = id; this.fullName = fullName; @@ -199,6 +206,10 @@ public void load() { private void load(String userId) { clearExistingProperties(); loadFromUserConfigFile(userId); + fixUpAfterLoad(); + } + + private void fixUpAfterLoad() { removeNullsThatFailedToLoad(); allocateDefaultPropertyInstancesAsNeeded(); setUserToProperties(); @@ -225,9 +236,10 @@ private void removeNullsThatFailedToLoad() { } private void loadFromUserConfigFile(String userId) { + AllUsers.getInstance().migrateUserIdMapper(); XmlFile config = getConfigFile(); try { - if (config != null && config.exists()) { + if (config.exists()) { config.unmarshal(this); this.id = userId; } @@ -241,8 +253,7 @@ private void clearExistingProperties() { } private XmlFile getConfigFile() { - File existingUserFolder = getExistingUserFolder(); - return existingUserFolder == null ? null : new XmlFile(XSTREAM, new File(existingUserFolder, CONFIG_XML)); + return new XmlFile(XSTREAM, new File(getUserFolderFor(id), CONFIG_XML)); } /** @@ -571,10 +582,10 @@ public void doSubmitDescription(StaplerRequest2 req, StaplerResponse2 rsp) throw */ private static @Nullable User getOrCreateById(@NonNull String id, @NonNull String fullName, boolean create) { User u = AllUsers.get(id); - if (u == null && (create || UserIdMapper.getInstance().isMapped(id))) { + if (u == null && create) { u = new User(id, fullName); AllUsers.put(id, u); - if (!id.equals(fullName) && !UserIdMapper.getInstance().isMapped(id)) { + if (!id.equals(fullName)) { try { u.save(); } catch (IOException x) { @@ -691,7 +702,6 @@ public void doSubmitDescription(StaplerRequest2 req, StaplerResponse2 rsp) throw */ @Restricted(Beta.class) public static void reload() throws IOException { - UserIdMapper.getInstance().reload(); AllUsers.reload(); } @@ -708,6 +718,32 @@ public static void rekey() { or greater issues in the realm change, could affect currently logged in users and even the user making the change. */ try { + var subdirectories = getRootDir().listFiles(); + if (subdirectories != null) { + for (var oldDirectory : subdirectories) { + var dirName = oldDirectory.getName(); + if (!HASHED_DIRNAMES.matcher(dirName).matches()) { + continue; + } + var xml = new XmlFile(XSTREAM, new File(oldDirectory, CONFIG_XML)); + if (!xml.exists()) { + continue; + } + try { + var user = (User) xml.read(); + if (user.id == null) { + continue; + } + var newDirectory = getUserFolderFor(user.id); + if (!oldDirectory.equals(newDirectory)) { + Files.move(oldDirectory.toPath(), newDirectory.toPath(), StandardCopyOption.REPLACE_EXISTING); + LOGGER.info(() -> "migrated " + oldDirectory + " to " + newDirectory); + } + } catch (Exception x) { + LOGGER.log(Level.WARNING, "failed to migrate " + xml, x); + } + } + } reload(); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Failed to perform rekey operation.", e); @@ -777,17 +813,9 @@ public static void clear() { if (ExtensionList.lookup(AllUsers.class).isEmpty()) { return; } - UserIdMapper.getInstance().clear(); AllUsers.clear(); } - private static File getConfigFileFor(String id) { - return new File(getUserFolderFor(id), "config.xml"); - } - - private static File getUserFolderFor(String id) { - return new File(getRootDir(), idStrategy().filenameOf(id)); - } /** * Returns the folder that store all the user information. * Useful for plugins to save a user-specific file aside the config.xml. @@ -799,11 +827,8 @@ private static File getUserFolderFor(String id) { */ public @CheckForNull File getUserFolder() { - return getExistingUserFolder(); - } - - private @CheckForNull File getExistingUserFolder() { - return UserIdMapper.getInstance().getDirectory(id); + var d = getUserFolderFor(id); + return d.isDirectory() ? d : null; } /** @@ -813,6 +838,21 @@ static File getRootDir() { return new File(Jenkins.get().getRootDir(), "users"); } + private static final int PREFIX_MAX = 14; + private static final Pattern DISALLOWED_PREFIX_CHARS = Pattern.compile("[^A-Za-z0-9]"); + static final Pattern HASHED_DIRNAMES = Pattern.compile("[a-z0-9]{0," + PREFIX_MAX + "}_[a-f0-9]{64}"); + private static final HMACConfidentialKey DIRNAMES = new HMACConfidentialKey(User.class, "DIRNAMES"); + + private static String getUserFolderNameFor(String id) { + var fullPrefix = DISALLOWED_PREFIX_CHARS.matcher(id).replaceAll("").toLowerCase(Locale.ROOT); + return (fullPrefix.length() > PREFIX_MAX ? fullPrefix.substring(0, PREFIX_MAX) : fullPrefix) + '_' + DIRNAMES.mac(idStrategy().keyFor(id)); + } + + @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "sanitized") + static File getUserFolderFor(String id) { + return new File(getRootDir(), getUserFolderNameFor(id)); + } + /** * Is the ID allowed? Some are prohibited for security reasons. See SECURITY-166. *

@@ -852,19 +892,11 @@ public synchronized void save() throws IOException { if (BulkChange.contains(this)) { return; } - XmlFile xmlFile = new XmlFile(XSTREAM, constructUserConfigFile()); + XmlFile xmlFile = getConfigFile(); xmlFile.write(this); SaveableListener.fireOnChange(this, xmlFile); } - private File constructUserConfigFile() throws IOException { - return new File(putUserFolderIfAbsent(), CONFIG_XML); - } - - private File putUserFolderIfAbsent() throws IOException { - return UserIdMapper.getInstance().putIfAbsent(id, true); - } - /** * Deletes the data directory and removes this user from Hudson. * @@ -872,19 +904,11 @@ private File putUserFolderIfAbsent() throws IOException { */ public void delete() throws IOException { String idKey = idStrategy().keyFor(id); - File existingUserFolder = getExistingUserFolder(); - UserIdMapper.getInstance().remove(id); AllUsers.remove(id); - deleteExistingUserFolder(existingUserFolder); + Util.deleteRecursive(getUserFolderFor(id)); UserDetailsCache.get().invalidate(idKey); } - private void deleteExistingUserFolder(File existingUserFolder) throws IOException { - if (existingUserFolder != null && existingUserFolder.exists()) { - Util.deleteRecursive(existingUserFolder); - } - } - /** * Exposed remote API. */ @@ -947,7 +971,7 @@ public ACL getACL() { public boolean canDelete() { final IdStrategy strategy = idStrategy(); return hasPermission(Jenkins.ADMINISTER) && !strategy.equals(id, Jenkins.getAuthentication2().getName()) - && UserIdMapper.getInstance().isMapped(id); + && getUserFolder() != null; } /** @@ -1074,14 +1098,68 @@ private Object readResolve() { @Restricted(NoExternalUse.class) public static final class AllUsers { + private boolean migratedUserIdMapper; private final ConcurrentMap byName = new ConcurrentHashMap<>(); + @SuppressWarnings("deprecation") + synchronized void migrateUserIdMapper() { + if (!migratedUserIdMapper) { + try { + UserIdMapper.migrate(); + } catch (IOException x) { + LOGGER.log(Level.WARNING, null, x); + } + migratedUserIdMapper = true; + } + } + @Initializer(after = InitMilestone.JOB_CONFIG_ADAPTED) - public static void scanAll() { - for (String userId : UserIdMapper.getInstance().getConvertedUserIds()) { - User user = new User(userId, userId); - getInstance().byName.putIfAbsent(idStrategy().keyFor(userId), user); + public static void scanAll() throws IOException { + DIRNAMES.createMac(); // force the key to be saved during startup + var instance = getInstance(); + instance.migrateUserIdMapper(); + var subdirectories = getRootDir().listFiles(); + if (subdirectories == null) { + return; + } + var byName = instance.byName; + var idStrategy = idStrategy(); + for (var dir : subdirectories) { + var dirName = dir.getName(); + if (!HASHED_DIRNAMES.matcher(dirName).matches()) { + LOGGER.fine(() -> "ignoring unrecognized dir " + dir); + continue; + } + var xml = new XmlFile(XSTREAM, new File(dir, CONFIG_XML)); + if (!xml.exists()) { + LOGGER.fine(() -> "ignoring dir " + dir + " with no " + CONFIG_XML); + continue; + } + var user = new User(); + try { + xml.unmarshal(user); + } catch (Exception x) { + LOGGER.log(Level.WARNING, "failed to load " + xml, x); + continue; + } + if (user.id == null) { + LOGGER.warning(() -> "ignoring " + xml + " with no "); + continue; + } + var expectedFolderName = getUserFolderNameFor(user.id); + if (!dirName.equals(expectedFolderName)) { + LOGGER.warning(() -> "ignoring " + xml + " with " + user.id + " expected to be in " + expectedFolderName); + continue; + } + user.fixUpAfterLoad(); + var old = byName.put(idStrategy.keyFor(user.id), user); + if (old != null) { + LOGGER.warning(() -> "entry for " + user.id + " in " + dir + " duplicates one seen earlier for " + old.id); + } else { + LOGGER.fine(() -> "successfully loaded " + user.id + " from " + xml); + } } + LOGGER.fine(() -> "loaded " + byName.size() + " entries"); } /** @@ -1094,7 +1172,7 @@ private static AllUsers getInstance() { return ExtensionList.lookupSingleton(AllUsers.class); } - private static void reload() { + private static void reload() throws IOException { getInstance().byName.clear(); UserDetailsCache.get().invalidateAll(); scanAll(); @@ -1252,7 +1330,7 @@ public String resolveCanonicalId(String idOrFullName, Map context) { UserDetails userDetails = UserDetailsCache.get().loadUserByUsername(idOrFullName); return userDetails.getUsername(); } catch (UsernameNotFoundException x) { - LOGGER.log(Level.FINE, "not sure whether " + idOrFullName + " is a valid username or not", x); + LOGGER.log(Level.FINER, "not sure whether " + idOrFullName + " is a valid username or not", x); } catch (ExecutionException x) { LOGGER.log(Level.FINE, "could not look up " + idOrFullName, x); } finally { diff --git a/core/src/main/java/hudson/model/UserIdMapper.java b/core/src/main/java/hudson/model/UserIdMapper.java index 31be0ad6f96a..9c93d63f810c 100644 --- a/core/src/main/java/hudson/model/UserIdMapper.java +++ b/core/src/main/java/hudson/model/UserIdMapper.java @@ -24,179 +24,90 @@ package hudson.model; -import edu.umd.cs.findbugs.annotations.CheckForNull; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import hudson.Extension; -import hudson.ExtensionList; -import hudson.Util; import hudson.XmlFile; -import hudson.init.InitMilestone; -import hudson.init.Initializer; import hudson.util.XStream2; import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.util.Collections; +import java.nio.file.StandardCopyOption; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.regex.Pattern; import jenkins.model.IdStrategy; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; +/** + * @deprecated Formerly used to track which directory held each user configuration. + * Now that is deterministic based on a hash of {@link IdStrategy#keyFor}. + */ +@Deprecated @Restricted(NoExternalUse.class) -@Extension public class UserIdMapper { private static final XStream2 XSTREAM = new XStream2(); - static final String MAPPING_FILE = "users.xml"; private static final Logger LOGGER = Logger.getLogger(UserIdMapper.class.getName()); - private static final int PREFIX_MAX = 15; - private static final Pattern PREFIX_PATTERN = Pattern.compile("[^A-Za-z0-9]"); - @SuppressFBWarnings(value = "SS_SHOULD_BE_STATIC", justification = "Reserved for future use") - private final int version = 1; // Not currently used, but it may be helpful in the future to store a version. - private transient File usersDirectory; + // contrary to the name, the keys were actually IdStrategy.keyFor, not necessarily ids private Map idToDirectoryNameMap = new ConcurrentHashMap<>(); - static UserIdMapper getInstance() { - return ExtensionList.lookupSingleton(UserIdMapper.class); - } - - public UserIdMapper() { - } - - @Initializer(after = InitMilestone.PLUGINS_STARTED, before = InitMilestone.JOB_LOADED) - public File init() throws IOException { - usersDirectory = createUsersDirectoryAsNeeded(); - load(); - return usersDirectory; - } - - @CheckForNull File getDirectory(String userId) { - String directoryName = idToDirectoryNameMap.get(getIdStrategy().keyFor(userId)); - return directoryName == null ? null : new File(usersDirectory, directoryName); - } - - File putIfAbsent(String userId, boolean saveToDisk) throws IOException { - String idKey = getIdStrategy().keyFor(userId); - String directoryName = idToDirectoryNameMap.get(idKey); - File directory = null; - if (directoryName == null) { - synchronized (this) { - directoryName = idToDirectoryNameMap.get(idKey); - if (directoryName == null) { - directory = createDirectoryForNewUser(userId); - directoryName = directory.getName(); - idToDirectoryNameMap.put(idKey, directoryName); - if (saveToDisk) { - save(); + private UserIdMapper() { + } + + @SuppressWarnings("deprecation") + static void migrate() throws IOException { + var idStrategy = User.idStrategy(); + var usersDirectory = User.getRootDir(); + var data = new UserIdMapper(); + var mapperXml = new XmlFile(XSTREAM, new File(usersDirectory, "users.xml")); + if (mapperXml.exists()) { // need to migrate + // Load it, and trust ids it defines over in users/…/config.xml which UserIdMigrator neglected to resave. + LOGGER.info(() -> "migrating " + mapperXml); + mapperXml.unmarshal(data); + for (var entry : data.idToDirectoryNameMap.entrySet()) { + var idKey = entry.getKey(); + var directoryName = entry.getValue(); + try { + var oldDirectory = new File(usersDirectory, directoryName); + var userXml = new XmlFile(User.XSTREAM, new File(oldDirectory, User.CONFIG_XML)); + var user = (User) userXml.read(); + if (user.id == null || !idKey.equals(idStrategy.keyFor(user.id))) { + user.id = idKey; // not quite right but hoping for the best + userXml.write(user); } + var newDirectory = User.getUserFolderFor(user.id); + Files.move(oldDirectory.toPath(), newDirectory.toPath(), StandardCopyOption.REPLACE_EXISTING); + LOGGER.info(() -> "migrated " + oldDirectory + " to " + newDirectory); + } catch (Exception x) { + LOGGER.log(Level.WARNING, "failed to migrate " + entry, x); } } + mapperXml.delete(); } - return directory == null ? new File(usersDirectory, directoryName) : directory; - } - - boolean isMapped(String userId) { - return idToDirectoryNameMap.containsKey(getIdStrategy().keyFor(userId)); - } - - Set getConvertedUserIds() { - return Collections.unmodifiableSet(idToDirectoryNameMap.keySet()); - } - - void remove(String userId) throws IOException { - idToDirectoryNameMap.remove(getIdStrategy().keyFor(userId)); - save(); - } - - void clear() { - idToDirectoryNameMap.clear(); - } - - void reload() throws IOException { - clear(); - load(); - } - - protected IdStrategy getIdStrategy() { - return User.idStrategy(); - } - - protected File getUsersDirectory() { - return User.getRootDir(); - } - - private XmlFile getXmlConfigFile() { - File file = getConfigFile(usersDirectory); - return new XmlFile(XSTREAM, file); - } - - static File getConfigFile(File usersDirectory) { - return new File(usersDirectory, MAPPING_FILE); - } - - private File createDirectoryForNewUser(String userId) throws IOException { - try { - Path tempDirectory = Files.createTempDirectory(Util.fileToPath(usersDirectory), generatePrefix(userId)); - return tempDirectory.toFile(); - } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Error creating directory for user: " + userId, e); - throw e; - } - } - - private String generatePrefix(String userId) { - String fullPrefix = PREFIX_PATTERN.matcher(userId).replaceAll(""); - return fullPrefix.length() > PREFIX_MAX - 1 ? fullPrefix.substring(0, PREFIX_MAX - 1) + '_' : fullPrefix + '_'; - } - - private File createUsersDirectoryAsNeeded() throws IOException { - File usersDirectory = getUsersDirectory(); - if (!usersDirectory.exists()) { - try { - Files.createDirectory(usersDirectory.toPath()); - } catch (IOException e) { - LOGGER.log(Level.SEVERE, "Unable to create users directory: " + usersDirectory, e); - throw e; - } - } - return usersDirectory; - } - - synchronized void save() throws IOException { - try { - getXmlConfigFile().write(this); - } catch (IOException ioe) { - LOGGER.log(Level.WARNING, "Error saving userId mapping file.", ioe); - throw ioe; - } - } - - private void load() throws IOException { - UserIdMigrator migrator = new UserIdMigrator(usersDirectory, getIdStrategy()); - if (migrator.needsMigration()) { - try { - migrator.migrateUsers(this); - } catch (IOException ioe) { - LOGGER.log(Level.SEVERE, "Error migrating users.", ioe); - throw ioe; - } - } else { - XmlFile config = getXmlConfigFile(); - try { - config.unmarshal(this); - } catch (NoSuchFileException e) { - LOGGER.log(Level.FINE, "User id mapping file does not exist. It will be created when a user is saved."); - } catch (IOException e) { - LOGGER.log(Level.WARNING, "Failed to load " + config, e); - throw e; + // Also look for any remaining user dirs, such as those predating even UserIdMapper, or PresetData or incomplete @LocalData. + var subdirectories = usersDirectory.listFiles(); + if (subdirectories != null) { + for (var oldDirectory : subdirectories) { + if (!User.HASHED_DIRNAMES.matcher(oldDirectory.getName()).matches()) { + var userXml = new XmlFile(User.XSTREAM, new File(oldDirectory, User.CONFIG_XML)); + if (userXml.exists()) { + try { + var user = (User) userXml.read(); + var id = user.id; + if (id == null) { + id = idStrategy.idFromFilename(oldDirectory.getName()); + user.id = id; + userXml.write(user); + } + var newDirectory = User.getUserFolderFor(id); + Files.move(oldDirectory.toPath(), newDirectory.toPath(), StandardCopyOption.REPLACE_EXISTING); + LOGGER.info(() -> "migrated " + oldDirectory + " to " + newDirectory); + } catch (Exception x) { + LOGGER.log(Level.WARNING, "failed to migrate " + oldDirectory, x); + } + } + } } } } diff --git a/core/src/main/java/hudson/model/UserIdMigrator.java b/core/src/main/java/hudson/model/UserIdMigrator.java deleted file mode 100644 index 4af152b6acb4..000000000000 --- a/core/src/main/java/hudson/model/UserIdMigrator.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2018 CloudBees, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package hudson.model; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; -import jenkins.model.IdStrategy; -import org.kohsuke.accmod.Restricted; -import org.kohsuke.accmod.restrictions.NoExternalUse; - -@Restricted(NoExternalUse.class) -class UserIdMigrator { - - private static final Logger LOGGER = Logger.getLogger(UserIdMigrator.class.getName()); - private static final String EMPTY_USERNAME_DIRECTORY_NAME = "emptyUsername"; - - private final File usersDirectory; - private final IdStrategy idStrategy; - - UserIdMigrator(File usersDirectory, IdStrategy idStrategy) { - this.usersDirectory = usersDirectory; - this.idStrategy = idStrategy; - } - - boolean needsMigration() { - File mappingFile = UserIdMapper.getConfigFile(usersDirectory); - if (mappingFile.exists() && mappingFile.isFile()) { - LOGGER.finest("User mapping file already exists. No migration needed."); - return false; - } - File[] userDirectories = listUserDirectories(); - return userDirectories != null && userDirectories.length > 0; - } - - private File[] listUserDirectories() { - return usersDirectory.listFiles(file -> file.isDirectory() && new File(file, User.CONFIG_XML).exists()); - } - - Map scanExistingUsers() throws IOException { - Map users = new HashMap<>(); - File[] userDirectories = listUserDirectories(); - if (userDirectories != null) { - for (File directory : userDirectories) { - String userId = idStrategy.idFromFilename(directory.getName()); - users.put(userId, directory); - } - } - addEmptyUsernameIfExists(users); - return users; - } - - private void addEmptyUsernameIfExists(Map users) throws IOException { - File emptyUsernameConfigFile = new File(usersDirectory, User.CONFIG_XML); - if (emptyUsernameConfigFile.exists()) { - File newEmptyUsernameDirectory = new File(usersDirectory, EMPTY_USERNAME_DIRECTORY_NAME); - Files.createDirectory(newEmptyUsernameDirectory.toPath()); - File newEmptyUsernameConfigFile = new File(newEmptyUsernameDirectory, User.CONFIG_XML); - Files.move(emptyUsernameConfigFile.toPath(), newEmptyUsernameConfigFile.toPath()); - users.put("", newEmptyUsernameDirectory); - } - } - - void migrateUsers(UserIdMapper mapper) throws IOException { - LOGGER.fine("Beginning migration of users to userId mapping."); - Map existingUsers = scanExistingUsers(); - for (Map.Entry existingUser : existingUsers.entrySet()) { - File newDirectory = mapper.putIfAbsent(existingUser.getKey(), false); - LOGGER.log(Level.INFO, "Migrating user '" + existingUser.getKey() + "' from 'users/" + existingUser.getValue().getName() + "/' to 'users/" + newDirectory.getName() + "/'"); - Files.move(existingUser.getValue().toPath(), newDirectory.toPath(), StandardCopyOption.REPLACE_EXISTING); - } - mapper.save(); - LOGGER.fine("Completed migration of users to userId mapping."); - } - -} diff --git a/core/src/test/java/hudson/model/TestUserIdMapper.java b/core/src/test/java/hudson/model/TestUserIdMapper.java deleted file mode 100644 index f0ee0979ea97..000000000000 --- a/core/src/test/java/hudson/model/TestUserIdMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package hudson.model; - -import java.io.File; -import jenkins.model.IdStrategy; - -class TestUserIdMapper extends UserIdMapper { - - private File usersDirectory; - private IdStrategy idStrategy; - - TestUserIdMapper(File usersDirectory, IdStrategy idStrategy) { - this.usersDirectory = usersDirectory; - this.idStrategy = idStrategy; - } - - @Override - protected File getUsersDirectory() { - return usersDirectory; - } - - @Override - protected IdStrategy getIdStrategy() { - return idStrategy; - } -} diff --git a/core/src/test/java/hudson/model/UserIdMapperTest.java b/core/src/test/java/hudson/model/UserIdMapperTest.java deleted file mode 100644 index dfe0f9d6d48a..000000000000 --- a/core/src/test/java/hudson/model/UserIdMapperTest.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2018 CloudBees, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package hudson.model; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; -import static org.hamcrest.Matchers.startsWith; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import java.io.File; -import java.io.IOException; -import jenkins.model.IdStrategy; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; - -class UserIdMapperTest { - - private TestInfo info; - - @BeforeEach - void setUp(TestInfo testInfo) { - info = testInfo; - } - - @Test - void testNonexistentFileLoads() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - } - - @Test - void testEmptyGet() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - assertThat(mapper.getDirectory("anything"), nullValue()); - } - - @Test - void testSimplePutGet() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - assertThat(directory, is(mapper.getDirectory(user1))); - } - - @Test - void testMultiple() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory1 = mapper.putIfAbsent(user1, true); - String user2 = "user2"; - File directory2 = mapper.putIfAbsent(user2, true); - String user3 = "user3"; - File directory3 = mapper.putIfAbsent(user3, true); - assertThat(directory1, is(mapper.getDirectory(user1))); - assertThat(directory2, is(mapper.getDirectory(user2))); - assertThat(directory3, is(mapper.getDirectory(user3))); - } - - @Test - void testMultipleSaved() throws IOException { - File usersDirectory = UserIdMigratorTest.createTestDirectory(getClass(), info); - IdStrategy idStrategy = IdStrategy.CASE_INSENSITIVE; - UserIdMapper mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - String user1 = "user1"; - File directory1 = mapper.putIfAbsent(user1, true); - String user2 = "user2"; - File directory2 = mapper.putIfAbsent(user2, true); - String user3 = "user3"; - File directory3 = mapper.putIfAbsent(user3, true); - mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - assertThat(directory1, is(mapper.getDirectory(user1))); - assertThat(directory2, is(mapper.getDirectory(user2))); - assertThat(directory3, is(mapper.getDirectory(user3))); - } - - @Test - void testRepeatPut() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory1 = mapper.putIfAbsent(user1, true); - File directory2 = mapper.putIfAbsent(user1, true); - assertThat(directory1, is(directory2)); - } - - @Test - void testIsNotMapped() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - assertThat(mapper.isMapped("anything"), is(false)); - } - - @Test - void testIsMapped() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - assertThat(mapper.isMapped(user1), is(true)); - } - - @Test - void testInitialUserIds() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - assertThat(mapper.getConvertedUserIds(), empty()); - } - - @Test - void testSingleUserIds() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - assertThat(mapper.getConvertedUserIds(), hasSize(1)); - assertThat(mapper.getConvertedUserIds().iterator().next(), is(user1)); - } - - @Test - void testMultipleUserIds() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - String user2 = "user2"; - File directory2 = mapper.putIfAbsent(user2, true); - assertThat(mapper.getConvertedUserIds(), hasSize(2)); - assertThat(mapper.getConvertedUserIds(), hasItems(user1, user2)); - } - - @Test - void testRemove() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - mapper.remove(user1); - assertThat(mapper.isMapped(user1), is(false)); - } - - @Test - void testRemoveAfterSave() throws IOException { - File usersDirectory = UserIdMigratorTest.createTestDirectory(getClass(), info); - IdStrategy idStrategy = IdStrategy.CASE_INSENSITIVE; - UserIdMapper mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - mapper.remove(user1); - mapper = new TestUserIdMapper(usersDirectory, idStrategy); - assertThat(mapper.isMapped(user1), is(false)); - } - - @Test - void testPutGetCaseInsensitive() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - assertThat(mapper.getDirectory(user1.toUpperCase()), notNullValue()); - } - - @Test - void testPutGetCaseSensitive() throws IOException { - IdStrategy idStrategy = new IdStrategy.CaseSensitive(); - UserIdMapper mapper = createUserIdMapper(idStrategy); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - assertThat(mapper.getDirectory(user1.toUpperCase()), nullValue()); - } - - @Test - void testIsMappedCaseInsensitive() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - assertThat(mapper.isMapped(user1.toUpperCase()), is(true)); - } - - @Test - void testIsMappedCaseSensitive() throws IOException { - IdStrategy idStrategy = new IdStrategy.CaseSensitive(); - UserIdMapper mapper = createUserIdMapper(idStrategy); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - assertThat(mapper.isMapped(user1.toUpperCase()), is(false)); - } - - @Test - void testRemoveCaseInsensitive() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - mapper.remove(user1.toUpperCase()); - assertThat(mapper.isMapped(user1), is(false)); - } - - @Test - void testRemoveCaseSensitive() throws IOException { - IdStrategy idStrategy = new IdStrategy.CaseSensitive(); - UserIdMapper mapper = createUserIdMapper(idStrategy); - String user1 = "user1"; - File directory = mapper.putIfAbsent(user1, true); - mapper.remove(user1.toUpperCase()); - assertThat(mapper.isMapped(user1), is(true)); - } - - @Test - void testRepeatRemove() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory1 = mapper.putIfAbsent(user1, true); - mapper.remove(user1); - mapper.remove(user1); - assertThat(mapper.isMapped(user1), is(false)); - } - - @Test - void testClear() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory1 = mapper.putIfAbsent(user1, true); - mapper.clear(); - assertThat(mapper.isMapped(user1), is(false)); - assertThat(mapper.getConvertedUserIds(), empty()); - } - - @Test - void testReload() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "user1"; - File directory1 = mapper.putIfAbsent(user1, true); - mapper.reload(); - assertThat(mapper.isMapped(user1), is(true)); - assertThat(mapper.getConvertedUserIds(), hasSize(1)); - } - - @Test - void testDirectoryFormatBasic() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "1user"; - File directory1 = mapper.putIfAbsent(user1, true); - assertThat(directory1.getName(), startsWith(user1 + '_')); - } - - @Test - void testDirectoryFormatLongerUserId() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "muchlongeruserid"; - File directory1 = mapper.putIfAbsent(user1, true); - assertThat(directory1.getName(), startsWith("muchlongeruser_")); - } - - @Test - void testDirectoryFormatAllSuppressedCharacters() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "!@#$%^"; - File directory1 = mapper.putIfAbsent(user1, true); - assertThat(directory1.getName(), startsWith("_")); - } - - @Test - void testDirectoryFormatSingleCharacter() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "."; - File directory1 = mapper.putIfAbsent(user1, true); - assertThat(directory1.getName(), startsWith("_")); - } - - @Test - void testDirectoryFormatMixed() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - String user1 = "a$b!c^d~e@f"; - File directory1 = mapper.putIfAbsent(user1, true); - assertThat(directory1.getName(), startsWith("abcdef_")); - } - - @Test - void testXmlFileCorrupted() { - assertThrows(IOException.class, () -> createUserIdMapper(IdStrategy.CASE_INSENSITIVE)); - } - - @Test - void testDuplicatedUserId() throws IOException { - UserIdMapper mapper = createUserIdMapper(IdStrategy.CASE_INSENSITIVE); - assertThat(mapper.isMapped("user2"), is(true)); - assertThat(mapper.isMapped("user1"), is(true)); - } - - private UserIdMapper createUserIdMapper(IdStrategy idStrategy) throws IOException { - File usersDirectory = UserIdMigratorTest.createTestDirectory(getClass(), info); - TestUserIdMapper mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - return mapper; - } - -} diff --git a/core/src/test/java/hudson/model/UserIdMigratorTest.java b/core/src/test/java/hudson/model/UserIdMigratorTest.java deleted file mode 100644 index 22697925b0f8..000000000000 --- a/core/src/test/java/hudson/model/UserIdMigratorTest.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2018 CloudBees, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package hudson.model; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.is; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Map; -import jenkins.model.IdStrategy; -import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; - -class UserIdMigratorTest { - - private static final String BASE_RESOURCE_PATH = "src/test/resources/hudson/model/"; - - private TestInfo info; - - @BeforeEach - void setUp(TestInfo testInfo) { - info = testInfo; - } - - - @Test - void needsMigrationBasic() throws IOException { - UserIdMigrator migrator = createUserIdMigrator(); - assertThat(migrator.needsMigration(), is(true)); - } - - @Test - void needsMigrationFalse() throws IOException { - UserIdMigrator migrator = createUserIdMigrator(); - assertThat(migrator.needsMigration(), is(false)); - } - - @Test - void needsMigrationNoneExisting() throws IOException { - UserIdMigrator migrator = createUserIdMigrator(); - assertThat(migrator.needsMigration(), is(false)); - } - - @Test - void needsMigrationNoUserConfigFiles() throws IOException { - UserIdMigrator migrator = createUserIdMigrator(); - assertThat(migrator.needsMigration(), is(false)); - } - - @Test - void scanExistingUsersNone() throws IOException { - File usersDirectory = createTestDirectory(getClass(), info); - UserIdMigrator migrator = new UserIdMigrator(usersDirectory, IdStrategy.CASE_INSENSITIVE); - Map userMappings = migrator.scanExistingUsers(); - assertThat(userMappings.keySet(), empty()); - } - - @Test - void scanExistingUsersNoUsersDirectory() throws IOException { - UserIdMigrator migrator = createUserIdMigrator(); - Map userMappings = migrator.scanExistingUsers(); - assertThat(userMappings.keySet(), empty()); - } - - @Test - void scanExistingUsersBasic() throws IOException { - UserIdMigrator migrator = createUserIdMigrator(); - Map userMappings = migrator.scanExistingUsers(); - assertThat(userMappings.keySet(), hasSize(2)); - assertThat(userMappings.keySet(), hasItems("admin", "jane")); - } - - @Test - void scanExistingUsersLegacy() throws IOException { - UserIdMigrator migrator = createUserIdMigrator(); - Map userMappings = migrator.scanExistingUsers(); - assertThat(userMappings.keySet(), hasSize(8)); - assertThat(userMappings.keySet(), hasItems("foo/bar", "foo/bar/baz", "/", "..", "bla$phem.us", "make$1000000", "big$money", "~com1")); - } - - @Test - void scanExistingUsersOldLegacy() throws IOException { - UserIdMigrator migrator = createUserIdMigrator(); - Map userMappings = migrator.scanExistingUsers(); - assertThat(userMappings.keySet(), hasSize(4)); - assertThat(userMappings.keySet(), hasItems("make\u1000000", "\u306f\u56fd\u5185\u3067\u6700\u5927", "\u1000yyy", "zzz\u1000")); - } - - @Test - void emptyUsernameConfigScanned() throws IOException { - UserIdMigrator migrator = createUserIdMigrator(); - Map userMappings = migrator.scanExistingUsers(); - assertThat(userMappings.keySet(), hasSize(2)); - assertThat(userMappings.keySet(), hasItems("admin", "")); - } - - @Test - void scanExistingUsersCaseSensitive() throws IOException { - File usersDirectory = createTestDirectory(getClass(), info); - UserIdMigrator migrator = new UserIdMigrator(usersDirectory, new IdStrategy.CaseSensitive()); - Map userMappings = migrator.scanExistingUsers(); - assertThat(userMappings.keySet(), hasSize(3)); - assertThat(userMappings.keySet(), hasItems("admin", "Fred", "Jane")); - } - - @Test - void migrateSimpleUser() throws IOException { - File usersDirectory = createTestDirectory(getClass(), info); - IdStrategy idStrategy = IdStrategy.CASE_INSENSITIVE; - UserIdMigrator migrator = new UserIdMigrator(usersDirectory, idStrategy); - TestUserIdMapper mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - assertThat(migrator.needsMigration(), is(false)); - mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - assertThat(mapper.getConvertedUserIds().size(), is(1)); - assertThat(mapper.isMapped("fred"), is(true)); - } - - @Test - void migrateMultipleUsers() throws IOException { - File usersDirectory = createTestDirectory(getClass(), info); - IdStrategy idStrategy = IdStrategy.CASE_INSENSITIVE; - UserIdMigrator migrator = new UserIdMigrator(usersDirectory, idStrategy); - TestUserIdMapper mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - assertThat(migrator.needsMigration(), is(false)); - mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - assertThat(mapper.getConvertedUserIds().size(), is(3)); - assertThat(mapper.isMapped("fred"), is(true)); - assertThat(mapper.isMapped("foo/bar"), is(true)); - assertThat(mapper.isMapped("zzz\u1000"), is(true)); - } - - @Test - void migrateUsersXml() throws IOException { - File usersDirectory = createTestDirectory(getClass(), info); - IdStrategy idStrategy = IdStrategy.CASE_INSENSITIVE; - UserIdMigrator migrator = new UserIdMigrator(usersDirectory, idStrategy); - TestUserIdMapper mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - assertThat(migrator.needsMigration(), is(false)); - mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - assertThat(mapper.getConvertedUserIds().size(), is(1)); - assertThat(mapper.isMapped("users.xml"), is(true)); - } - - @Test - void migrateEntireDirectory() throws IOException { - File usersDirectory = createTestDirectory(getClass(), info); - IdStrategy idStrategy = IdStrategy.CASE_INSENSITIVE; - UserIdMigrator migrator = new UserIdMigrator(usersDirectory, idStrategy); - TestUserIdMapper mapper = new TestUserIdMapper(usersDirectory, idStrategy); - mapper.init(); - File fredDirectory = mapper.getDirectory("fred"); - File otherFile = new File(fredDirectory, "otherfile.txt"); - assertThat(otherFile.exists(), is(true)); - File originalFredDirectory = new File(usersDirectory, "fred"); - assertThat(originalFredDirectory.exists(), is(false)); - } - - static File createTestDirectory(Class clazz, TestInfo info) throws IOException { - File tempDirectory = Files.createTempDirectory(Paths.get("target"), "userIdMigratorTest").toFile(); - tempDirectory.deleteOnExit(); - copyTestDataIfExists(clazz, info, tempDirectory); - return new File(tempDirectory, "users"); - } - - static void copyTestDataIfExists(Class clazz, TestInfo info, File tempDirectory) throws IOException { - File resourcesDirectory = new File(BASE_RESOURCE_PATH + clazz.getSimpleName(), info.getTestMethod().orElseThrow().getName()); - if (resourcesDirectory.exists()) { - FileUtils.copyDirectory(resourcesDirectory, tempDirectory); - } - } - - private UserIdMigrator createUserIdMigrator() throws IOException { - File usersDirectory = createTestDirectory(getClass(), info); - return new UserIdMigrator(usersDirectory, IdStrategy.CASE_INSENSITIVE); - } - -} diff --git a/core/src/test/resources/hudson/model/UserIdMapperTest/testDuplicatedUserId/users/users.xml b/core/src/test/resources/hudson/model/UserIdMapperTest/testDuplicatedUserId/users/users.xml deleted file mode 100644 index b094fd36f976..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMapperTest/testDuplicatedUserId/users/users.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - user1 - user2957281690483826750 - - - user1 - user6639871027538302990 - - - user2 - user22222 - - - diff --git a/core/src/test/resources/hudson/model/UserIdMapperTest/testXmlFileCorrupted/users/users.xml b/core/src/test/resources/hudson/model/UserIdMapperTest/testXmlFileCorrupted/users/users.xml deleted file mode 100644 index ad31ae2638a6..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMapperTest/testXmlFileCorrupted/users/users.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - fred - Fred Smith - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/emptyUsernameConfigScanned/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/emptyUsernameConfigScanned/config.xml deleted file mode 100644 index e8902ede4e10..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/emptyUsernameConfigScanned/config.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - 1.0 - 2 - NORMAL - true - - true - - - true - false - - false - - ${JENKINS_HOME}/workspace/${ITEM_FULLNAME} - ${ITEM_ROOTDIR}/builds - - - - - 0 - - - - all - false - false - - - - all - -1 - - - false - - - - \ No newline at end of file diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/emptyUsernameConfigScanned/users/admin/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/emptyUsernameConfigScanned/users/admin/config.xml deleted file mode 100644 index 91fc2f3e1f51..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/emptyUsernameConfigScanned/users/admin/config.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - Admin - - - {AQAAABAAAAAwu9tm9n3SIC+bkaGz5WfsKwJz+a04aUUWiq4hACNLemh6f62j2cgIT9KuyMGtXvr7ab6GWBQGzThOrJfK1etETQ==} - - - - - - all - false - false - - - - - - - - - false - - - #jbcrypt:$2a$10$eDQD3w/iXX0VWWKb3Kv5QOKjFg0Yj3Hk9Z.Y43iFHJQOUYmHdvVuS - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/emptyUsernameConfigScanned/users/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/emptyUsernameConfigScanned/users/config.xml deleted file mode 100644 index 9df32ee88b47..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/emptyUsernameConfigScanned/users/config.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - Empty - - - {AQAAABAAAAAwkYgvFl7YHG1866pnHDawvcy2VQ0jlbQd85vu9WWI22SjmLmJS0TMMS4w+3XqvEt8nHx9/0U06huIcMj3XuDPuQ==} - - - - - - all - false - false - - - - - - - - - false - - - #jbcrypt:$2a$10$dTn2EpIBa2E0T6R.2XK/HucVkyqdu9qGQ6FmBOYdZlpeN2mtv.Ez2 - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateEntireDirectory/users/fred/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateEntireDirectory/users/fred/config.xml deleted file mode 100644 index ad31ae2638a6..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateEntireDirectory/users/fred/config.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - fred - Fred Smith - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateEntireDirectory/users/fred/otherfile.txt b/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateEntireDirectory/users/fred/otherfile.txt deleted file mode 100644 index 1b376877f435..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateEntireDirectory/users/fred/otherfile.txt +++ /dev/null @@ -1 +0,0 @@ -Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateMultipleUsers/users/foo$002fbar/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateMultipleUsers/users/foo$002fbar/config.xml deleted file mode 100644 index fddfc4117665..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateMultipleUsers/users/foo$002fbar/config.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Foo Bar - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateMultipleUsers/users/fred/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateMultipleUsers/users/fred/config.xml deleted file mode 100644 index ad31ae2638a6..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateMultipleUsers/users/fred/config.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - fred - Fred Smith - diff --git "a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateMultipleUsers/users/zzz\341\200\200/config.xml" "b/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateMultipleUsers/users/zzz\341\200\200/config.xml" deleted file mode 100644 index 9216f71ae311..000000000000 --- "a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateMultipleUsers/users/zzz\341\200\200/config.xml" +++ /dev/null @@ -1,4 +0,0 @@ - - - Old Legacy - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateSimpleUser/users/fred/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateSimpleUser/users/fred/config.xml deleted file mode 100644 index ad31ae2638a6..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateSimpleUser/users/fred/config.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - fred - Fred Smith - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateUsersXml/users/users.xml/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateUsersXml/users/users.xml/config.xml deleted file mode 100644 index ad31ae2638a6..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/migrateUsersXml/users/users.xml/config.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - fred - Fred Smith - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/needsMigrationBasic/users/jane_4975613142751794216/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/needsMigrationBasic/users/jane_4975613142751794216/config.xml deleted file mode 100644 index 6465bde25c74..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/needsMigrationBasic/users/jane_4975613142751794216/config.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - jane - Fred Smith - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/needsMigrationFalse/users/users.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/needsMigrationFalse/users/users.xml deleted file mode 100644 index c8017032d1ba..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/needsMigrationFalse/users/users.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - fred - user4975613142751794216 - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/needsMigrationNoUserConfigFiles/users/users.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/needsMigrationNoUserConfigFiles/users/users.xml deleted file mode 100644 index c8017032d1ba..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/needsMigrationNoUserConfigFiles/users/users.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - fred - user4975613142751794216 - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersBasic/users/admin/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersBasic/users/admin/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersBasic/users/admin/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersBasic/users/jane/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersBasic/users/jane/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersBasic/users/jane/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersCaseSensitive/users/Fred/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersCaseSensitive/users/Fred/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersCaseSensitive/users/Fred/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersCaseSensitive/users/admin/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersCaseSensitive/users/admin/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersCaseSensitive/users/admin/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersCaseSensitive/users/~jane/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersCaseSensitive/users/~jane/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersCaseSensitive/users/~jane/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/$002e$002e/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/$002e$002e/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/$002e$002e/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/$002f/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/$002f/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/$002f/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/big$money/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/big$money/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/big$money/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/bla$0024phem.us/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/bla$0024phem.us/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/bla$0024phem.us/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/foo$002fbar$002fbaz/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/foo$002fbar$002fbaz/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/foo$002fbar$002fbaz/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/foo$002fbar/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/foo$002fbar/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/foo$002fbar/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/make$00241000000/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/make$00241000000/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/make$00241000000/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/~com1/config.xml b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/~com1/config.xml deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersLegacy/users/~com1/config.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git "a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/make\341\200\200000/config.xml" "b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/make\341\200\200000/config.xml" deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- "a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/make\341\200\200000/config.xml" +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git "a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/zzz\341\200\200/config.xml" "b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/zzz\341\200\200/config.xml" deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- "a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/zzz\341\200\200/config.xml" +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git "a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/\341\200\200yyy/config.xml" "b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/\341\200\200yyy/config.xml" deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- "a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/\341\200\200yyy/config.xml" +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git "a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/\343\201\257\345\233\275\345\206\205\343\201\247\346\234\200\345\244\247/config.xml" "b/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/\343\201\257\345\233\275\345\206\205\343\201\247\346\234\200\345\244\247/config.xml" deleted file mode 100644 index 3eae7e9ffa95..000000000000 --- "a/core/src/test/resources/hudson/model/UserIdMigratorTest/scanExistingUsersOldLegacy/users/\343\201\257\345\233\275\345\206\205\343\201\247\346\234\200\345\244\247/config.xml" +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/test/src/test/java/hudson/model/UserIdMigratorTest.java b/test/src/test/java/hudson/model/UserIdMigratorTest.java index 2ef0f4db91b8..07461fcb6837 100644 --- a/test/src/test/java/hudson/model/UserIdMigratorTest.java +++ b/test/src/test/java/hudson/model/UserIdMigratorTest.java @@ -29,10 +29,13 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.jvnet.hudson.test.For; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.junit.jupiter.WithJenkins; import org.jvnet.hudson.test.recipes.LocalData; +@SuppressWarnings("deprecation") +@For(UserIdMapper.class) @WithJenkins class UserIdMigratorTest { diff --git a/test/src/test/java/hudson/model/UserTest.java b/test/src/test/java/hudson/model/UserTest.java index c17b81da94fd..062d22479c7f 100644 --- a/test/src/test/java/hudson/model/UserTest.java +++ b/test/src/test/java/hudson/model/UserTest.java @@ -61,6 +61,7 @@ import java.util.List; import java.util.Locale; import java.util.Set; +import java.util.logging.Level; import jenkins.model.IdStrategy; import jenkins.model.Jenkins; import jenkins.security.ApiTokenProperty; @@ -72,12 +73,14 @@ import org.htmlunit.html.HtmlPage; import org.htmlunit.util.WebConnectionWrapper; import org.jenkinsci.plugins.matrixauth.PermissionEntry; +import org.junit.jupiter.api.AutoClose; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.FakeChangeLogSCM; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.LogRecorder; import org.jvnet.hudson.test.MockAuthorizationStrategy; import org.jvnet.hudson.test.TestExtension; import org.jvnet.hudson.test.junit.jupiter.WithJenkins; @@ -100,6 +103,9 @@ void setUp(JenkinsRule rule) { j = rule; } + @AutoClose + LogRecorder logging = new LogRecorder().record(User.class, Level.FINE); + public static class UserPropertyImpl extends UserProperty implements Action { private final String testString;