Merge branch 'master' of https://github.com/AuthMe/AuthMeReloaded into 792-add-registration-date-and-ip

This commit is contained in:
ljacqu
2017-10-21 10:46:17 +02:00
21 changed files with 195 additions and 130 deletions
@@ -19,6 +19,7 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -142,25 +143,22 @@ public class ConsoleLoggerTest {
ConsoleLogger.setLoggingOptions(newSettings(true, LogLevel.DEBUG));
// when
ConsoleLogger.debug("Got {0} entries", "test");
ConsoleLogger.debug("Player `{0}` is in world `{1}`", "Bobby", "world");
ConsoleLogger.debug("The {0} is {1} the {2}", "fox", "behind", "chicken");
ConsoleLogger.debug("Got {0} entries", 17);
ConsoleLogger.debug("Player `{0}` is in world `{1}`", "Bobby", new World("world"));
ConsoleLogger.debug("{0} quick {1} jump over {2} lazy {3} (reason: {4})", 5, "foxes", 3, "dogs", null);
ConsoleLogger.debug(() -> "Too little too late");
// then
verify(logger).log(Level.INFO, "[DEBUG] Got {0} entries", "test");
verify(logger).log(Level.INFO, "[DEBUG] Player `{0}` is in world `{1}`", new Object[]{"Bobby", "world"});
verify(logger).log(Level.INFO, "[DEBUG] The {0} is {1} the {2}", new Object[]{"fox", "behind", "chicken"});
verify(logger).log(Level.INFO, "[DEBUG] Got {0} entries", 17);
verify(logger).log(Level.INFO, "[DEBUG] Player `{0}` is in world `{1}`", new Object[]{"Bobby", new World("world")});
verify(logger).log(Level.INFO, "[DEBUG] {0} quick {1} jump over {2} lazy {3} (reason: {4})",
new Object[]{"5", "foxes", "3", "dogs", "null"});
new Object[]{5, "foxes", 3, "dogs", null});
verify(logger).info("[DEBUG] Too little too late");
List<String> loggedLines = Files.readAllLines(logFile.toPath(), StandardCharsets.UTF_8);
assertThat(loggedLines, contains(
containsString("[DEBUG] Got {0} entries {test}"),
containsString("[DEBUG] Player `{0}` is in world `{1}` {Bobby, world}"),
containsString("[DEBUG] The {0} is {1} the {2} {fox, behind, chicken}"),
containsString("[DEBUG] Got {0} entries {17}"),
containsString("[DEBUG] Player `{0}` is in world `{1}` {Bobby, w[world]}"),
containsString("[DEBUG] {0} quick {1} jump over {2} lazy {3} (reason: {4}) {5, foxes, 3, dogs, null}"),
containsString("[DEBUG] Too little too late")));
}
@@ -176,4 +174,25 @@ public class ConsoleLoggerTest {
given(settings.getProperty(PluginSettings.LOG_LEVEL)).willReturn(logLevel);
return settings;
}
private static final class World {
private final String name;
World(String name) {
this.name = name;
}
@Override
public String toString() {
return "w[" + name + "]";
}
@Override
public boolean equals(Object other) {
if (other instanceof World) {
return Objects.equals(this.name, ((World) other).name);
}
return false;
}
}
}
@@ -1,27 +0,0 @@
package fr.xephi.authme.initialization;
import fr.xephi.authme.security.HashAlgorithm;
import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* Test for {@link OnStartupTasks}.
*/
public class OnStartupTasksTest {
@Test
public void shouldCheckIfHashIsDeprecatedIn54() {
// given / when / then
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.CUSTOM), equalTo(false));
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.IPB3), equalTo(false));
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.PLAINTEXT), equalTo(false));
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.SHA256), equalTo(false));
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.WORDPRESS), equalTo(false));
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.MD5), equalTo(true));
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.SHA512), equalTo(true));
assertThat(OnStartupTasks.isHashDeprecatedIn54(HashAlgorithm.WHIRLPOOL), equalTo(true));
}
}
@@ -4,6 +4,8 @@ import ch.jalu.injector.Injector;
import ch.jalu.injector.InjectorBuilder;
import fr.xephi.authme.security.crypts.EncryptionMethod;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.security.crypts.description.Recommendation;
import fr.xephi.authme.security.crypts.description.Usage;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.HooksSettings;
import fr.xephi.authme.settings.properties.SecuritySettings;
@@ -12,6 +14,8 @@ import org.junit.BeforeClass;
import org.junit.Test;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import static org.hamcrest.Matchers.equalTo;
@@ -70,4 +74,29 @@ public class HashAlgorithmIntegrationTest {
}
}
@Test
public void shouldBeDeprecatedIfEncryptionClassIsDeprecated() throws NoSuchFieldException {
// given
List<String> failedEntries = new LinkedList<>();
// when
for (HashAlgorithm hashAlgorithm : HashAlgorithm.values()) {
if (hashAlgorithm != HashAlgorithm.CUSTOM) {
boolean isEnumDeprecated = HashAlgorithm.class.getDeclaredField(hashAlgorithm.name())
.isAnnotationPresent(Deprecated.class);
boolean isDeprecatedClass = hashAlgorithm.getClazz().isAnnotationPresent(Deprecated.class);
Recommendation recommendation = hashAlgorithm.getClazz().getAnnotation(Recommendation.class);
boolean hasDeprecatedUsage = recommendation != null && recommendation.value() == Usage.DEPRECATED;
if (isEnumDeprecated != isDeprecatedClass || isEnumDeprecated != hasDeprecatedUsage) {
failedEntries.add(hashAlgorithm + ": enum @Deprecated = " + isEnumDeprecated
+ ", @Deprecated class = " + isDeprecatedClass + ", usage Deprecated = " + hasDeprecatedUsage);
}
}
}
// then
if (!failedEntries.isEmpty()) {
fail("Found inconsistencies:\n" + String.join("\n", failedEntries));
}
}
}
@@ -1,12 +1,16 @@
package fr.xephi.authme.settings;
import ch.jalu.configme.configurationdata.ConfigurationData;
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.resource.PropertyResource;
import ch.jalu.configme.resource.YamlFileResource;
import com.google.common.io.Files;
import fr.xephi.authme.TestHelper;
import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.output.LogLevel;
import fr.xephi.authme.process.register.RegisterSecondaryArgument;
import fr.xephi.authme.process.register.RegistrationType;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.settings.properties.AuthMeSettingsRetriever;
import org.junit.BeforeClass;
import org.junit.Rule;
@@ -16,6 +20,8 @@ import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import static fr.xephi.authme.TestHelper.getJarFile;
import static fr.xephi.authme.settings.properties.PluginSettings.ENABLE_PERMISSION_CHECK;
@@ -28,6 +34,8 @@ import static fr.xephi.authme.settings.properties.RegistrationSettings.REGISTRAT
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_NICKNAME_CHARACTERS;
import static fr.xephi.authme.settings.properties.RestrictionSettings.FORCE_SPAWN_LOCATION_AFTER_LOGIN;
import static fr.xephi.authme.settings.properties.RestrictionSettings.FORCE_SPAWN_ON_WORLDS;
import static fr.xephi.authme.settings.properties.SecuritySettings.LEGACY_HASHES;
import static fr.xephi.authme.settings.properties.SecuritySettings.PASSWORD_HASH;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
@@ -47,8 +55,9 @@ public class SettingsMigrationServiceTest {
TestHelper.setupLogger();
}
/* When settings are loaded, test that migrations are applied and immediately available in memory. */
@Test
public void shouldPerformMigrations() throws IOException {
public void shouldPerformMigrationsInMemory() throws IOException {
// given
File dataFolder = temporaryFolder.newFolder();
File configFile = new File(dataFolder, "config.yml");
@@ -61,22 +70,31 @@ public class SettingsMigrationServiceTest {
dataFolder, resource, migrationService, AuthMeSettingsRetriever.buildConfigurationData());
// then
assertThat(settings.getProperty(ALLOWED_NICKNAME_CHARACTERS), equalTo(ALLOWED_NICKNAME_CHARACTERS.getDefaultValue()));
assertThat(settings.getProperty(DELAY_JOIN_MESSAGE), equalTo(true));
assertThat(settings.getProperty(FORCE_SPAWN_LOCATION_AFTER_LOGIN), equalTo(true));
assertThat(settings.getProperty(FORCE_SPAWN_ON_WORLDS), contains("survival", "survival_nether", "creative"));
assertThat(settings.getProperty(LOG_LEVEL), equalTo(LogLevel.INFO));
assertThat(settings.getProperty(REGISTRATION_TYPE), equalTo(RegistrationType.EMAIL));
assertThat(settings.getProperty(REGISTER_SECOND_ARGUMENT), equalTo(RegisterSecondaryArgument.CONFIRMATION));
assertThat(settings.getProperty(ENABLE_PERMISSION_CHECK), equalTo(true));
assertThat(settings.getProperty(REGISTERED_GROUP), equalTo("unLoggedinGroup"));
assertThat(settings.getProperty(UNREGISTERED_GROUP), equalTo(""));
verifyHasUpToDateSettings(settings, dataFolder);
}
// Check migration of old setting to email.html
assertThat(Files.readLines(new File(dataFolder, "email.html"), StandardCharsets.UTF_8),
contains("Dear <playername />, <br /><br /> This is your new AuthMe password for the server "
+ "<br /><br /> <servername /> : <br /><br /> <generatedpass /><br /><image /><br />Do not forget to "
+ "change password after login! <br /> /changepassword <generatedpass /> newPassword"));
/*
* When settings are loaded, test that migrations are applied and persisted to disk,
* i.e. when the settings are loaded again from the file, no migrations should be necessary.
*/
@Test
public void shouldPerformMigrationsAndPersistToDisk() throws IOException {
// given
File dataFolder = temporaryFolder.newFolder();
File configFile = new File(dataFolder, "config.yml");
Files.copy(getJarFile(OLD_CONFIG_FILE), configFile);
PropertyResource resource = new YamlFileResource(configFile);
TestMigrationServiceExtension migrationService = new TestMigrationServiceExtension(dataFolder);
ConfigurationData configurationData = AuthMeSettingsRetriever.buildConfigurationData();
// when
new Settings(dataFolder, resource, migrationService, configurationData);
resource = new YamlFileResource(configFile);
Settings settings = new Settings(dataFolder, resource, migrationService, configurationData);
// then
verifyHasUpToDateSettings(settings, dataFolder);
assertThat(migrationService.returnedValues, contains(true, false));
}
@Test
@@ -97,4 +115,40 @@ public class SettingsMigrationServiceTest {
assertThat(migrationService.getOnRegisterCommands(), contains("me registers", "msg CONSOLE hi"));
assertThat(migrationService.getOnRegisterConsoleCommands(), contains("sethome %p:regloc"));
}
private void verifyHasUpToDateSettings(Settings settings, File dataFolder) throws IOException {
assertThat(settings.getProperty(ALLOWED_NICKNAME_CHARACTERS), equalTo(ALLOWED_NICKNAME_CHARACTERS.getDefaultValue()));
assertThat(settings.getProperty(DELAY_JOIN_MESSAGE), equalTo(true));
assertThat(settings.getProperty(FORCE_SPAWN_LOCATION_AFTER_LOGIN), equalTo(true));
assertThat(settings.getProperty(FORCE_SPAWN_ON_WORLDS), contains("survival", "survival_nether", "creative"));
assertThat(settings.getProperty(LOG_LEVEL), equalTo(LogLevel.INFO));
assertThat(settings.getProperty(REGISTRATION_TYPE), equalTo(RegistrationType.EMAIL));
assertThat(settings.getProperty(REGISTER_SECOND_ARGUMENT), equalTo(RegisterSecondaryArgument.CONFIRMATION));
assertThat(settings.getProperty(ENABLE_PERMISSION_CHECK), equalTo(true));
assertThat(settings.getProperty(REGISTERED_GROUP), equalTo("unLoggedinGroup"));
assertThat(settings.getProperty(UNREGISTERED_GROUP), equalTo(""));
assertThat(settings.getProperty(PASSWORD_HASH), equalTo(HashAlgorithm.SHA256));
assertThat(settings.getProperty(LEGACY_HASHES), contains(HashAlgorithm.PBKDF2, HashAlgorithm.WORDPRESS, HashAlgorithm.SHA512));
// Check migration of old setting to email.html
assertThat(Files.readLines(new File(dataFolder, "email.html"), StandardCharsets.UTF_8),
contains("Dear <playername />, <br /><br /> This is your new AuthMe password for the server "
+ "<br /><br /> <servername /> : <br /><br /> <generatedpass /><br /><image /><br />Do not forget to "
+ "change password after login! <br /> /changepassword <generatedpass /> newPassword"));
}
private static class TestMigrationServiceExtension extends SettingsMigrationService {
private List<Boolean> returnedValues = new ArrayList<>();
TestMigrationServiceExtension(@DataFolder File pluginFolder) {
super(pluginFolder);
}
@Override
protected boolean performMigrations(PropertyResource resource, List<Property<?>> properties) {
boolean result = super.performMigrations(resource, properties);
returnedValues.add(result);
return result;
}
}
}
@@ -191,7 +191,10 @@ settings:
# PLAINTEXT ( unhashed password),
# MYBB, IPB3, PHPFUSION, SMF, XENFORO, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512,
# DOUBLEMD5, PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM(for developpers only)
passwordHash: SHA256
passwordHash: SHA512
legacyHashes:
- PBKDF2
- WORDPRESS
# salt length for the SALTED2MD5 MD5(MD5(password)+salt)
doubleMD5SaltLength: 8
# If password checking return false , do we need to check with all