());
- changes = true;
- }
- if (!contains("Hooks.customAttributes")) {
- set("Hooks.customAttributes", false);
- changes = true;
- }
- if (!contains("Purge.removePermissions")) {
- set("Purge.removePermissions", false);
- changes = true;
- }
- if (contains("Hooks.notifications")) {
- set("Hooks.notifications", null);
- changes = true;
- }
- if (contains("Hooks.chestshop")) {
- set("Hooks.chestshop", null);
- changes = true;
- }
- if (contains("Hooks.legacyChestshop")) {
- set("Hooks.legacyChestshop", null);
- changes = true;
- }
- if (!contains("Email.generateImage")) {
- set("Email.generateImage", false);
- changes = true;
- }
- if (!contains("DataSource.mySQLRealName")) {
- set("DataSource.mySQLRealName", "realname");
- changes = true;
- }
-
- if (!contains("settings.preventOtherCase")) {
- set("settings.preventOtherCase", false);
- changes = true;
- }
-
- if (contains("Email.mailText")) {
- set("Email.mailText", null);
- ConsoleLogger.showError("Remove Email.mailText from config, we now use the email.html file");
- }
-
- if (!contains("Security.stop.kickPlayersBeforeStopping")) {
- set("Security.stop.kickPlayersBeforeStopping", true);
- changes = true;
- }
-
- if (!contains("Email.emailOauth2Token"))
- set("Email.emailOauth2Token", "");
-
- if (!contains("Hooks.sendPlayerTo")) {
- set("Hooks.sendPlayerTo", "");
- changes = true;
- }
-
- if (changes) {
- save();
- plugin.getLogger().warning("Merged new Config Options - I'm not an error, please don't report me");
- plugin.getLogger().warning("Please check your config.yml file for new configs!");
- }
- }
-
- private static boolean contains(String path) {
- return configFile.contains(path);
- }
-
- // public because it's used in AuthMe at one place
-
- /**
- * @param path String
- * @param value String
- */
- public void set(String path, Object value) {
- configFile.set(path, value);
- }
-
/**
* Saves current configuration (plus defaults) to disk.
*
@@ -769,7 +344,7 @@ public final class Settings {
*
* @return True if saved successfully
*/
- public final boolean saveDefaults() {
+ private boolean saveDefaults() {
configFile.options()
.copyDefaults(true)
.copyHeader(true);
diff --git a/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java b/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java
new file mode 100644
index 000000000..0a41301c7
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/settings/SettingsMigrationService.java
@@ -0,0 +1,139 @@
+package fr.xephi.authme.settings;
+
+import com.google.common.annotations.VisibleForTesting;
+import fr.xephi.authme.AuthMe;
+import fr.xephi.authme.ConsoleLogger;
+import fr.xephi.authme.settings.domain.Property;
+import fr.xephi.authme.settings.propertymap.PropertyMap;
+import org.bukkit.configuration.file.FileConfiguration;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+
+import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_NICKNAME_CHARACTERS;
+import static java.lang.String.format;
+
+/**
+ * Service for verifying that the configuration is up-to-date.
+ */
+public final class SettingsMigrationService {
+
+ private SettingsMigrationService() {
+ }
+
+ /**
+ * Checks the config file and does any necessary migrations.
+ *
+ * @param configuration The file configuration to check and migrate
+ * @param propertyMap The property map of all existing properties
+ * @param pluginFolder The plugin folder
+ * @return True if there is a change and the config must be saved, false if the config is up-to-date
+ */
+ public static boolean checkAndMigrate(FileConfiguration configuration, PropertyMap propertyMap, File pluginFolder) {
+ return performMigrations(configuration, pluginFolder) || hasDeprecatedProperties(configuration)
+ || !containsAllSettings(configuration, propertyMap);
+ }
+
+ private static boolean performMigrations(FileConfiguration configuration, File pluginFolder) {
+ boolean changes = false;
+ if ("[a-zA-Z0-9_?]*".equals(configuration.getString(ALLOWED_NICKNAME_CHARACTERS.getPath()))) {
+ configuration.set(ALLOWED_NICKNAME_CHARACTERS.getPath(), "[a-zA-Z0-9_]*");
+ changes = true;
+ }
+ changes = changes || performMailTextToFileMigration(configuration, pluginFolder);
+
+ return changes;
+ }
+
+ @VisibleForTesting
+ static boolean containsAllSettings(FileConfiguration configuration, PropertyMap propertyMap) {
+ for (Property> property : propertyMap.keySet()) {
+ if (!property.isPresent(configuration)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean hasDeprecatedProperties(FileConfiguration configuration) {
+ String[] deprecatedProperties = {
+ "Converter.Rakamak.newPasswordHash", "Hooks.chestshop", "Hooks.legacyChestshop", "Hooks.notifications",
+ "Passpartu", "Performances", "settings.delayJoinMessage", "settings.restrictions.enablePasswordVerifier",
+ "Xenoforo.predefinedSalt"};
+ for (String deprecatedPath : deprecatedProperties) {
+ if (configuration.contains(deprecatedPath)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // --------
+ // Specific migrations
+ // --------
+
+ /**
+ * Check if {@code Email.mailText} is present and move it to the Email.html file if it doesn't exist yet.
+ *
+ * @param configuration The file configuration to verify
+ * @param dataFolder The plugin data folder
+ * @return True if a migration has been completed, false otherwise
+ */
+ private static boolean performMailTextToFileMigration(FileConfiguration configuration, File dataFolder) {
+ final String oldSettingPath = "Email.mailText";
+ if (!configuration.contains(oldSettingPath)) {
+ return false;
+ }
+
+ final File emailFile = new File(dataFolder, "email.html");
+ final String mailText = configuration.getString(oldSettingPath)
+ .replace("", "")
+ .replace("", "")
+ .replace("", "")
+ .replace("", "");
+ if (!emailFile.exists()) {
+ try (FileWriter fw = new FileWriter(emailFile)) {
+ fw.write(mailText);
+ } catch (IOException e) {
+ ConsoleLogger.logException("Could not create email.html configuration file:", e);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Copy a resource file (from the JAR) to the given file if it doesn't exist.
+ *
+ * @param destinationFile The file to check and copy to (outside of JAR)
+ * @param resourcePath Absolute path to the resource file (path to file within JAR)
+ * @return False if the file does not exist and could not be copied, true otherwise
+ */
+ public static boolean copyFileFromResource(File destinationFile, String resourcePath) {
+ if (destinationFile.exists()) {
+ return true;
+ } else if (!destinationFile.getParentFile().exists() && !destinationFile.getParentFile().mkdirs()) {
+ ConsoleLogger.showError("Cannot create parent directories for '" + destinationFile + "'");
+ return false;
+ }
+
+ // ClassLoader#getResourceAsStream does not deal with the '\' path separator: replace to '/'
+ final String normalizedPath = resourcePath.replace("\\", "/");
+ try (InputStream is = AuthMe.class.getClassLoader().getResourceAsStream(normalizedPath)) {
+ if (is == null) {
+ ConsoleLogger.showError(format("Cannot copy resource '%s' to file '%s': cannot load resource",
+ resourcePath, destinationFile.getPath()));
+ } else {
+ Files.copy(is, destinationFile.toPath());
+ return true;
+ }
+ } catch (IOException e) {
+ ConsoleLogger.logException(format("Cannot copy resource '%s' to file '%s':",
+ resourcePath, destinationFile.getPath()), e);
+ }
+ return false;
+ }
+
+}
diff --git a/src/main/java/fr/xephi/authme/settings/custom/NewSetting.java b/src/main/java/fr/xephi/authme/settings/custom/NewSetting.java
deleted file mode 100644
index 7a9094f61..000000000
--- a/src/main/java/fr/xephi/authme/settings/custom/NewSetting.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package fr.xephi.authme.settings.custom;
-
-import com.google.common.annotations.VisibleForTesting;
-import fr.xephi.authme.ConsoleLogger;
-import fr.xephi.authme.settings.domain.Property;
-import fr.xephi.authme.settings.propertymap.PropertyMap;
-import fr.xephi.authme.util.CollectionUtils;
-import fr.xephi.authme.util.StringUtils;
-import org.bukkit.configuration.file.FileConfiguration;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-/**
- * The new settings manager.
- */
-public class NewSetting {
-
- private File file;
- private FileConfiguration configuration;
-
- /**
- * Constructor.
- * Loads the file as YAML and checks its integrity.
- *
- * @param configuration The configuration to interact with
- * @param file The configuration file
- */
- public NewSetting(FileConfiguration configuration, File file) {
- this.configuration = configuration;
- this.file = file;
-
- // TODO ljacqu 20160109: Ensure that save() works as desired (i.e. that it always produces valid YAML)
- // and then uncomment the lines below. Once this is uncommented, the checks in the old Settings.java should
- // be removed as we should check to rewrite the config.yml file only at one place
- // --------
- // PropertyMap propertyMap = SettingsFieldRetriever.getAllPropertyFields();
- // if (!containsAllSettings(propertyMap)) {
- // save(propertyMap);
- // }
- }
-
- /**
- * Constructor for testing purposes, allowing more options.
- *
- * @param configuration The FileConfiguration object to use
- * @param file The file to write to
- * @param propertyMap The property map whose properties should be verified for presence, or null to skip this
- */
- @VisibleForTesting
- NewSetting(FileConfiguration configuration, File file, PropertyMap propertyMap) {
- this.configuration = configuration;
- this.file = file;
-
- if (propertyMap != null && !containsAllSettings(propertyMap)) {
- save(propertyMap);
- }
- }
-
- /**
- * Get the given property from the configuration.
- *
- * @param property The property to retrieve
- * @param The property's type
- * @return The property's value
- */
- public T getProperty(Property property) {
- return property.getFromFile(configuration);
- }
-
- public void save() {
- save(SettingsFieldRetriever.getAllPropertyFields());
- }
-
- public void save(PropertyMap propertyMap) {
- try (FileWriter writer = new FileWriter(file)) {
- writer.write("");
-
- // Contains all but the last node of the setting, e.g. [DataSource, mysql] for "DataSource.mysql.username"
- List currentPath = new ArrayList<>();
- for (Map.Entry, String[]> entry : propertyMap.entrySet()) {
- Property> property = entry.getKey();
-
- // Handle properties
- List propertyPath = Arrays.asList(property.getPath().split("\\."));
- List commonPathParts = CollectionUtils.filterCommonStart(
- currentPath, propertyPath.subList(0, propertyPath.size() - 1));
- List newPathParts = CollectionUtils.getRange(propertyPath, commonPathParts.size());
-
- if (commonPathParts.isEmpty()) {
- writer.append("\n");
- }
-
- int indentationLevel = commonPathParts.size();
- if (newPathParts.size() > 1) {
- for (String path : newPathParts.subList(0, newPathParts.size() - 1)) {
- writer.append("\n")
- .append(indent(indentationLevel))
- .append(path)
- .append(": ");
- ++indentationLevel;
- }
- }
- for (String comment : entry.getValue()) {
- writer.append("\n")
- .append(indent(indentationLevel))
- .append("# ")
- .append(comment);
- }
- writer.append("\n")
- .append(indent(indentationLevel))
- .append(CollectionUtils.getRange(newPathParts, newPathParts.size() - 1).get(0))
- .append(": ");
-
- List yamlLines = property.formatValueAsYaml(configuration);
- String delim = "";
- for (String yamlLine : yamlLines) {
- writer.append(delim).append(yamlLine);
- delim = "\n" + indent(indentationLevel);
- }
-
- currentPath = propertyPath.subList(0, propertyPath.size() - 1);
- }
- writer.flush();
- writer.close();
- } catch (IOException e) {
- ConsoleLogger.logException("Could not save config file:", e);
- }
- }
-
- @VisibleForTesting
- boolean containsAllSettings(PropertyMap propertyMap) {
- for (Property> property : propertyMap.keySet()) {
- if (!property.isPresent(configuration)) {
- return false;
- }
- }
- return true;
- }
-
- private static String indent(int level) {
- // YAML uses indentation of 4 spaces
- StringBuilder sb = new StringBuilder(level * 4);
- for (int i = 0; i < level; ++i) {
- sb.append(" ");
- }
- return sb.toString();
- }
-
-}
diff --git a/src/main/java/fr/xephi/authme/settings/domain/EnumPropertyType.java b/src/main/java/fr/xephi/authme/settings/domain/EnumPropertyType.java
index ed184bb7d..d38d0649d 100644
--- a/src/main/java/fr/xephi/authme/settings/domain/EnumPropertyType.java
+++ b/src/main/java/fr/xephi/authme/settings/domain/EnumPropertyType.java
@@ -1,13 +1,11 @@
package fr.xephi.authme.settings.domain;
import org.bukkit.configuration.file.FileConfiguration;
-
-import java.util.List;
-
-import static java.util.Arrays.asList;
+import org.yaml.snakeyaml.Yaml;
/**
* Enum property type.
+ *
* @param The enum class
*/
class EnumPropertyType> extends PropertyType {
@@ -28,17 +26,17 @@ class EnumPropertyType> extends PropertyType {
return mappedValue != null ? mappedValue : property.getDefaultValue();
}
- @Override
- protected List asYaml(E value) {
- return asList("'" + value + "'");
- }
-
@Override
public boolean contains(Property property, FileConfiguration configuration) {
return super.contains(property, configuration)
&& mapToEnum(configuration.getString(property.getPath())) != null;
}
+ @Override
+ public String toYaml(E value, Yaml simpleYaml, Yaml singleQuoteYaml) {
+ return singleQuoteYaml.dump(value.name());
+ }
+
private E mapToEnum(String value) {
for (E entry : clazz.getEnumConstants()) {
if (entry.name().equalsIgnoreCase(value)) {
diff --git a/src/main/java/fr/xephi/authme/settings/domain/Property.java b/src/main/java/fr/xephi/authme/settings/domain/Property.java
index 6b15b5d3b..f9637a7be 100644
--- a/src/main/java/fr/xephi/authme/settings/domain/Property.java
+++ b/src/main/java/fr/xephi/authme/settings/domain/Property.java
@@ -1,13 +1,14 @@
package fr.xephi.authme.settings.domain;
import org.bukkit.configuration.file.FileConfiguration;
+import org.yaml.snakeyaml.Yaml;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
- * Properties (i.e. a setting that is read from the config.yml file).
+ * Property class, representing a setting that is read from the config.yml file.
*/
public class Property {
@@ -22,15 +23,43 @@ public class Property {
this.defaultValue = defaultValue;
}
+ /**
+ * Create a new property. See also {@link #newProperty(PropertyType, String, Object[])} for lists and
+ * {@link #newProperty(Class, String, Enum)}.
+ *
+ * @param type The property type
+ * @param path The property's path
+ * @param defaultValue The default value
+ * @param The type of the property
+ * @return The created property
+ */
public static Property newProperty(PropertyType type, String path, T defaultValue) {
return new Property<>(type, path, defaultValue);
}
+ /**
+ * Create a new list property.
+ *
+ * @param type The list type of the property
+ * @param path The property's path
+ * @param defaultValues The default value's items
+ * @param The list type
+ * @return The created list property
+ */
@SafeVarargs
public static Property> newProperty(PropertyType> type, String path, U... defaultValues) {
return new Property<>(type, path, Arrays.asList(defaultValues));
}
+ /**
+ * Create a new enum property.
+ *
+ * @param clazz The enum class
+ * @param path The property's path
+ * @param defaultValue The default value
+ * @param The enum type
+ * @return The created enum property
+ */
public static > Property newProperty(Class clazz, String path, E defaultValue) {
return new Property<>(new EnumPropertyType<>(clazz), path, defaultValue);
}
@@ -53,9 +82,8 @@ public class Property {
// -----
// Hooks to the PropertyType methods
// -----
-
/**
- * Get the property value from the given configuration.
+ * Get the property value from the given configuration – guaranteed to never return null.
*
* @param configuration The configuration to read the value from
* @return The value, or default if not present
@@ -64,16 +92,6 @@ public class Property {
return type.getFromFile(this, configuration);
}
- /**
- * Format the property value as YAML.
- *
- * @param configuration The configuration to read the value from
- * @return The property value as YAML
- */
- public List formatValueAsYaml(FileConfiguration configuration) {
- return type.asYaml(this, configuration);
- }
-
/**
* Return whether or not the given configuration file contains the property.
*
@@ -84,10 +102,21 @@ public class Property {
return type.contains(this, configuration);
}
+ /**
+ * Format the property's value as YAML.
+ *
+ * @param configuration The file configuration
+ * @param simpleYaml YAML object (default)
+ * @param singleQuoteYaml YAML object using single quotes
+ * @return The generated YAML
+ */
+ public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) {
+ return type.toYaml(getFromFile(configuration), simpleYaml, singleQuoteYaml);
+ }
+
// -----
// Trivial getters
// -----
-
/**
* Return the default value of the property.
*
diff --git a/src/main/java/fr/xephi/authme/settings/domain/PropertyType.java b/src/main/java/fr/xephi/authme/settings/domain/PropertyType.java
index dc1975bba..28a505cfb 100644
--- a/src/main/java/fr/xephi/authme/settings/domain/PropertyType.java
+++ b/src/main/java/fr/xephi/authme/settings/domain/PropertyType.java
@@ -1,12 +1,10 @@
package fr.xephi.authme.settings.domain;
import org.bukkit.configuration.file.FileConfiguration;
+import org.yaml.snakeyaml.Yaml;
-import java.util.ArrayList;
import java.util.List;
-import static java.util.Arrays.asList;
-
/**
* Handles a certain property type and provides type-specific functionality.
*
@@ -16,7 +14,6 @@ import static java.util.Arrays.asList;
public abstract class PropertyType {
public static final PropertyType BOOLEAN = new BooleanProperty();
- public static final PropertyType DOUBLE = new DoubleProperty();
public static final PropertyType INTEGER = new IntegerProperty();
public static final PropertyType STRING = new StringProperty();
public static final PropertyType> STRING_LIST = new StringListProperty();
@@ -30,17 +27,6 @@ public abstract class PropertyType {
*/
public abstract T getFromFile(Property property, FileConfiguration configuration);
- /**
- * Return the property's value (or its default) as YAML.
- *
- * @param property The property to transform
- * @param configuration The YAML configuration to read from
- * @return The read value or its default in YAML format
- */
- public List asYaml(Property property, FileConfiguration configuration) {
- return asYaml(getFromFile(property, configuration));
- }
-
/**
* Return whether the property is present in the given configuration.
*
@@ -53,12 +39,16 @@ public abstract class PropertyType {
}
/**
- * Transform the given value to YAML.
+ * Format the value as YAML.
*
- * @param value The value to transform
- * @return The value as YAML
+ * @param value The value to export
+ * @param simpleYaml YAML object (default)
+ * @param singleQuoteYaml YAML object set to use single quotes
+ * @return The generated YAML
*/
- protected abstract List asYaml(T value);
+ public String toYaml(T value, Yaml simpleYaml, Yaml singleQuoteYaml) {
+ return simpleYaml.dump(value);
+ }
/**
@@ -69,26 +59,6 @@ public abstract class PropertyType {
public Boolean getFromFile(Property property, FileConfiguration configuration) {
return configuration.getBoolean(property.getPath(), property.getDefaultValue());
}
-
- @Override
- protected List asYaml(Boolean value) {
- return asList(value ? "true" : "false");
- }
- }
-
- /**
- * Double property.
- */
- private static final class DoubleProperty extends PropertyType {
- @Override
- public Double getFromFile(Property property, FileConfiguration configuration) {
- return configuration.getDouble(property.getPath(), property.getDefaultValue());
- }
-
- @Override
- protected List asYaml(Double value) {
- return asList(String.valueOf(value));
- }
}
/**
@@ -99,11 +69,6 @@ public abstract class PropertyType {
public Integer getFromFile(Property property, FileConfiguration configuration) {
return configuration.getInt(property.getPath(), property.getDefaultValue());
}
-
- @Override
- protected List asYaml(Integer value) {
- return asList(String.valueOf(value));
- }
}
/**
@@ -114,15 +79,9 @@ public abstract class PropertyType {
public String getFromFile(Property property, FileConfiguration configuration) {
return configuration.getString(property.getPath(), property.getDefaultValue());
}
-
@Override
- protected List asYaml(String value) {
- return asList(toYamlLiteral(value));
- }
-
- public static String toYamlLiteral(String str) {
- // TODO: Need to handle new lines properly
- return "'" + str.replace("'", "''") + "'";
+ public String toYaml(String value, Yaml simpleYaml, Yaml singleQuoteYaml) {
+ return singleQuoteYaml.dump(value);
}
}
@@ -139,23 +98,18 @@ public abstract class PropertyType {
}
@Override
- protected List asYaml(List value) {
- if (value.isEmpty()) {
- return asList("[]");
- }
-
- List resultLines = new ArrayList<>();
- resultLines.add(""); // add
- for (String entry : value) {
- // TODO: StringProperty#toYamlLiteral will return List...
- resultLines.add(" - " + StringProperty.toYamlLiteral(entry));
- }
- return resultLines;
+ public boolean contains(Property> property, FileConfiguration configuration) {
+ return configuration.contains(property.getPath()) && configuration.isList(property.getPath());
}
@Override
- public boolean contains(Property> property, FileConfiguration configuration) {
- return configuration.contains(property.getPath()) && configuration.isList(property.getPath());
+ public String toYaml(List value, Yaml simpleYaml, Yaml singleQuoteYaml) {
+ String yaml = singleQuoteYaml.dump(value);
+ // If the property is a non-empty list we need to append a new line because it will be
+ // something like the following, which requires a new line:
+ // - 'item 1'
+ // - 'second item in list'
+ return value.isEmpty() ? yaml : "\n" + yaml;
}
}
diff --git a/src/main/java/fr/xephi/authme/settings/custom/BackupSettings.java b/src/main/java/fr/xephi/authme/settings/properties/BackupSettings.java
similarity index 95%
rename from src/main/java/fr/xephi/authme/settings/custom/BackupSettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/BackupSettings.java
index f2e78931b..32c439db2 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/BackupSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/BackupSettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property;
diff --git a/src/main/java/fr/xephi/authme/settings/custom/ConverterSettings.java b/src/main/java/fr/xephi/authme/settings/properties/ConverterSettings.java
similarity index 96%
rename from src/main/java/fr/xephi/authme/settings/custom/ConverterSettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/ConverterSettings.java
index f32cf7483..9dc4ad60a 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/ConverterSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/ConverterSettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property;
diff --git a/src/main/java/fr/xephi/authme/settings/custom/DatabaseSettings.java b/src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java
similarity index 99%
rename from src/main/java/fr/xephi/authme/settings/custom/DatabaseSettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java
index 84f0b7085..49ddc597b 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/DatabaseSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.settings.domain.Comment;
diff --git a/src/main/java/fr/xephi/authme/settings/custom/EmailSettings.java b/src/main/java/fr/xephi/authme/settings/properties/EmailSettings.java
similarity index 98%
rename from src/main/java/fr/xephi/authme/settings/custom/EmailSettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/EmailSettings.java
index 683143652..7b7ee3cef 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/EmailSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/EmailSettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property;
diff --git a/src/main/java/fr/xephi/authme/settings/custom/HooksSettings.java b/src/main/java/fr/xephi/authme/settings/properties/HooksSettings.java
similarity index 98%
rename from src/main/java/fr/xephi/authme/settings/custom/HooksSettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/HooksSettings.java
index af0458ac4..b20d28686 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/HooksSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/HooksSettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property;
diff --git a/src/main/java/fr/xephi/authme/settings/custom/PluginSettings.java b/src/main/java/fr/xephi/authme/settings/properties/PluginSettings.java
similarity index 98%
rename from src/main/java/fr/xephi/authme/settings/custom/PluginSettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/PluginSettings.java
index e35076db2..6fea29fb0 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/PluginSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/PluginSettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property;
diff --git a/src/main/java/fr/xephi/authme/settings/custom/ProtectionSettings.java b/src/main/java/fr/xephi/authme/settings/properties/ProtectionSettings.java
similarity index 97%
rename from src/main/java/fr/xephi/authme/settings/custom/ProtectionSettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/ProtectionSettings.java
index 2582c277f..f5a51215e 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/ProtectionSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/ProtectionSettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property;
diff --git a/src/main/java/fr/xephi/authme/settings/custom/PurgeSettings.java b/src/main/java/fr/xephi/authme/settings/properties/PurgeSettings.java
similarity index 98%
rename from src/main/java/fr/xephi/authme/settings/custom/PurgeSettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/PurgeSettings.java
index 5fcc139d7..b4de9abfc 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/PurgeSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/PurgeSettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property;
diff --git a/src/main/java/fr/xephi/authme/settings/custom/RegistrationSettings.java b/src/main/java/fr/xephi/authme/settings/properties/RegistrationSettings.java
similarity index 99%
rename from src/main/java/fr/xephi/authme/settings/custom/RegistrationSettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/RegistrationSettings.java
index 7e8301456..129e4ab97 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/RegistrationSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/RegistrationSettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property;
diff --git a/src/main/java/fr/xephi/authme/settings/custom/RestrictionSettings.java b/src/main/java/fr/xephi/authme/settings/properties/RestrictionSettings.java
similarity index 99%
rename from src/main/java/fr/xephi/authme/settings/custom/RestrictionSettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/RestrictionSettings.java
index ae5fe63db..386e130c0 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/RestrictionSettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/RestrictionSettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property;
diff --git a/src/main/java/fr/xephi/authme/settings/custom/SecuritySettings.java b/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java
similarity index 95%
rename from src/main/java/fr/xephi/authme/settings/custom/SecuritySettings.java
rename to src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java
index 94e33258c..6a2ace715 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/SecuritySettings.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/SecuritySettings.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.settings.domain.Comment;
@@ -30,6 +30,10 @@ public class SecuritySettings implements SettingsClass {
public static final Property REMOVE_PASSWORD_FROM_CONSOLE =
newProperty("Security.console.removePassword", true);
+ @Comment("Copy AuthMe log output in a separate file as well?")
+ public static final Property USE_LOGGING =
+ newProperty("Security.console.logConsole", true);
+
@Comment("Player need to put a captcha when he fails too lot the password")
public static final Property USE_CAPTCHA =
newProperty("Security.captcha.useCaptcha", false);
diff --git a/src/main/java/fr/xephi/authme/settings/custom/SettingsFieldRetriever.java b/src/main/java/fr/xephi/authme/settings/properties/SettingsFieldRetriever.java
similarity index 80%
rename from src/main/java/fr/xephi/authme/settings/custom/SettingsFieldRetriever.java
rename to src/main/java/fr/xephi/authme/settings/properties/SettingsFieldRetriever.java
index 74b722e8f..cedd358ee 100644
--- a/src/main/java/fr/xephi/authme/settings/custom/SettingsFieldRetriever.java
+++ b/src/main/java/fr/xephi/authme/settings/properties/SettingsFieldRetriever.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Comment;
import fr.xephi.authme.settings.domain.Property;
@@ -12,9 +12,10 @@ import java.util.Arrays;
import java.util.List;
/**
- * Utility class responsible for the retrieval of all {@link Property} fields via reflections.
+ * Utility class responsible for retrieving all {@link Property} fields
+ * from {@link SettingsClass} implementations via reflection.
*/
-final class SettingsFieldRetriever {
+public final class SettingsFieldRetriever {
/** The classes to scan for properties. */
private static final List> CONFIGURATION_CLASSES = Arrays.asList(
@@ -37,7 +38,7 @@ final class SettingsFieldRetriever {
for (Class> clazz : CONFIGURATION_CLASSES) {
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
- Property property = getFieldIfRelevant(field);
+ Property property = getPropertyField(field);
if (property != null) {
properties.put(property, getCommentsForField(field));
}
@@ -53,7 +54,13 @@ final class SettingsFieldRetriever {
return new String[0];
}
- private static Property> getFieldIfRelevant(Field field) {
+ /**
+ * Return the given field's value if it is a static {@link Property}.
+ *
+ * @param field The field's value to return
+ * @return The property the field defines, or null if not applicable
+ */
+ private static Property> getPropertyField(Field field) {
field.setAccessible(true);
if (field.isAccessible() && Property.class.equals(field.getType()) && Modifier.isStatic(field.getModifiers())) {
try {
diff --git a/src/main/java/fr/xephi/authme/util/CollectionUtils.java b/src/main/java/fr/xephi/authme/util/CollectionUtils.java
index 13077547c..6ec617a2c 100644
--- a/src/main/java/fr/xephi/authme/util/CollectionUtils.java
+++ b/src/main/java/fr/xephi/authme/util/CollectionUtils.java
@@ -52,11 +52,12 @@ public final class CollectionUtils {
}
/**
- * @param element
- * @param coll Collection
- * @return boolean Boolean
+ * Null-safe way to check whether a collection is empty or not.
+ *
+ * @param coll The collection to verify
+ * @return True if the collection is null or empty, false otherwise
*/
- public static boolean isEmpty(Collection coll) {
+ public static boolean isEmpty(Collection> coll) {
return coll == null || coll.isEmpty();
}
diff --git a/src/main/java/fr/xephi/authme/util/StringUtils.java b/src/main/java/fr/xephi/authme/util/StringUtils.java
index 9ae0ec0fd..377dd9f75 100644
--- a/src/main/java/fr/xephi/authme/util/StringUtils.java
+++ b/src/main/java/fr/xephi/authme/util/StringUtils.java
@@ -4,6 +4,7 @@ import net.ricecode.similarity.LevenshteinDistanceStrategy;
import net.ricecode.similarity.StringSimilarityService;
import net.ricecode.similarity.StringSimilarityServiceImpl;
+import java.io.File;
import java.util.Arrays;
/**
@@ -37,12 +38,12 @@ public final class StringUtils {
}
/**
- * Returns whether the given string contains any of the provided elements.
+ * Return whether the given string contains any of the provided elements.
*
- * @param str the string to analyze
- * @param pieces the items to check the string for
+ * @param str The string to analyze
+ * @param pieces The items to check the string for
*
- * @return true if the string contains at least one of the items
+ * @return True if the string contains at least one of the items
*/
public static boolean containsAny(String str, String... pieces) {
if (str == null) {
@@ -60,21 +61,21 @@ public final class StringUtils {
* Null-safe method for checking whether a string is empty. Note that the string
* is trimmed, so this method also considers a string with whitespace as empty.
*
- * @param str the string to verify
+ * @param str The string to verify
*
- * @return true if the string is empty, false otherwise
+ * @return True if the string is empty, false otherwise
*/
public static boolean isEmpty(String str) {
return str == null || str.trim().isEmpty();
}
/**
- * Joins a list of elements into a single string with the specified delimiter.
+ * Join a list of elements into a single string with the specified delimiter.
*
- * @param delimiter the delimiter to use
- * @param elements the elements to join
+ * @param delimiter The delimiter to use
+ * @param elements The elements to join
*
- * @return a new String that is composed of the elements separated by the delimiter
+ * @return A new String that is composed of the elements separated by the delimiter
*/
public static String join(String delimiter, Iterable elements) {
if (delimiter == null) {
@@ -95,12 +96,12 @@ public final class StringUtils {
}
/**
- * Joins a list of elements into a single string with the specified delimiter.
+ * Join a list of elements into a single string with the specified delimiter.
*
- * @param delimiter the delimiter to use
- * @param elements the elements to join
+ * @param delimiter The delimiter to use
+ * @param elements The elements to join
*
- * @return a new String that is composed of the elements separated by the delimiter
+ * @return A new String that is composed of the elements separated by the delimiter
*/
public static String join(String delimiter, String... elements) {
return join(delimiter, Arrays.asList(elements));
@@ -117,4 +118,15 @@ public final class StringUtils {
return "[" + th.getClass().getSimpleName() + "]: " + th.getMessage();
}
+ /**
+ * Construct a file path from the given elements, i.e. separate the given elements by the file separator.
+ *
+ * @param elements The elements to create a path with
+ *
+ * @return The created path
+ */
+ public static String makePath(String... elements) {
+ return join(File.separator, elements);
+ }
+
}
diff --git a/src/main/java/fr/xephi/authme/util/Utils.java b/src/main/java/fr/xephi/authme/util/Utils.java
index 58d296bfa..f12c8b341 100644
--- a/src/main/java/fr/xephi/authme/util/Utils.java
+++ b/src/main/java/fr/xephi/authme/util/Utils.java
@@ -7,8 +7,10 @@ import fr.xephi.authme.cache.limbo.LimboCache;
import fr.xephi.authme.cache.limbo.LimboPlayer;
import fr.xephi.authme.events.AuthMeTeleportEvent;
import fr.xephi.authme.permission.PermissionsManager;
+import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.settings.properties.EmailSettings;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
@@ -19,6 +21,7 @@ import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
/**
* Utility class for various operations used in the codebase.
@@ -254,6 +257,30 @@ public final class Utils {
}
}
+ public static boolean isEmailCorrect(String email, NewSetting settings) {
+ if (!email.contains("@") || "your@email.com".equalsIgnoreCase(email)) {
+ return false;
+ }
+ final String emailDomain = email.split("@")[1];
+
+ List whitelist = settings.getProperty(EmailSettings.DOMAIN_WHITELIST);
+ if (!CollectionUtils.isEmpty(whitelist)) {
+ return containsIgnoreCase(whitelist, emailDomain);
+ }
+
+ List blacklist = settings.getProperty(EmailSettings.DOMAIN_BLACKLIST);
+ return CollectionUtils.isEmpty(blacklist) || !containsIgnoreCase(blacklist, emailDomain);
+ }
+
+ private static boolean containsIgnoreCase(Collection coll, String needle) {
+ for (String entry : coll) {
+ if (entry.equalsIgnoreCase(needle)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
*/
public enum GroupType {
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 67fa18a4e..c9cdbfe64 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -308,6 +308,8 @@ Security:
noConsoleSpam: false
# Replace passwords in the console when player type a command like /login
removePassword: true
+ # Copy AuthMe log output in a separate file as well?
+ logConsole: true
captcha:
# Player need to put a captcha when he fails too lot the password
useCaptcha: false
diff --git a/src/main/resources/welcome.txt b/src/main/resources/welcome.txt
new file mode 100644
index 000000000..1c49f042b
--- /dev/null
+++ b/src/main/resources/welcome.txt
@@ -0,0 +1,3 @@
+Welcome {PLAYER} on {SERVER} server
+
+This server uses AuthMeReloaded protection!
diff --git a/src/test/java/fr/xephi/authme/ConsoleLoggerTestInitializer.java b/src/test/java/fr/xephi/authme/ConsoleLoggerTestInitializer.java
new file mode 100644
index 000000000..cfa871e3e
--- /dev/null
+++ b/src/test/java/fr/xephi/authme/ConsoleLoggerTestInitializer.java
@@ -0,0 +1,20 @@
+package fr.xephi.authme;
+
+import org.mockito.Mockito;
+
+import java.util.logging.Logger;
+
+/**
+ * Test initializer for {@link ConsoleLogger}.
+ */
+public class ConsoleLoggerTestInitializer {
+
+ private ConsoleLoggerTestInitializer() {
+ }
+
+ public static Logger setupLogger() {
+ Logger logger = Mockito.mock(Logger.class);
+ ConsoleLogger.setLogger(logger);
+ return logger;
+ }
+}
diff --git a/src/test/java/fr/xephi/authme/command/CommandServiceTest.java b/src/test/java/fr/xephi/authme/command/CommandServiceTest.java
index e3e67e3ed..4ebd4c8a9 100644
--- a/src/test/java/fr/xephi/authme/command/CommandServiceTest.java
+++ b/src/test/java/fr/xephi/authme/command/CommandServiceTest.java
@@ -8,8 +8,8 @@ import fr.xephi.authme.output.Messages;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.process.Management;
import fr.xephi.authme.security.PasswordSecurity;
-import fr.xephi.authme.settings.custom.NewSetting;
-import fr.xephi.authme.settings.custom.SecuritySettings;
+import fr.xephi.authme.settings.NewSetting;
+import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.settings.domain.Property;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -18,6 +18,7 @@ import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import java.io.File;
import java.util.Arrays;
import java.util.List;
@@ -95,19 +96,6 @@ public class CommandServiceTest {
verify(commandMapper).mapPartsToCommand(sender, commandParts);
}
- @Test
- @Ignore
- public void shouldRunTaskInAsync() {
- // given
- Runnable runnable = mock(Runnable.class);
-
- // when
- commandService.runTaskAsynchronously(runnable);
-
- // then
- // TODO ljacqu 20151226: AuthMe#getServer() is final, i.e. not mockable
- }
-
@Test
public void shouldGetDataSource() {
// given
@@ -193,10 +181,40 @@ public class CommandServiceTest {
given(settings.getProperty(property)).willReturn(7);
// when
- int result = settings.getProperty(property);
+ int result = commandService.getProperty(property);
// then
assertThat(result, equalTo(7));
verify(settings).getProperty(property);
}
+
+ @Test
+ public void shouldReloadMessages() {
+ // given
+ File file = new File("some/bogus-file.test");
+
+ // when
+ commandService.reloadMessages(file);
+
+ // then
+ verify(messages).reload(file);
+ }
+
+ @Test
+ public void shouldReturnSettings() {
+ // given/when
+ NewSetting result = commandService.getSettings();
+
+ // then
+ assertThat(result, equalTo(settings));
+ }
+
+ @Test
+ public void shouldReturnAuthMe() {
+ // given/when
+ AuthMe result = commandService.getAuthMe();
+
+ // then
+ assertThat(result, equalTo(authMe));
+ }
}
diff --git a/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java
index c33b13ef3..b3b54a1c4 100644
--- a/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/captcha/CaptchaCommandTest.java
@@ -5,7 +5,7 @@ import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.command.ExecutableCommand;
import fr.xephi.authme.output.MessageKey;
import fr.xephi.authme.output.Messages;
-import fr.xephi.authme.settings.custom.SecuritySettings;
+import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.util.WrapperMock;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.CommandSender;
diff --git a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java
index d00a4e37d..3936e5069 100644
--- a/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java
+++ b/src/test/java/fr/xephi/authme/command/executable/changepassword/ChangePasswordCommandTest.java
@@ -4,8 +4,8 @@ import fr.xephi.authme.ReflectionTestUtils;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.command.CommandService;
import fr.xephi.authme.output.MessageKey;
-import fr.xephi.authme.settings.custom.RestrictionSettings;
-import fr.xephi.authme.settings.custom.SecuritySettings;
+import fr.xephi.authme.settings.properties.RestrictionSettings;
+import fr.xephi.authme.settings.properties.SecuritySettings;
import fr.xephi.authme.task.ChangePasswordTask;
import fr.xephi.authme.util.WrapperMock;
import org.bukkit.Server;
diff --git a/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java b/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java
index cb9c85012..45e4d4240 100644
--- a/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java
+++ b/src/test/java/fr/xephi/authme/command/help/HelpProviderTest.java
@@ -6,7 +6,6 @@ import fr.xephi.authme.command.FoundResultStatus;
import fr.xephi.authme.command.TestCommandsUtil;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.permission.PlayerPermission;
-import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.WrapperMock;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@@ -40,22 +39,22 @@ import static org.mockito.Mockito.mock;
*/
public class HelpProviderTest {
+ private static final String HELP_HEADER = "Help";
+ private static Set commands;
private HelpProvider helpProvider;
private PermissionsManager permissionsManager;
private CommandSender sender;
- private static Set commands;
@BeforeClass
public static void setUpCommands() {
WrapperMock.createInstance();
- Settings.helpHeader = "Help";
commands = TestCommandsUtil.generateCommands();
}
@Before
public void setUpHelpProvider() {
permissionsManager = mock(PermissionsManager.class);
- helpProvider = new HelpProvider(permissionsManager);
+ helpProvider = new HelpProvider(permissionsManager, HELP_HEADER);
sender = mock(CommandSender.class);
}
@@ -70,7 +69,7 @@ public class HelpProviderTest {
// then
assertThat(lines, hasSize(5));
- assertThat(lines.get(0), containsString(Settings.helpHeader + " HELP"));
+ assertThat(lines.get(0), containsString(HELP_HEADER + " HELP"));
assertThat(removeColors(lines.get(1)), containsString("Command: /authme login "));
assertThat(removeColors(lines.get(2)), containsString("Short description: login cmd"));
assertThat(removeColors(lines.get(3)), equalTo("Detailed description:"));
@@ -88,7 +87,7 @@ public class HelpProviderTest {
// then
assertThat(lines, hasSize(4));
- assertThat(lines.get(0), containsString(Settings.helpHeader + " HELP"));
+ assertThat(lines.get(0), containsString(HELP_HEADER + " HELP"));
assertThat(removeColors(lines.get(1)), equalTo("Arguments:"));
assertThat(removeColors(lines.get(2)), containsString("password: 'password' argument description"));
assertThat(removeColors(lines.get(3)), containsString("confirmation: 'confirmation' argument description"));
@@ -279,7 +278,7 @@ public class HelpProviderTest {
// then
assertThat(lines, hasSize(2));
- assertThat(lines.get(0), containsString(Settings.helpHeader + " HELP"));
+ assertThat(lines.get(0), containsString(HELP_HEADER + " HELP"));
assertThat(removeColors(lines.get(1)), containsString("Command: /authme register "));
}
diff --git a/src/test/java/fr/xephi/authme/output/Log4JFilterTest.java b/src/test/java/fr/xephi/authme/output/Log4JFilterTest.java
index fdd338919..b9977de8e 100644
--- a/src/test/java/fr/xephi/authme/output/Log4JFilterTest.java
+++ b/src/test/java/fr/xephi/authme/output/Log4JFilterTest.java
@@ -219,8 +219,8 @@ public class Log4JFilterTest {
* Mocks a {@link Message} object and makes it return the given formatted message.
*
* @param formattedMessage the formatted message the mock should return
-
- * @return Message mock */
+ * @return Message mock
+ */
private static Message mockMessage(String formattedMessage) {
Message message = Mockito.mock(Message.class);
when(message.getFormattedMessage()).thenReturn(formattedMessage);
diff --git a/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java b/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java
index 343a56871..2d3e7b08f 100644
--- a/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java
+++ b/src/test/java/fr/xephi/authme/output/MessagesIntegrationTest.java
@@ -1,10 +1,11 @@
package fr.xephi.authme.output;
-import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.util.WrapperMock;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
@@ -28,6 +29,12 @@ public class MessagesIntegrationTest {
private static final String YML_TEST_FILE = "messages_test.yml";
private Messages messages;
+ @BeforeClass
+ public static void setup() {
+ WrapperMock.createInstance();
+ ConsoleLoggerTestInitializer.setupLogger();
+ }
+
/**
* Loads the messages in the file {@code messages_test.yml} in the test resources folder.
* The file does not contain all messages defined in {@link MessageKey} and its contents
@@ -35,17 +42,12 @@ public class MessagesIntegrationTest {
*/
@Before
public void setUpMessages() {
- WrapperMock.createInstance();
-
- Settings.messagesLanguage = "en";
URL url = getClass().getClassLoader().getResource(YML_TEST_FILE);
if (url == null) {
throw new RuntimeException("File '" + YML_TEST_FILE + "' could not be loaded");
}
- Settings.messageFile = new File(url.getFile());
- Settings.messagesLanguage = "en";
- messages = Messages.getInstance();
+ messages = new Messages(new File(url.getFile()));
}
@Test
diff --git a/src/test/java/fr/xephi/authme/security/crypts/BcryptTest.java b/src/test/java/fr/xephi/authme/security/crypts/BcryptTest.java
index 106689ae7..6ee291143 100644
--- a/src/test/java/fr/xephi/authme/security/crypts/BcryptTest.java
+++ b/src/test/java/fr/xephi/authme/security/crypts/BcryptTest.java
@@ -1,5 +1,6 @@
package fr.xephi.authme.security.crypts;
+import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.util.WrapperMock;
import org.junit.BeforeClass;
@@ -13,6 +14,7 @@ public class BcryptTest extends AbstractEncryptionMethodTest {
public static void setUpSettings() {
WrapperMock.createInstance();
Settings.bCryptLog2Rounds = 8;
+ ConsoleLoggerTestInitializer.setupLogger();
}
public BcryptTest() {
diff --git a/src/test/java/fr/xephi/authme/security/crypts/XFBCRYPTTest.java b/src/test/java/fr/xephi/authme/security/crypts/XFBCRYPTTest.java
index 3b7294a04..ed49ccd71 100644
--- a/src/test/java/fr/xephi/authme/security/crypts/XFBCRYPTTest.java
+++ b/src/test/java/fr/xephi/authme/security/crypts/XFBCRYPTTest.java
@@ -1,5 +1,6 @@
package fr.xephi.authme.security.crypts;
+import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.util.WrapperMock;
import org.junit.BeforeClass;
@@ -9,8 +10,9 @@ import org.junit.BeforeClass;
public class XFBCRYPTTest extends AbstractEncryptionMethodTest {
@BeforeClass
- public static void setUpWrapper() {
+ public static void setup() {
WrapperMock.createInstance();
+ ConsoleLoggerTestInitializer.setupLogger();
}
public XFBCRYPTTest() {
diff --git a/src/test/java/fr/xephi/authme/settings/custom/ConfigFileConsistencyTest.java b/src/test/java/fr/xephi/authme/settings/ConfigFileConsistencyTest.java
similarity index 86%
rename from src/test/java/fr/xephi/authme/settings/custom/ConfigFileConsistencyTest.java
rename to src/test/java/fr/xephi/authme/settings/ConfigFileConsistencyTest.java
index d012a50a4..755dcc461 100644
--- a/src/test/java/fr/xephi/authme/settings/custom/ConfigFileConsistencyTest.java
+++ b/src/test/java/fr/xephi/authme/settings/ConfigFileConsistencyTest.java
@@ -1,7 +1,7 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings;
-import fr.xephi.authme.ReflectionTestUtils;
import fr.xephi.authme.settings.domain.Property;
+import fr.xephi.authme.settings.properties.SettingsFieldRetriever;
import fr.xephi.authme.settings.propertymap.PropertyMap;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.configuration.MemorySection;
@@ -34,16 +34,14 @@ public class ConfigFileConsistencyTest {
// given
URL url = this.getClass().getResource(CONFIG_FILE);
File configFile = new File(url.getFile());
- NewSetting settings = new NewSetting(YamlConfiguration.loadConfiguration(configFile), new File("bogus"), null);
+ FileConfiguration configuration = YamlConfiguration.loadConfiguration(configFile);
// when
- boolean result = settings.containsAllSettings(SettingsFieldRetriever.getAllPropertyFields());
+ boolean result = SettingsMigrationService.containsAllSettings(
+ configuration, SettingsFieldRetriever.getAllPropertyFields());
// then
if (!result) {
- FileConfiguration configuration =
- (FileConfiguration) ReflectionTestUtils.getFieldValue(NewSetting.class, settings, "configuration");
-
Set knownProperties = getAllKnownPropertyPaths();
List missingProperties = new ArrayList<>();
for (String path : knownProperties) {
diff --git a/src/test/java/fr/xephi/authme/settings/custom/NewSettingIntegrationTest.java b/src/test/java/fr/xephi/authme/settings/NewSettingIntegrationTest.java
similarity index 54%
rename from src/test/java/fr/xephi/authme/settings/custom/NewSettingIntegrationTest.java
rename to src/test/java/fr/xephi/authme/settings/NewSettingIntegrationTest.java
index 73b80b020..646c18456 100644
--- a/src/test/java/fr/xephi/authme/settings/custom/NewSettingIntegrationTest.java
+++ b/src/test/java/fr/xephi/authme/settings/NewSettingIntegrationTest.java
@@ -1,11 +1,13 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings;
import com.google.common.collect.ImmutableMap;
import fr.xephi.authme.ReflectionTestUtils;
import fr.xephi.authme.settings.domain.Property;
+import fr.xephi.authme.settings.properties.TestConfiguration;
+import fr.xephi.authme.settings.properties.TestEnum;
import fr.xephi.authme.settings.propertymap.PropertyMap;
+import fr.xephi.authme.util.WrapperMock;
import org.bukkit.configuration.file.YamlConfiguration;
-import org.junit.BeforeClass;
import org.junit.Test;
import java.io.File;
@@ -13,8 +15,10 @@ import java.lang.reflect.Field;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
+import static fr.xephi.authme.settings.domain.Property.newProperty;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.junit.Assume.assumeThat;
@@ -28,40 +32,28 @@ public class NewSettingIntegrationTest {
private static final String COMPLETE_FILE = "config-sample-values.yml";
/** File name of the sample config missing certain {@link TestConfiguration} values. */
private static final String INCOMPLETE_FILE = "config-incomplete-sample.yml";
+ /** File name for testing difficult values. */
+ private static final String DIFFICULT_FILE = "config-difficult-values.yml";
- private static PropertyMap propertyMap;
-
- @BeforeClass
- public static void generatePropertyMap() {
- propertyMap = new PropertyMap();
- for (Field field : TestConfiguration.class.getDeclaredFields()) {
- Object fieldValue = ReflectionTestUtils.getFieldValue(TestConfiguration.class, null, field.getName());
- if (fieldValue instanceof Property>) {
- Property> property = (Property>) fieldValue;
- String[] comments = new String[]{"Comment for '" + property.getPath() + "'"};
- propertyMap.put(property, comments);
- }
- }
- }
+ private static PropertyMap propertyMap = generatePropertyMap();
@Test
public void shouldLoadAndReadAllProperties() {
// given
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(getConfigFile(COMPLETE_FILE));
File file = new File("unused");
- assumeThat(file.exists(), equalTo(false));
// when / then
NewSetting settings = new NewSetting(configuration, file, propertyMap);
Map, Object> expectedValues = ImmutableMap., Object>builder()
.put(TestConfiguration.DURATION_IN_SECONDS, 22)
.put(TestConfiguration.SYSTEM_NAME, "Custom sys name")
- .put(TestConfiguration.RATIO_LIMIT, -4.1)
+ .put(TestConfiguration.RATIO_ORDER, TestEnum.FIRST)
.put(TestConfiguration.RATIO_FIELDS, Arrays.asList("Australia", "Burundi", "Colombia"))
.put(TestConfiguration.VERSION_NUMBER, 2492)
.put(TestConfiguration.SKIP_BORING_FEATURES, false)
.put(TestConfiguration.BORING_COLORS, Arrays.asList("beige", "gray"))
- .put(TestConfiguration.DUST_LEVEL, 0.81)
+ .put(TestConfiguration.DUST_LEVEL, 2)
.put(TestConfiguration.USE_COOL_FEATURES, true)
.put(TestConfiguration.COOL_OPTIONS, Arrays.asList("Dinosaurs", "Explosions", "Big trucks"))
.build();
@@ -89,12 +81,12 @@ public class NewSettingIntegrationTest {
Map, Object> expectedValues = ImmutableMap., Object>builder()
.put(TestConfiguration.DURATION_IN_SECONDS, 22)
.put(TestConfiguration.SYSTEM_NAME, "[TestDefaultValue]")
- .put(TestConfiguration.RATIO_LIMIT, 3.0)
+ .put(TestConfiguration.RATIO_ORDER, TestEnum.SECOND)
.put(TestConfiguration.RATIO_FIELDS, Arrays.asList("Australia", "Burundi", "Colombia"))
.put(TestConfiguration.VERSION_NUMBER, 32046)
.put(TestConfiguration.SKIP_BORING_FEATURES, false)
.put(TestConfiguration.BORING_COLORS, Collections.EMPTY_LIST)
- .put(TestConfiguration.DUST_LEVEL, 0.2)
+ .put(TestConfiguration.DUST_LEVEL, -1)
.put(TestConfiguration.USE_COOL_FEATURES, false)
.put(TestConfiguration.COOL_OPTIONS, Arrays.asList("Dinosaurs", "Explosions", "Big trucks"))
.build();
@@ -104,6 +96,62 @@ public class NewSettingIntegrationTest {
}
}
+ /** Verify that "difficult cases" such as apostrophes in strings etc. are handled properly. */
+ @Test
+ public void shouldProperlyExportAnyValues() {
+ // given
+ File file = getConfigFile(DIFFICULT_FILE);
+ YamlConfiguration configuration = YamlConfiguration.loadConfiguration(file);
+ assumeThat(configuration.contains(TestConfiguration.DUST_LEVEL.getPath()), equalTo(false));
+
+ // Additional string properties
+ List> additionalProperties = Arrays.asList(
+ newProperty("more.string1", "it's a text with some \\'apostrophes'"),
+ newProperty("more.string2", "\tthis one\nhas some\nnew '' lines-test")
+ );
+ PropertyMap propertyMap = generatePropertyMap();
+ for (Property> property : additionalProperties) {
+ propertyMap.put(property, new String[0]);
+ }
+
+ // when
+ new NewSetting(configuration, file, propertyMap);
+ // reload the file as settings should hav been rewritten
+ configuration = YamlConfiguration.loadConfiguration(file);
+
+ // then
+ // assert that we won't rewrite the settings again! One rewrite should produce a valid, complete configuration
+ File unusedFile = new File("config-difficult-values.unused.yml");
+ NewSetting settings = new NewSetting(configuration, unusedFile, propertyMap);
+ assertThat(unusedFile.exists(), equalTo(false));
+ assertThat(configuration.contains(TestConfiguration.DUST_LEVEL.getPath()), equalTo(true));
+
+ Map, Object> expectedValues = ImmutableMap., Object>builder()
+ .put(TestConfiguration.DURATION_IN_SECONDS, 20)
+ .put(TestConfiguration.SYSTEM_NAME, "A 'test' name")
+ .put(TestConfiguration.RATIO_ORDER, TestEnum.FOURTH)
+ .put(TestConfiguration.RATIO_FIELDS, Arrays.asList("Australia\\", "\tBurundi'", "Colombia?\n''"))
+ .put(TestConfiguration.VERSION_NUMBER, -1337)
+ .put(TestConfiguration.SKIP_BORING_FEATURES, false)
+ .put(TestConfiguration.BORING_COLORS, Arrays.asList("it's a difficult string!", "gray\nwith new lines\n"))
+ .put(TestConfiguration.DUST_LEVEL, -1)
+ .put(TestConfiguration.USE_COOL_FEATURES, true)
+ .put(TestConfiguration.COOL_OPTIONS, Collections.EMPTY_LIST)
+ .put(additionalProperties.get(0), additionalProperties.get(0).getDefaultValue())
+ .put(additionalProperties.get(1), additionalProperties.get(1).getDefaultValue())
+ .build();
+ for (Map.Entry, Object> entry : expectedValues.entrySet()) {
+ assertThat("Property '" + entry.getKey().getPath() + "' has expected value"
+ + entry.getValue() + " but found " + settings.getProperty(entry.getKey()),
+ settings.getProperty(entry.getKey()), equalTo(entry.getValue()));
+ }
+ }
+
+ /**
+ * Return a {@link File} instance to an existing file in the target/test-classes folder.
+ *
+ * @return The generated File
+ */
private File getConfigFile(String file) {
URL url = getClass().getClassLoader().getResource(file);
if (url == null) {
@@ -112,4 +160,23 @@ public class NewSettingIntegrationTest {
return new File(url.getFile());
}
+ /**
+ * Generate a property map with all properties in {@link TestConfiguration}.
+ *
+ * @return The generated property map
+ */
+ private static PropertyMap generatePropertyMap() {
+ WrapperMock.createInstance();
+ PropertyMap propertyMap = new PropertyMap();
+ for (Field field : TestConfiguration.class.getDeclaredFields()) {
+ Object fieldValue = ReflectionTestUtils.getFieldValue(TestConfiguration.class, null, field.getName());
+ if (fieldValue instanceof Property>) {
+ Property> property = (Property>) fieldValue;
+ String[] comments = new String[]{"Comment for '" + property.getPath() + "'"};
+ propertyMap.put(property, comments);
+ }
+ }
+ return propertyMap;
+ }
+
}
diff --git a/src/test/java/fr/xephi/authme/settings/custom/NewSettingTest.java b/src/test/java/fr/xephi/authme/settings/NewSettingTest.java
similarity index 87%
rename from src/test/java/fr/xephi/authme/settings/custom/NewSettingTest.java
rename to src/test/java/fr/xephi/authme/settings/NewSettingTest.java
index 64e213aed..8ae651289 100644
--- a/src/test/java/fr/xephi/authme/settings/custom/NewSettingTest.java
+++ b/src/test/java/fr/xephi/authme/settings/NewSettingTest.java
@@ -1,6 +1,9 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings;
import fr.xephi.authme.settings.domain.Property;
+import fr.xephi.authme.settings.properties.TestConfiguration;
+import fr.xephi.authme.settings.properties.TestEnum;
+import fr.xephi.authme.settings.propertymap.PropertyMap;
import org.bukkit.configuration.file.YamlConfiguration;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
@@ -35,15 +38,15 @@ public class NewSettingTest {
setReturnValue(file, TestConfiguration.VERSION_NUMBER, 20);
setReturnValue(file, TestConfiguration.SKIP_BORING_FEATURES, true);
- setReturnValue(file, TestConfiguration.RATIO_LIMIT, 4.25);
+ setReturnValue(file, TestConfiguration.RATIO_ORDER, TestEnum.THIRD);
setReturnValue(file, TestConfiguration.SYSTEM_NAME, "myTestSys");
// when / then
- NewSetting settings = new NewSetting(file, new File("conf.txt"), null);
+ NewSetting settings = new NewSetting(file, new File("conf.txt"), (PropertyMap) null);
assertThat(settings.getProperty(TestConfiguration.VERSION_NUMBER), equalTo(20));
assertThat(settings.getProperty(TestConfiguration.SKIP_BORING_FEATURES), equalTo(true));
- assertThat(settings.getProperty(TestConfiguration.RATIO_LIMIT), equalTo(4.25));
+ assertThat(settings.getProperty(TestConfiguration.RATIO_ORDER), equalTo(TestEnum.THIRD));
assertThat(settings.getProperty(TestConfiguration.SYSTEM_NAME), equalTo("myTestSys"));
assertDefaultValue(TestConfiguration.DURATION_IN_SECONDS, settings);
@@ -58,8 +61,8 @@ public class NewSettingTest {
when(config.getInt(eq(property.getPath()), anyInt())).thenReturn((Integer) value);
} else if (value instanceof Boolean) {
when(config.getBoolean(eq(property.getPath()), anyBoolean())).thenReturn((Boolean) value);
- } else if (value instanceof Double) {
- when(config.getDouble(eq(property.getPath()), anyDouble())).thenReturn((Double) value);
+ } else if (value instanceof Enum>) {
+ when(config.getString(property.getPath())).thenReturn(((Enum>) value).name());
} else {
throw new UnsupportedOperationException("Value has unsupported type '"
+ (value == null ? "null" : value.getClass().getSimpleName()) + "'");
diff --git a/src/test/java/fr/xephi/authme/settings/domain/PropertyTypeTest.java b/src/test/java/fr/xephi/authme/settings/domain/PropertyTypeTest.java
index 6dce2ad3e..df0120631 100644
--- a/src/test/java/fr/xephi/authme/settings/domain/PropertyTypeTest.java
+++ b/src/test/java/fr/xephi/authme/settings/domain/PropertyTypeTest.java
@@ -13,7 +13,6 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyDouble;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
@@ -33,8 +32,6 @@ public class PropertyTypeTest {
when(configuration.getBoolean(eq("bool.path.test"), anyBoolean())).thenReturn(true);
when(configuration.getBoolean(eq("bool.path.wrong"), anyBoolean())).thenAnswer(secondParameter());
- when(configuration.getDouble(eq("double.path.test"), anyDouble())).thenReturn(-6.4);
- when(configuration.getDouble(eq("double.path.wrong"), anyDouble())).thenAnswer(secondParameter());
when(configuration.getInt(eq("int.path.test"), anyInt())).thenReturn(27);
when(configuration.getInt(eq("int.path.wrong"), anyInt())).thenAnswer(secondParameter());
when(configuration.getString(eq("str.path.test"), anyString())).thenReturn("Test value");
@@ -69,31 +66,6 @@ public class PropertyTypeTest {
assertThat(result, equalTo(true));
}
- /* Double */
- @Test
- public void shouldGetDoubleValue() {
- // given
- Property property = Property.newProperty(PropertyType.DOUBLE, "double.path.test", 3.8);
-
- // when
- double result = property.getFromFile(configuration);
-
- // then
- assertThat(result, equalTo(-6.4));
- }
-
- @Test
- public void shouldGetDoubleDefault() {
- // given
- Property property = Property.newProperty(PropertyType.DOUBLE, "double.path.wrong", 12.0);
-
- // when
- double result = property.getFromFile(configuration);
-
- // then
- assertThat(result, equalTo(12.0));
- }
-
/* Integer */
@Test
public void shouldGetIntValue() {
diff --git a/src/test/java/fr/xephi/authme/settings/custom/SettingsClassConsistencyTest.java b/src/test/java/fr/xephi/authme/settings/properties/SettingsClassConsistencyTest.java
similarity index 98%
rename from src/test/java/fr/xephi/authme/settings/custom/SettingsClassConsistencyTest.java
rename to src/test/java/fr/xephi/authme/settings/properties/SettingsClassConsistencyTest.java
index a6b67763a..075103345 100644
--- a/src/test/java/fr/xephi/authme/settings/custom/SettingsClassConsistencyTest.java
+++ b/src/test/java/fr/xephi/authme/settings/properties/SettingsClassConsistencyTest.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.ReflectionTestUtils;
import fr.xephi.authme.settings.domain.Property;
@@ -25,7 +25,7 @@ import static org.junit.Assert.fail;
*/
public class SettingsClassConsistencyTest {
- private static final String SETTINGS_FOLDER = "src/main/java/fr/xephi/authme/settings/custom";
+ private static final String SETTINGS_FOLDER = "src/main/java/fr/xephi/authme/settings/properties";
private static List> classes;
@BeforeClass
diff --git a/src/test/java/fr/xephi/authme/settings/custom/TestConfiguration.java b/src/test/java/fr/xephi/authme/settings/properties/TestConfiguration.java
similarity index 75%
rename from src/test/java/fr/xephi/authme/settings/custom/TestConfiguration.java
rename to src/test/java/fr/xephi/authme/settings/properties/TestConfiguration.java
index 5f43262c7..dc02e9ccb 100644
--- a/src/test/java/fr/xephi/authme/settings/custom/TestConfiguration.java
+++ b/src/test/java/fr/xephi/authme/settings/properties/TestConfiguration.java
@@ -1,4 +1,4 @@
-package fr.xephi.authme.settings.custom;
+package fr.xephi.authme.settings.properties;
import fr.xephi.authme.settings.domain.Property;
import fr.xephi.authme.settings.domain.PropertyType;
@@ -11,7 +11,7 @@ import static fr.xephi.authme.settings.domain.Property.newProperty;
/**
* Sample properties for testing purposes.
*/
-class TestConfiguration implements SettingsClass {
+public final class TestConfiguration implements SettingsClass {
public static final Property DURATION_IN_SECONDS =
newProperty("test.duration", 4);
@@ -19,8 +19,8 @@ class TestConfiguration implements SettingsClass {
public static final Property SYSTEM_NAME =
newProperty("test.systemName", "[TestDefaultValue]");
- public static final Property RATIO_LIMIT =
- newProperty(PropertyType.DOUBLE, "sample.ratio.limit", 3.0);
+ public static final Property RATIO_ORDER =
+ newProperty(TestEnum.class, "sample.ratio.order", TestEnum.SECOND);
public static final Property> RATIO_FIELDS =
newProperty(PropertyType.STRING_LIST, "sample.ratio.fields", "a", "b", "c");
@@ -34,8 +34,8 @@ class TestConfiguration implements SettingsClass {
public static final Property> BORING_COLORS =
newProperty(PropertyType.STRING_LIST, "features.boring.colors");
- public static final Property DUST_LEVEL =
- newProperty(PropertyType.DOUBLE, "features.boring.dustLevel", 0.2);
+ public static final Property DUST_LEVEL =
+ newProperty(PropertyType.INTEGER, "features.boring.dustLevel", -1);
public static final Property USE_COOL_FEATURES =
newProperty("features.cool.enabled", false);
@@ -43,4 +43,8 @@ class TestConfiguration implements SettingsClass {
public static final Property> COOL_OPTIONS =
newProperty(PropertyType.STRING_LIST, "features.cool.options", "Sparks", "Sprinkles");
+
+ private TestConfiguration() {
+ }
+
}
diff --git a/src/test/java/fr/xephi/authme/settings/properties/TestEnum.java b/src/test/java/fr/xephi/authme/settings/properties/TestEnum.java
new file mode 100644
index 000000000..e02d6825a
--- /dev/null
+++ b/src/test/java/fr/xephi/authme/settings/properties/TestEnum.java
@@ -0,0 +1,16 @@
+package fr.xephi.authme.settings.properties;
+
+/**
+ * Test enum used in {@link TestConfiguration}.
+ */
+public enum TestEnum {
+
+ FIRST,
+
+ SECOND,
+
+ THIRD,
+
+ FOURTH
+
+}
diff --git a/src/test/java/fr/xephi/authme/util/StringUtilsTest.java b/src/test/java/fr/xephi/authme/util/StringUtilsTest.java
index 238c8bcef..6cc7799aa 100644
--- a/src/test/java/fr/xephi/authme/util/StringUtilsTest.java
+++ b/src/test/java/fr/xephi/authme/util/StringUtilsTest.java
@@ -2,6 +2,7 @@ package fr.xephi.authme.util;
import org.junit.Test;
+import java.io.File;
import java.net.MalformedURLException;
import java.util.Arrays;
import java.util.List;
@@ -135,4 +136,13 @@ public class StringUtilsTest {
assertThat(StringUtils.getDifference("test", "bear"), equalTo(0.75));
assertThat(StringUtils.getDifference("test", "something"), greaterThan(0.88));
}
+
+ @Test
+ public void shouldConstructPath() {
+ // given/when
+ String result = StringUtils.makePath("path", "to", "test-file.txt");
+
+ // then
+ assertThat(result, equalTo("path" + File.separator + "to" + File.separator + "test-file.txt"));
+ }
}
diff --git a/src/test/java/fr/xephi/authme/util/UtilsTest.java b/src/test/java/fr/xephi/authme/util/UtilsTest.java
index 7bfac16ca..67723c494 100644
--- a/src/test/java/fr/xephi/authme/util/UtilsTest.java
+++ b/src/test/java/fr/xephi/authme/util/UtilsTest.java
@@ -1,16 +1,21 @@
package fr.xephi.authme.util;
import fr.xephi.authme.AuthMe;
+import fr.xephi.authme.ConsoleLoggerTestInitializer;
import fr.xephi.authme.ReflectionTestUtils;
import fr.xephi.authme.permission.PermissionsManager;
+import fr.xephi.authme.settings.NewSetting;
import fr.xephi.authme.settings.Settings;
+import fr.xephi.authme.settings.properties.EmailSettings;
import org.bukkit.entity.Player;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
@@ -35,6 +40,7 @@ public class UtilsTest {
public static void setUpMocks() {
WrapperMock wrapperMock = WrapperMock.createInstance();
authMeMock = wrapperMock.getAuthMe();
+ ConsoleLoggerTestInitializer.setupLogger();
}
@Before
@@ -92,6 +98,95 @@ public class UtilsTest {
assertThat(players, hasSize(2));
}
+ // ----------------
+ // Tests for Utils#isEmailCorrect()
+ // ----------------
+ @Test
+ public void shouldAcceptEmailWithEmptyLists() {
+ // given
+ NewSetting settings = mock(NewSetting.class);
+ given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)).willReturn(Collections.EMPTY_LIST);
+ given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)).willReturn(Collections.EMPTY_LIST);
+
+ // when
+ boolean result = Utils.isEmailCorrect("test@example.org", settings);
+
+ // then
+ assertThat(result, equalTo(true));
+ }
+
+ @Test
+ public void shouldAcceptEmailWithWhitelist() {
+ // given
+ NewSetting settings = mock(NewSetting.class);
+ given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST))
+ .willReturn(Arrays.asList("domain.tld", "example.com"));
+ given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)).willReturn(Collections.EMPTY_LIST);
+
+ // when
+ boolean result = Utils.isEmailCorrect("TesT@Example.com", settings);
+
+ // then
+ assertThat(result, equalTo(true));
+ }
+
+ @Test
+ public void shouldRejectEmailNotInWhitelist() {
+ // given
+ NewSetting settings = mock(NewSetting.class);
+ given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST))
+ .willReturn(Arrays.asList("domain.tld", "example.com"));
+ given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST)).willReturn(Collections.EMPTY_LIST);
+
+ // when
+ boolean result = Utils.isEmailCorrect("email@other-domain.abc", settings);
+
+ // then
+ assertThat(result, equalTo(false));
+ }
+
+ @Test
+ public void shouldAcceptEmailNotInBlacklist() {
+ // given
+ NewSetting settings = mock(NewSetting.class);
+ given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)).willReturn(Collections.EMPTY_LIST);
+ given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST))
+ .willReturn(Arrays.asList("Example.org", "a-test-name.tld"));
+
+ // when
+ boolean result = Utils.isEmailCorrect("sample@valid-name.tld", settings);
+
+ // then
+ assertThat(result, equalTo(true));
+ }
+
+ @Test
+ public void shouldRejectEmailInBlacklist() {
+ // given
+ NewSetting settings = mock(NewSetting.class);
+ given(settings.getProperty(EmailSettings.DOMAIN_WHITELIST)).willReturn(Collections.EMPTY_LIST);
+ given(settings.getProperty(EmailSettings.DOMAIN_BLACKLIST))
+ .willReturn(Arrays.asList("Example.org", "a-test-name.tld"));
+
+ // when
+ boolean result = Utils.isEmailCorrect("sample@a-Test-name.tld", settings);
+
+ // then
+ assertThat(result, equalTo(false));
+ }
+
+ @Test
+ public void shouldRejectInvalidEmail() {
+ // given/when/then
+ assertThat(Utils.isEmailCorrect("invalidinput", mock(NewSetting.class)), equalTo(false));
+ }
+
+ @Test
+ public void shouldRejectDefaultEmail() {
+ // given/when/then
+ assertThat(Utils.isEmailCorrect("your@email.com", mock(NewSetting.class)), equalTo(false));
+ }
+
// Note: This method is used through reflections
public static Player[] onlinePlayersImpl() {
return new Player[]{
diff --git a/src/test/resources/config-difficult-values.yml b/src/test/resources/config-difficult-values.yml
new file mode 100644
index 000000000..29bc0e371
--- /dev/null
+++ b/src/test/resources/config-difficult-values.yml
@@ -0,0 +1,29 @@
+# Test config file with some "difficult" values
+
+test:
+ duration: 20.102
+ systemName: 'A ''test'' name'
+sample:
+ ratio:
+ order: Fourth
+ fields:
+ - Australia\
+ - ' Burundi'''
+ - 'Colombia?
+
+ '''''
+ # The last element above represents "Colombia?\n''"
+version: -1337
+features:
+ boring:
+ # YAML allows both "yes"/"no" and "true"/"false" for expressing booleans
+ skip: no
+ colors:
+ - 'it''s a difficult string!'
+ - |
+ gray
+ with new lines
+ # dustLevel: 8 <-- missing property triggering rewrite
+ cool:
+ enabled: yes
+ options: []
diff --git a/src/test/resources/config-incomplete-sample.yml b/src/test/resources/config-incomplete-sample.yml
index a29879720..65990e84d 100644
--- a/src/test/resources/config-incomplete-sample.yml
+++ b/src/test/resources/config-incomplete-sample.yml
@@ -6,7 +6,7 @@ test:
# systemName: 'Custom sys name'
sample:
ratio:
-# limit: 3.0
+# order: 'THIRD'
fields:
- 'Australia'
- 'Burundi'
@@ -18,7 +18,7 @@ features:
# colors:
# - 'beige'
# - 'gray'
-# dustLevel: 0.81
+# dustLevel: 1
cool:
# enabled: true
options:
diff --git a/src/test/resources/config-sample-values.yml b/src/test/resources/config-sample-values.yml
index 1bd99d771..72cdeb790 100644
--- a/src/test/resources/config-sample-values.yml
+++ b/src/test/resources/config-sample-values.yml
@@ -6,7 +6,7 @@ test:
systemName: 'Custom sys name'
sample:
ratio:
- limit: -4.1
+ order: 'first'
fields:
- 'Australia'
- 'Burundi'
@@ -18,7 +18,7 @@ features:
colors:
- 'beige'
- 'gray'
- dustLevel: 0.81
+ dustLevel: 2
cool:
enabled: true
options: