Update configme (#1631)

* Upgrade to ConfigMe 1.0.1
* Use ConfigMe reader whenever possible, minor simplifications
This commit is contained in:
ljacqu
2018-09-09 15:45:00 +02:00
committed by GitHub
parent 6676a39447
commit ee764c0a6e
42 changed files with 516 additions and 555 deletions
@@ -39,7 +39,7 @@ public class JarMessageSource {
}
private static String getString(String path, PropertyReader reader) {
return reader == null ? null : reader.getTypedObject(path, String.class);
return reader == null ? null : reader.getString(path);
}
private static MessageMigraterPropertyReader loadJarFile(String jarPath) {
@@ -0,0 +1,43 @@
package fr.xephi.authme.message.updater;
import ch.jalu.configme.configurationdata.ConfigurationDataImpl;
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.resource.PropertyReader;
import fr.xephi.authme.message.MessageKey;
import java.util.List;
import java.util.Map;
public class MessageKeyConfigurationData extends ConfigurationDataImpl {
/**
* Constructor.
*
* @param propertyListBuilder property list builder for message key properties
* @param allComments registered comments
*/
public MessageKeyConfigurationData(MessageUpdater.MessageKeyPropertyListBuilder propertyListBuilder,
Map<String, List<String>> allComments) {
super(propertyListBuilder.getAllProperties(), allComments);
}
@Override
public void initializeValues(PropertyReader reader) {
getAllMessageProperties().stream()
.filter(prop -> prop.isPresent(reader))
.forEach(prop -> setValue(prop, prop.determineValue(reader)));
}
@SuppressWarnings("unchecked")
public List<Property<String>> getAllMessageProperties() {
return (List) getProperties();
}
public String getMessage(MessageKey messageKey) {
return getValue(new MessageUpdater.MessageKeyProperty(messageKey));
}
public void setMessage(MessageKey messageKey, String message) {
setValue(new MessageUpdater.MessageKeyProperty(messageKey), message);
}
}
@@ -12,20 +12,19 @@ import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Implementation of {@link PropertyReader} which can read a file or a stream with
* a specified charset.
*/
public final class MessageMigraterPropertyReader implements PropertyReader {
final class MessageMigraterPropertyReader implements PropertyReader {
public static final Charset CHARSET = StandardCharsets.UTF_8;
private static final Charset CHARSET = StandardCharsets.UTF_8;
private Map<String, Object> root;
/** See same field in {@link ch.jalu.configme.resource.YamlFileReader} for details. */
private boolean hasObjectAsRoot = false;
private MessageMigraterPropertyReader(Map<String, Object> valuesMap) {
root = valuesMap;
@@ -38,14 +37,11 @@ public final class MessageMigraterPropertyReader implements PropertyReader {
* @return the created property reader
*/
public static MessageMigraterPropertyReader loadFromFile(File file) {
Map<String, Object> valuesMap;
try (InputStream is = new FileInputStream(file)) {
valuesMap = readStreamToMap(is);
return loadFromStream(is);
} catch (IOException e) {
throw new IllegalStateException("Error while reading file '" + file + "'", e);
}
return new MessageMigraterPropertyReader(valuesMap);
}
public static MessageMigraterPropertyReader loadFromStream(InputStream inputStream) {
@@ -53,10 +49,20 @@ public final class MessageMigraterPropertyReader implements PropertyReader {
return new MessageMigraterPropertyReader(valuesMap);
}
@Override
public boolean contains(String path) {
return getObject(path) != null;
}
@Override
public Set<String> getKeys(boolean b) {
throw new UnsupportedOperationException();
}
@Override
public Object getObject(String path) {
if (path.isEmpty()) {
return hasObjectAsRoot ? root.get("") : root;
return root.get("");
}
Object node = root;
String[] keys = path.split("\\.");
@@ -70,66 +76,29 @@ public final class MessageMigraterPropertyReader implements PropertyReader {
}
@Override
public <T> T getTypedObject(String path, Class<T> clazz) {
Object value = getObject(path);
if (clazz.isInstance(value)) {
return clazz.cast(value);
}
return null;
public String getString(String path) {
Object o = getObject(path);
return o instanceof String ? (String) o : null;
}
@Override
public void set(String path, Object value) {
Objects.requireNonNull(path);
if (path.isEmpty()) {
root.clear();
root.put("", value);
hasObjectAsRoot = true;
} else if (hasObjectAsRoot) {
throw new ConfigMeException("The root path is a bean property; you cannot set values to any subpath. "
+ "Modify the bean at the root or set a new one instead.");
} else {
setValueInChildPath(path, value);
}
}
/**
* Sets the value at the given path. This method is used when the root is a map and not a specific object.
*
* @param path the path to set the value at
* @param value the value to set
*/
@SuppressWarnings("unchecked")
private void setValueInChildPath(String path, Object value) {
Map<String, Object> node = root;
String[] keys = path.split("\\.");
for (int i = 0; i < keys.length - 1; ++i) {
Object child = node.get(keys[i]);
if (child instanceof Map<?, ?>) {
node = (Map<String, Object>) child;
} else { // child is null or some other value - replace with map
Map<String, Object> newEntry = new HashMap<>();
node.put(keys[i], newEntry);
if (value == null) {
// For consistency, replace whatever value/null here with an empty map,
// but if the value is null our work here is done.
return;
}
node = newEntry;
}
}
// node now contains the parent map (existing or newly created)
if (value == null) {
node.remove(keys[keys.length - 1]);
} else {
node.put(keys[keys.length - 1], value);
}
public Integer getInt(String path) {
throw new UnsupportedOperationException();
}
@Override
public void reload() {
throw new UnsupportedOperationException("Reload not supported by this implementation");
public Double getDouble(String path) {
throw new UnsupportedOperationException();
}
@Override
public Boolean getBoolean(String path) {
throw new UnsupportedOperationException();
}
@Override
public List<?> getList(String path) {
throw new UnsupportedOperationException();
}
private static Map<String, Object> readStreamToMap(InputStream inputStream) {
@@ -1,10 +1,10 @@
package fr.xephi.authme.message.updater;
import ch.jalu.configme.SettingsManager;
import ch.jalu.configme.configurationdata.ConfigurationData;
import ch.jalu.configme.configurationdata.PropertyListBuilder;
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.properties.StringProperty;
import ch.jalu.configme.resource.PropertyReader;
import ch.jalu.configme.resource.PropertyResource;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Files;
@@ -20,21 +20,15 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static java.util.Collections.singletonList;
/**
* Migrates the used messages file to a complete, up-to-date version when necessary.
*/
public class MessageUpdater {
/**
* Configuration data object for all message keys incl. comments associated to sections.
*/
private static final ConfigurationData CONFIGURATION_DATA = buildConfigurationData();
public static ConfigurationData getConfigurationData() {
return CONFIGURATION_DATA;
}
/**
* Applies any necessary migrations to the user's messages file and saves it if it has been modified.
*
@@ -57,52 +51,57 @@ public class MessageUpdater {
*/
private boolean migrateAndSave(File userFile, JarMessageSource jarMessageSource) {
// YamlConfiguration escapes all special characters when saving, making the file hard to use, so use ConfigMe
MessageKeyConfigurationData configurationData = createConfigurationData();
PropertyResource userResource = new MigraterYamlFileResource(userFile);
PropertyReader reader = userResource.createReader();
configurationData.initializeValues(reader);
// Step 1: Migrate any old keys in the file to the new paths
boolean movedOldKeys = migrateOldKeys(userResource);
boolean movedOldKeys = migrateOldKeys(reader, configurationData);
// Step 2: Perform newer migrations
boolean movedNewerKeys = migrateKeys(userResource);
boolean movedNewerKeys = migrateKeys(reader, configurationData);
// Step 3: Take any missing messages from the message files shipped in the AuthMe JAR
boolean addedMissingKeys = addMissingKeys(jarMessageSource, userResource);
boolean addedMissingKeys = addMissingKeys(jarMessageSource, configurationData);
if (movedOldKeys || movedNewerKeys || addedMissingKeys) {
backupMessagesFile(userFile);
SettingsManager settingsManager = new SettingsManager(userResource, null, CONFIGURATION_DATA);
settingsManager.save();
userResource.exportProperties(configurationData);
ConsoleLogger.debug("Successfully saved {0}", userFile);
return true;
}
return false;
}
private boolean migrateKeys(PropertyResource userResource) {
return moveIfApplicable(userResource, "misc.two_factor_create", MessageKey.TWO_FACTOR_CREATE.getKey());
private boolean migrateKeys(PropertyReader propertyReader, MessageKeyConfigurationData configurationData) {
return moveIfApplicable(propertyReader, configurationData,
"misc.two_factor_create", MessageKey.TWO_FACTOR_CREATE);
}
private static boolean moveIfApplicable(PropertyResource resource, String oldPath, String newPath) {
if (resource.getString(newPath) == null && resource.getString(oldPath) != null) {
resource.setValue(newPath, resource.getString(oldPath));
private static boolean moveIfApplicable(PropertyReader reader, MessageKeyConfigurationData configurationData,
String oldPath, MessageKey messageKey) {
if (configurationData.getMessage(messageKey) == null && reader.getString(oldPath) != null) {
configurationData.setMessage(messageKey, reader.getString(oldPath));
return true;
}
return false;
}
private boolean migrateOldKeys(PropertyResource userResource) {
boolean hasChange = OldMessageKeysMigrater.migrateOldPaths(userResource);
private boolean migrateOldKeys(PropertyReader propertyReader, MessageKeyConfigurationData configurationData) {
boolean hasChange = OldMessageKeysMigrater.migrateOldPaths(propertyReader, configurationData);
if (hasChange) {
ConsoleLogger.info("Old keys have been moved to the new ones in your messages_xx.yml file");
}
return hasChange;
}
private boolean addMissingKeys(JarMessageSource jarMessageSource, PropertyResource userResource) {
private boolean addMissingKeys(JarMessageSource jarMessageSource, MessageKeyConfigurationData configurationData) {
List<String> addedKeys = new ArrayList<>();
for (Property<?> property : CONFIGURATION_DATA.getProperties()) {
for (Property<String> property : configurationData.getAllMessageProperties()) {
final String key = property.getPath();
if (userResource.getString(key) == null) {
userResource.setValue(key, jarMessageSource.getMessageFromJar(property));
if (configurationData.getValue(property) == null) {
configurationData.setValue(property, jarMessageSource.getMessageFromJar(property));
addedKeys.add(key);
}
}
@@ -129,40 +128,68 @@ public class MessageUpdater {
*
* @return the configuration data to export with
*/
private static ConfigurationData buildConfigurationData() {
Map<String, String[]> comments = ImmutableMap.<String, String[]>builder()
.put("registration", new String[]{"Registration"})
.put("password", new String[]{"Password errors on registration"})
.put("login", new String[]{"Login"})
.put("error", new String[]{"Errors"})
.put("antibot", new String[]{"AntiBot"})
.put("unregister", new String[]{"Unregister"})
.put("misc", new String[]{"Other messages"})
.put("session", new String[]{"Session messages"})
.put("on_join_validation", new String[]{"Error messages when joining"})
.put("email", new String[]{"Email"})
.put("recovery", new String[]{"Password recovery by email"})
.put("captcha", new String[]{"Captcha"})
.put("verification", new String[]{"Verification code"})
.put("time", new String[]{"Time units"})
.put("two_factor", new String[]{"Two-factor authentication"})
public static MessageKeyConfigurationData createConfigurationData() {
Map<String, String> comments = ImmutableMap.<String, String>builder()
.put("registration", "Registration")
.put("password", "Password errors on registration")
.put("login", "Login")
.put("error", "Errors")
.put("antibot", "AntiBot")
.put("unregister", "Unregister")
.put("misc", "Other messages")
.put("session", "Session messages")
.put("on_join_validation", "Error messages when joining")
.put("email", "Email")
.put("recovery", "Password recovery by email")
.put("captcha", "Captcha")
.put("verification", "Verification code")
.put("time", "Time units")
.put("two_factor", "Two-factor authentication")
.build();
Set<String> addedKeys = new HashSet<>();
PropertyListBuilder builder = new PropertyListBuilder();
MessageKeyPropertyListBuilder builder = new MessageKeyPropertyListBuilder();
// Add one key per section based on the comments map above so that the order is clear
for (String path : comments.keySet()) {
MessageKey key = Arrays.stream(MessageKey.values()).filter(p -> p.getKey().startsWith(path + "."))
.findFirst().orElseThrow(() -> new IllegalStateException(path));
builder.add(new StringProperty(key.getKey(), ""));
builder.addMessageKey(key);
addedKeys.add(key.getKey());
}
// Add all remaining keys to the property list builder
Arrays.stream(MessageKey.values())
.filter(key -> !addedKeys.contains(key.getKey()))
.forEach(key -> builder.add(new StringProperty(key.getKey(), "")));
.forEach(builder::addMessageKey);
return new ConfigurationData(builder.create(), comments);
// Create ConfigurationData instance
Map<String, List<String>> commentsMap = comments.entrySet().stream()
.collect(Collectors.toMap(e -> e.getKey(), e -> singletonList(e.getValue())));
return new MessageKeyConfigurationData(builder, commentsMap);
}
static final class MessageKeyProperty extends StringProperty {
MessageKeyProperty(MessageKey messageKey) {
super(messageKey.getKey(), "");
}
@Override
protected String getFromReader(PropertyReader reader) {
return reader.getString(getPath());
}
}
static final class MessageKeyPropertyListBuilder {
private PropertyListBuilder propertyListBuilder = new PropertyListBuilder();
void addMessageKey(MessageKey key) {
propertyListBuilder.add(new MessageKeyProperty(key));
}
@SuppressWarnings("unchecked")
List<MessageKeyProperty> getAllProperties() {
return (List) propertyListBuilder.create();
}
}
}
@@ -1,41 +1,30 @@
package fr.xephi.authme.message.updater;
import ch.jalu.configme.beanmapper.leafproperties.LeafPropertiesGenerator;
import ch.jalu.configme.configurationdata.ConfigurationData;
import ch.jalu.configme.exception.ConfigMeException;
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.resource.PropertyPathTraverser;
import ch.jalu.configme.resource.PropertyReader;
import ch.jalu.configme.resource.YamlFileResource;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import static fr.xephi.authme.message.updater.MessageMigraterPropertyReader.CHARSET;
/**
* Extension of {@link YamlFileResource} to fine-tune the export style
* and to be able to specify the character encoding.
* Extension of {@link YamlFileResource} to fine-tune the export style.
*/
public class MigraterYamlFileResource extends YamlFileResource {
private static final String INDENTATION = " ";
private final File file;
private Yaml singleQuoteYaml;
public MigraterYamlFileResource(File file) {
super(file, MessageMigraterPropertyReader.loadFromFile(file), new LeafPropertiesGenerator());
this.file = file;
super(file);
}
@Override
protected Yaml getSingleQuoteYaml() {
public PropertyReader createReader() {
return MessageMigraterPropertyReader.loadFromFile(getFile());
}
@Override
protected Yaml createNewYaml() {
if (singleQuoteYaml == null) {
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
@@ -47,57 +36,4 @@ public class MigraterYamlFileResource extends YamlFileResource {
}
return singleQuoteYaml;
}
@Override
public void exportProperties(ConfigurationData configurationData) {
try (FileOutputStream fos = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(fos, CHARSET)) {
PropertyPathTraverser pathTraverser = new PropertyPathTraverser(configurationData);
for (Property<?> property : convertPropertiesToExportableTypes(configurationData.getProperties())) {
List<PropertyPathTraverser.PathElement> pathElements = pathTraverser.getPathElements(property);
for (PropertyPathTraverser.PathElement pathElement : pathElements) {
writeComments(writer, pathElement.indentationLevel, pathElement.comments);
writer.append("\n")
.append(indent(pathElement.indentationLevel))
.append(pathElement.name)
.append(":");
}
writer.append(" ")
.append(toYaml(property, pathElements.get(pathElements.size() - 1).indentationLevel));
}
writer.flush();
writer.close();
} catch (IOException e) {
throw new ConfigMeException("Could not save config to '" + file.getPath() + "'", e);
} finally {
singleQuoteYaml = null;
}
}
private void writeComments(Writer writer, int indentation, String[] comments) throws IOException {
if (comments.length == 0) {
return;
}
String commentStart = "\n" + indent(indentation) + "# ";
for (String comment : comments) {
writer.append(commentStart).append(comment);
}
}
private <T> String toYaml(Property<T> property, int indent) {
Object value = property.getValue(this);
String representation = transformValue(property, value);
String[] lines = representation.split("\\n");
return String.join("\n" + indent(indent), lines);
}
private static String indent(int level) {
String result = "";
for (int i = 0; i < level; i++) {
result += INDENTATION;
}
return result;
}
}
@@ -1,6 +1,6 @@
package fr.xephi.authme.message.updater;
import ch.jalu.configme.resource.PropertyResource;
import ch.jalu.configme.resource.PropertyReader;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import fr.xephi.authme.message.MessageKey;
@@ -16,7 +16,6 @@ import static com.google.common.collect.ImmutableMap.of;
*/
final class OldMessageKeysMigrater {
@VisibleForTesting
static final Map<MessageKey, String> KEYS_TO_OLD_PATH = ImmutableMap.<MessageKey, String>builder()
.put(MessageKey.LOGIN_SUCCESS, "login")
@@ -130,23 +129,26 @@ final class OldMessageKeysMigrater {
/**
* Migrates any existing old key paths to their new paths if no text has been defined for the new key.
*
* @param resource the resource to modify and read from
* @param reader the property reader to get values from
* @param configurationData the configuration data to write to
* @return true if at least one message could be migrated, false otherwise
*/
static boolean migrateOldPaths(PropertyResource resource) {
static boolean migrateOldPaths(PropertyReader reader, MessageKeyConfigurationData configurationData) {
boolean wasPropertyMoved = false;
for (Map.Entry<MessageKey, String> migrationEntry : KEYS_TO_OLD_PATH.entrySet()) {
wasPropertyMoved |= moveIfApplicable(resource, migrationEntry.getKey(), migrationEntry.getValue());
wasPropertyMoved |= moveIfApplicable(reader, configurationData,
migrationEntry.getKey(), migrationEntry.getValue());
}
return wasPropertyMoved;
}
private static boolean moveIfApplicable(PropertyResource resource, MessageKey messageKey, String oldPath) {
if (resource.getString(messageKey.getKey()) == null) {
String textAtOldPath = resource.getString(oldPath);
private static boolean moveIfApplicable(PropertyReader reader, MessageKeyConfigurationData configurationData,
MessageKey messageKey, String oldPath) {
if (configurationData.getMessage(messageKey) == null) {
String textAtOldPath = reader.getString(oldPath);
if (textAtOldPath != null) {
textAtOldPath = replaceOldPlaceholders(messageKey, textAtOldPath);
resource.setValue(messageKey.getKey(), textAtOldPath);
configurationData.setMessage(messageKey, textAtOldPath);
return true;
}
}
@@ -23,7 +23,6 @@ import org.bukkit.entity.Player;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
@@ -45,7 +44,6 @@ public class ValidationService implements Reloadable {
private GeoIpService geoIpService;
private Pattern passwordRegex;
private Set<String> unrestrictedNames;
private Multimap<String, String> restrictedNames;
ValidationService() {
@@ -55,8 +53,6 @@ public class ValidationService implements Reloadable {
@Override
public void reload() {
passwordRegex = Utils.safePatternCompile(settings.getProperty(RestrictionSettings.ALLOWED_PASSWORD_REGEX));
// Use Set for more efficient contains() lookup
unrestrictedNames = new HashSet<>(settings.getProperty(RestrictionSettings.UNRESTRICTED_NAMES));
restrictedNames = settings.getProperty(RestrictionSettings.ENABLE_RESTRICTED_USERS)
? loadNameRestrictions(settings.getProperty(RestrictionSettings.RESTRICTED_USERS))
: HashMultimap.create();
@@ -140,7 +136,7 @@ public class ValidationService implements Reloadable {
* @return true if unrestricted, false otherwise
*/
public boolean isUnrestricted(String name) {
return unrestrictedNames.contains(name.toLowerCase());
return settings.getProperty(RestrictionSettings.UNRESTRICTED_NAMES).contains(name.toLowerCase());
}
/**
@@ -208,7 +204,7 @@ public class ValidationService implements Reloadable {
* @param configuredRestrictions the restriction rules to convert to a map
* @return map of allowed IPs/domain names by player name
*/
private Multimap<String, String> loadNameRestrictions(List<String> configuredRestrictions) {
private Multimap<String, String> loadNameRestrictions(Set<String> configuredRestrictions) {
Multimap<String, String> restrictions = HashMultimap.create();
for (String restriction : configuredRestrictions) {
if (isInsideString(';', restriction)) {
@@ -1,7 +1,8 @@
package fr.xephi.authme.service.yaml;
import ch.jalu.configme.exception.ConfigMeException;
import ch.jalu.configme.resource.PropertyReader;
import ch.jalu.configme.resource.YamlFileResource;
import org.yaml.snakeyaml.parser.ParserException;
import java.io.File;
@@ -15,16 +16,32 @@ public final class YamlFileResourceProvider {
/**
* Creates a {@link YamlFileResource} instance for the given file. Wraps SnakeYAML's parse exception
* into an AuthMe exception.
* thrown when a reader is created into an AuthMe exception.
*
* @param file the file to load
* @return the generated resource
*/
public static YamlFileResource loadFromFile(File file) {
try {
return new YamlFileResource(file);
} catch (ParserException e) {
throw new YamlParseException(file.getPath(), e);
return new AuthMeYamlFileResource(file);
}
/**
* Extension of {@link YamlFileResource} which wraps SnakeYAML's parse exception into a custom
* exception when a reader is created.
*/
private static final class AuthMeYamlFileResource extends YamlFileResource {
AuthMeYamlFileResource(File file) {
super(file);
}
@Override
public PropertyReader createReader() {
try {
return super.createReader();
} catch (ConfigMeException e) {
throw new YamlParseException(getFile().getPath(), e);
}
}
}
}
@@ -1,6 +1,8 @@
package fr.xephi.authme.service.yaml;
import org.yaml.snakeyaml.parser.ParserException;
import ch.jalu.configme.exception.ConfigMeException;
import static com.google.common.base.MoreObjects.firstNonNull;
/**
* Exception when a YAML file could not be parsed.
@@ -13,10 +15,10 @@ public class YamlParseException extends RuntimeException {
* Constructor.
*
* @param file the file a parsing exception occurred with
* @param snakeYamlException the caught exception from SnakeYAML
* @param configMeException the caught exception from ConfigMe
*/
public YamlParseException(String file, ParserException snakeYamlException) {
super(snakeYamlException);
public YamlParseException(String file, ConfigMeException configMeException) {
super(firstNonNull(configMeException.getCause(), configMeException));
this.file = file;
}
@@ -1,7 +1,7 @@
package fr.xephi.authme.settings;
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.resource.PropertyResource;
import ch.jalu.configme.properties.BaseProperty;
import ch.jalu.configme.resource.PropertyReader;
import java.util.Collection;
import java.util.LinkedHashSet;
@@ -15,7 +15,7 @@ import static com.google.common.collect.Sets.newHashSet;
*
* @param <E> the enum type
*/
public class EnumSetProperty<E extends Enum<E>> extends Property<Set<E>> {
public class EnumSetProperty<E extends Enum<E>> extends BaseProperty<Set<E>> {
private final Class<E> enumClass;
@@ -26,8 +26,8 @@ public class EnumSetProperty<E extends Enum<E>> extends Property<Set<E>> {
}
@Override
protected Set<E> getFromResource(PropertyResource resource) {
Object entry = resource.getObject(getPath());
protected Set<E> getFromReader(PropertyReader reader) {
Object entry = reader.getObject(getPath());
if (entry instanceof Collection<?>) {
return ((Collection<?>) entry).stream()
.map(val -> toEnum(String.valueOf(val)))
@@ -45,4 +45,11 @@ public class EnumSetProperty<E extends Enum<E>> extends Property<Set<E>> {
}
return null;
}
@Override
public Object toExportValue(Set<E> value) {
return value.stream()
.map(Enum::name)
.collect(Collectors.toList());
}
}
@@ -1,6 +1,6 @@
package fr.xephi.authme.settings;
import ch.jalu.configme.SettingsManager;
import ch.jalu.configme.SettingsManagerImpl;
import ch.jalu.configme.configurationdata.ConfigurationData;
import ch.jalu.configme.migration.MigrationService;
import ch.jalu.configme.resource.PropertyResource;
@@ -16,7 +16,7 @@ import static fr.xephi.authme.util.FileUtils.copyFileFromResource;
/**
* The AuthMe settings manager.
*/
public class Settings extends SettingsManager {
public class Settings extends SettingsManagerImpl {
private final File pluginFolder;
private String passwordEmailMessage;
@@ -33,7 +33,7 @@ public class Settings extends SettingsManager {
*/
public Settings(File pluginFolder, PropertyResource resource, MigrationService migrationService,
ConfigurationData configurationData) {
super(resource, migrationService, configurationData);
super(resource, configurationData, migrationService);
this.pluginFolder = pluginFolder;
loadSettingsFromFiles();
}
@@ -1,8 +1,9 @@
package fr.xephi.authme.settings;
import ch.jalu.configme.configurationdata.ConfigurationData;
import ch.jalu.configme.migration.PlainMigrationService;
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.resource.PropertyResource;
import ch.jalu.configme.resource.PropertyReader;
import com.google.common.base.MoreObjects;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.initialization.DataFolder;
@@ -25,6 +26,7 @@ import java.util.Set;
import static ch.jalu.configme.properties.PropertyInitializer.newListProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
import static fr.xephi.authme.settings.properties.DatabaseSettings.MYSQL_POOL_SIZE;
import static fr.xephi.authme.settings.properties.RegistrationSettings.DELAY_JOIN_MESSAGE;
import static fr.xephi.authme.settings.properties.RegistrationSettings.REMOVE_JOIN_MESSAGE;
import static fr.xephi.authme.settings.properties.RegistrationSettings.REMOVE_LEAVE_MESSAGE;
@@ -53,33 +55,33 @@ public class SettingsMigrationService extends PlainMigrationService {
@Override
@SuppressWarnings("checkstyle:BooleanExpressionComplexity")
protected boolean performMigrations(PropertyResource resource, List<Property<?>> properties) {
protected boolean performMigrations(PropertyReader reader, ConfigurationData configurationData) {
boolean changes = false;
if ("[a-zA-Z0-9_?]*".equals(resource.getString(ALLOWED_NICKNAME_CHARACTERS.getPath()))) {
resource.setValue(ALLOWED_NICKNAME_CHARACTERS.getPath(), "[a-zA-Z0-9_]*");
if ("[a-zA-Z0-9_?]*".equals(reader.getString(ALLOWED_NICKNAME_CHARACTERS.getPath()))) {
configurationData.setValue(ALLOWED_NICKNAME_CHARACTERS, "[a-zA-Z0-9_]*");
changes = true;
}
setOldOtherAccountsCommandFieldsIfSet(resource);
setOldOtherAccountsCommandFieldsIfSet(reader);
// Note ljacqu 20160211: Concatenating migration methods with | instead of the usual ||
// ensures that all migrations will be performed
return changes
| performMailTextToFileMigration(resource)
| migrateJoinLeaveMessages(resource)
| migrateForceSpawnSettings(resource)
| migratePoolSizeSetting(resource)
| changeBooleanSettingToLogLevelProperty(resource)
| hasOldHelpHeaderProperty(resource)
| hasSupportOldPasswordProperty(resource)
| convertToRegistrationType(resource)
| mergeAndMovePermissionGroupSettings(resource)
| moveDeprecatedHashAlgorithmIntoLegacySection(resource)
| moveSaltColumnConfigWithOtherColumnConfigs(resource)
|| hasDeprecatedProperties(resource);
| performMailTextToFileMigration(reader)
| migrateJoinLeaveMessages(reader, configurationData)
| migrateForceSpawnSettings(reader, configurationData)
| migratePoolSizeSetting(reader, configurationData)
| changeBooleanSettingToLogLevelProperty(reader, configurationData)
| hasOldHelpHeaderProperty(reader)
| hasSupportOldPasswordProperty(reader)
| convertToRegistrationType(reader, configurationData)
| mergeAndMovePermissionGroupSettings(reader, configurationData)
| moveDeprecatedHashAlgorithmIntoLegacySection(reader, configurationData)
| moveSaltColumnConfigWithOtherColumnConfigs(reader, configurationData)
|| hasDeprecatedProperties(reader);
}
private static boolean hasDeprecatedProperties(PropertyResource resource) {
private static boolean hasDeprecatedProperties(PropertyReader reader) {
String[] deprecatedProperties = {
"Converter.Rakamak.newPasswordHash", "Hooks.chestshop", "Hooks.legacyChestshop", "Hooks.notifications",
"Passpartu", "Performances", "settings.restrictions.enablePasswordVerifier", "Xenoforo.predefinedSalt",
@@ -90,7 +92,7 @@ public class SettingsMigrationService extends PlainMigrationService {
"settings.sessions.sessionExpireOnIpChange", "settings.restrictions.otherAccountsCmd",
"settings.restrictions.otherAccountsCmdThreshold"};
for (String deprecatedPath : deprecatedProperties) {
if (resource.contains(deprecatedPath)) {
if (reader.contains(deprecatedPath)) {
return true;
}
}
@@ -119,12 +121,12 @@ public class SettingsMigrationService extends PlainMigrationService {
/**
* Check if {@code Email.mailText} is present and move it to the Email.html file if it doesn't exist yet.
*
* @param resource The property resource
* @param reader The property reader
* @return True if a migration has been completed, false otherwise
*/
private boolean performMailTextToFileMigration(PropertyResource resource) {
private boolean performMailTextToFileMigration(PropertyReader reader) {
final String oldSettingPath = "Email.mailText";
final String oldMailText = resource.getString(oldSettingPath);
final String oldMailText = reader.getString(oldSettingPath);
if (oldMailText == null) {
return false;
}
@@ -149,12 +151,13 @@ public class SettingsMigrationService extends PlainMigrationService {
* Detect deprecated {@code settings.delayJoinLeaveMessages} and inform user of new "remove join messages"
* and "remove leave messages" settings.
*
* @param resource The property resource
* @param reader The property reader
* @param configData Configuration data
* @return True if the configuration has changed, false otherwise
*/
private static boolean migrateJoinLeaveMessages(PropertyResource resource) {
private static boolean migrateJoinLeaveMessages(PropertyReader reader, ConfigurationData configData) {
Property<Boolean> oldDelayJoinProperty = newProperty("settings.delayJoinLeaveMessages", false);
boolean hasMigrated = moveProperty(oldDelayJoinProperty, DELAY_JOIN_MESSAGE, resource);
boolean hasMigrated = moveProperty(oldDelayJoinProperty, DELAY_JOIN_MESSAGE, reader, configData);
if (hasMigrated) {
ConsoleLogger.info(String.format("Note that we now also have the settings %s and %s",
@@ -167,31 +170,33 @@ public class SettingsMigrationService extends PlainMigrationService {
* Detects old "force spawn loc on join" and "force spawn on these worlds" settings and moves them
* to the new paths.
*
* @param resource The property resource
* @param reader The property reader
* @param configData Configuration data
* @return True if the configuration has changed, false otherwise
*/
private static boolean migrateForceSpawnSettings(PropertyResource resource) {
private static boolean migrateForceSpawnSettings(PropertyReader reader, ConfigurationData configData) {
Property<Boolean> oldForceLocEnabled = newProperty(
"settings.restrictions.ForceSpawnLocOnJoinEnabled", false);
Property<List<String>> oldForceWorlds = newListProperty(
"settings.restrictions.ForceSpawnOnTheseWorlds", "world", "world_nether", "world_the_ed");
return moveProperty(oldForceLocEnabled, FORCE_SPAWN_LOCATION_AFTER_LOGIN, resource)
| moveProperty(oldForceWorlds, FORCE_SPAWN_ON_WORLDS, resource);
return moveProperty(oldForceLocEnabled, FORCE_SPAWN_LOCATION_AFTER_LOGIN, reader, configData)
| moveProperty(oldForceWorlds, FORCE_SPAWN_ON_WORLDS, reader, configData);
}
/**
* Detects the old auto poolSize value and replaces it with the default value.
*
* @param resource The property resource
* @param reader The property reader
* @param configData Configuration data
* @return True if the configuration has changed, false otherwise
*/
private static boolean migratePoolSizeSetting(PropertyResource resource) {
Integer oldValue = resource.getInt("DataSource.poolSize");
private static boolean migratePoolSizeSetting(PropertyReader reader, ConfigurationData configData) {
Integer oldValue = reader.getInt(MYSQL_POOL_SIZE.getPath());
if (oldValue == null || oldValue > 0) {
return false;
}
resource.setValue("DataSource.poolSize", 10);
configData.setValue(MYSQL_POOL_SIZE, 10);
return true;
}
@@ -199,24 +204,26 @@ public class SettingsMigrationService extends PlainMigrationService {
* Changes the old boolean property "hide spam from console" to the new property specifying
* the log level.
*
* @param resource The property resource
* @param reader The property reader
* @param configData Configuration data
* @return True if the configuration has changed, false otherwise
*/
private static boolean changeBooleanSettingToLogLevelProperty(PropertyResource resource) {
private static boolean changeBooleanSettingToLogLevelProperty(PropertyReader reader,
ConfigurationData configData) {
final String oldPath = "Security.console.noConsoleSpam";
final Property<LogLevel> newProperty = PluginSettings.LOG_LEVEL;
if (!newProperty.isPresent(resource) && resource.contains(oldPath)) {
if (!newProperty.isPresent(reader) && reader.contains(oldPath)) {
ConsoleLogger.info("Moving '" + oldPath + "' to '" + newProperty.getPath() + "'");
boolean oldValue = MoreObjects.firstNonNull(resource.getBoolean(oldPath), false);
boolean oldValue = MoreObjects.firstNonNull(reader.getBoolean(oldPath), false);
LogLevel level = oldValue ? LogLevel.INFO : LogLevel.FINE;
resource.setValue(newProperty.getPath(), level.name());
configData.setValue(newProperty, level);
return true;
}
return false;
}
private static boolean hasOldHelpHeaderProperty(PropertyResource resource) {
if (resource.contains("settings.helpHeader")) {
private static boolean hasOldHelpHeaderProperty(PropertyReader reader) {
if (reader.contains("settings.helpHeader")) {
ConsoleLogger.warning("Help header setting is now in messages/help_xx.yml, "
+ "please check the file to set it again");
return true;
@@ -224,9 +231,9 @@ public class SettingsMigrationService extends PlainMigrationService {
return false;
}
private static boolean hasSupportOldPasswordProperty(PropertyResource resource) {
private static boolean hasSupportOldPasswordProperty(PropertyReader reader) {
String path = "settings.security.supportOldPasswordHash";
if (resource.contains(path)) {
if (reader.contains(path)) {
ConsoleLogger.warning("Property '" + path + "' is no longer supported. "
+ "Use '" + SecuritySettings.LEGACY_HASHES.getPath() + "' instead.");
return true;
@@ -237,56 +244,58 @@ public class SettingsMigrationService extends PlainMigrationService {
/**
* Converts old boolean configurations for registration to the new enum properties, if applicable.
*
* @param resource The property resource
* @param reader The property reader
* @param configData Configuration data
* @return True if the configuration has changed, false otherwise
*/
private static boolean convertToRegistrationType(PropertyResource resource) {
private static boolean convertToRegistrationType(PropertyReader reader, ConfigurationData configData) {
String oldEmailRegisterPath = "settings.registration.enableEmailRegistrationSystem";
if (RegistrationSettings.REGISTRATION_TYPE.isPresent(resource) || !resource.contains(oldEmailRegisterPath)) {
if (RegistrationSettings.REGISTRATION_TYPE.isPresent(reader) || !reader.contains(oldEmailRegisterPath)) {
return false;
}
boolean useEmail = newProperty(oldEmailRegisterPath, false).getValue(resource);
boolean useEmail = newProperty(oldEmailRegisterPath, false).determineValue(reader);
RegistrationType registrationType = useEmail ? RegistrationType.EMAIL : RegistrationType.PASSWORD;
String useConfirmationPath = useEmail
? "settings.registration.doubleEmailCheck"
: "settings.restrictions.enablePasswordConfirmation";
boolean hasConfirmation = newProperty(useConfirmationPath, false).getValue(resource);
boolean hasConfirmation = newProperty(useConfirmationPath, false).determineValue(reader);
RegisterSecondaryArgument secondaryArgument = hasConfirmation
? RegisterSecondaryArgument.CONFIRMATION
: RegisterSecondaryArgument.NONE;
ConsoleLogger.warning("Merging old registration settings into '"
+ RegistrationSettings.REGISTRATION_TYPE.getPath() + "'");
resource.setValue(RegistrationSettings.REGISTRATION_TYPE.getPath(), registrationType);
resource.setValue(RegistrationSettings.REGISTER_SECOND_ARGUMENT.getPath(), secondaryArgument);
configData.setValue(RegistrationSettings.REGISTRATION_TYPE, registrationType);
configData.setValue(RegistrationSettings.REGISTER_SECOND_ARGUMENT, secondaryArgument);
return true;
}
/**
* Migrates old permission group settings to the new configurations.
*
* @param resource The property resource
* @param reader The property reader
* @param configData Configuration data
* @return True if the configuration has changed, false otherwise
*/
private static boolean mergeAndMovePermissionGroupSettings(PropertyResource resource) {
private static boolean mergeAndMovePermissionGroupSettings(PropertyReader reader, ConfigurationData configData) {
boolean performedChanges;
// We have two old settings replaced by only one: move the first non-empty one
Property<String> oldUnloggedInGroup = newProperty("settings.security.unLoggedinGroup", "");
Property<String> oldRegisteredGroup = newProperty("GroupOptions.RegisteredPlayerGroup", "");
if (!oldUnloggedInGroup.getValue(resource).isEmpty()) {
performedChanges = moveProperty(oldUnloggedInGroup, PluginSettings.REGISTERED_GROUP, resource);
if (!oldUnloggedInGroup.determineValue(reader).isEmpty()) {
performedChanges = moveProperty(oldUnloggedInGroup, PluginSettings.REGISTERED_GROUP, reader, configData);
} else {
performedChanges = moveProperty(oldRegisteredGroup, PluginSettings.REGISTERED_GROUP, resource);
performedChanges = moveProperty(oldRegisteredGroup, PluginSettings.REGISTERED_GROUP, reader, configData);
}
// Move paths of other old options
performedChanges |= moveProperty(newProperty("GroupOptions.UnregisteredPlayerGroup", ""),
PluginSettings.UNREGISTERED_GROUP, resource);
PluginSettings.UNREGISTERED_GROUP, reader, configData);
performedChanges |= moveProperty(newProperty("permission.EnablePermissionCheck", false),
PluginSettings.ENABLE_PERMISSION_CHECK, resource);
PluginSettings.ENABLE_PERMISSION_CHECK, reader, configData);
return performedChanges;
}
@@ -294,19 +303,21 @@ public class SettingsMigrationService extends PlainMigrationService {
* If a deprecated hash is used, it is added to the legacy hashes option and the active hash
* is changed to SHA256.
*
* @param resource The property resource
* @param reader The property reader
* @param configData Configuration data
* @return True if the configuration has changed, false otherwise
*/
private static boolean moveDeprecatedHashAlgorithmIntoLegacySection(PropertyResource resource) {
HashAlgorithm currentHash = SecuritySettings.PASSWORD_HASH.getValue(resource);
private static boolean moveDeprecatedHashAlgorithmIntoLegacySection(PropertyReader reader,
ConfigurationData configData) {
HashAlgorithm currentHash = SecuritySettings.PASSWORD_HASH.determineValue(reader);
// Skip CUSTOM (has no class) and PLAINTEXT (is force-migrated later on in the startup process)
if (currentHash != HashAlgorithm.CUSTOM && currentHash != HashAlgorithm.PLAINTEXT) {
Class<?> encryptionClass = currentHash.getClazz();
if (encryptionClass.isAnnotationPresent(Deprecated.class)) {
resource.setValue(SecuritySettings.PASSWORD_HASH.getPath(), HashAlgorithm.SHA256);
Set<HashAlgorithm> legacyHashes = SecuritySettings.LEGACY_HASHES.getValue(resource);
configData.setValue(SecuritySettings.PASSWORD_HASH, HashAlgorithm.SHA256);
Set<HashAlgorithm> legacyHashes = SecuritySettings.LEGACY_HASHES.determineValue(reader);
legacyHashes.add(currentHash);
resource.setValue(SecuritySettings.LEGACY_HASHES.getPath(), legacyHashes);
configData.setValue(SecuritySettings.LEGACY_HASHES, legacyHashes);
ConsoleLogger.warning("The hash algorithm '" + currentHash
+ "' is no longer supported for active use. New hashes will be in SHA256.");
return true;
@@ -318,28 +329,30 @@ public class SettingsMigrationService extends PlainMigrationService {
/**
* Moves the property for the password salt column name to the same path as all other column name properties.
*
* @param resource The property resource
* @param reader The property reader
* @param configData Configuration data
* @return True if the configuration has changed, false otherwise
*/
private static boolean moveSaltColumnConfigWithOtherColumnConfigs(PropertyResource resource) {
private static boolean moveSaltColumnConfigWithOtherColumnConfigs(PropertyReader reader,
ConfigurationData configData) {
Property<String> oldProperty = newProperty("ExternalBoardOptions.mySQLColumnSalt",
DatabaseSettings.MYSQL_COL_SALT.getDefaultValue());
return moveProperty(oldProperty, DatabaseSettings.MYSQL_COL_SALT, resource);
return moveProperty(oldProperty, DatabaseSettings.MYSQL_COL_SALT, reader, configData);
}
/**
* Retrieves the old config to run a command when alt accounts are detected and sets them to this instance
* for further processing.
*
* @param resource The property resource
* @param reader The property reader
*/
private void setOldOtherAccountsCommandFieldsIfSet(PropertyResource resource) {
private void setOldOtherAccountsCommandFieldsIfSet(PropertyReader reader) {
Property<String> commandProperty = newProperty("settings.restrictions.otherAccountsCmd", "");
Property<Integer> commandThresholdProperty = newProperty("settings.restrictions.otherAccountsCmdThreshold", 0);
if (commandProperty.isPresent(resource) && commandThresholdProperty.getValue(resource) >= 2) {
oldOtherAccountsCommand = commandProperty.getValue(resource);
oldOtherAccountsCommandThreshold = commandThresholdProperty.getValue(resource);
if (commandProperty.isPresent(reader) && commandThresholdProperty.determineValue(reader) >= 2) {
oldOtherAccountsCommand = commandProperty.determineValue(reader);
oldOtherAccountsCommandThreshold = commandThresholdProperty.determineValue(reader);
}
}
@@ -348,19 +361,21 @@ public class SettingsMigrationService extends PlainMigrationService {
*
* @param oldProperty The old property (create a temporary {@link Property} object with the path)
* @param newProperty The new property to move the value to
* @param resource The property resource
* @param reader The property reader
* @param configData Configuration data
* @param <T> The type of the property
* @return True if a migration has been done, false otherwise
*/
private static <T> boolean moveProperty(Property<T> oldProperty,
Property<T> newProperty,
PropertyResource resource) {
if (resource.contains(oldProperty.getPath())) {
if (resource.contains(newProperty.getPath())) {
protected static <T> boolean moveProperty(Property<T> oldProperty,
Property<T> newProperty,
PropertyReader reader,
ConfigurationData configData) {
if (reader.contains(oldProperty.getPath())) {
if (reader.contains(newProperty.getPath())) {
ConsoleLogger.info("Detected deprecated property " + oldProperty.getPath());
} else {
ConsoleLogger.info("Renaming " + oldProperty.getPath() + " to " + newProperty.getPath());
resource.setValue(newProperty.getPath(), oldProperty.getValue(resource));
configData.setValue(newProperty, oldProperty.determineValue(reader));
}
return true;
}
@@ -1,6 +1,7 @@
package fr.xephi.authme.settings.commandconfig;
import ch.jalu.configme.SettingsManager;
import ch.jalu.configme.SettingsManagerBuilder;
import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.initialization.Reloadable;
import fr.xephi.authme.service.BukkitService;
@@ -148,8 +149,11 @@ public class CommandManager implements Reloadable {
File file = new File(dataFolder, "commands.yml");
FileUtils.copyFileFromResource(file, "commands.yml");
SettingsManager settingsManager = new SettingsManager(
YamlFileResourceProvider.loadFromFile(file), commandMigrationService, CommandSettingsHolder.class);
SettingsManager settingsManager = SettingsManagerBuilder
.withResource(YamlFileResourceProvider.loadFromFile(file))
.configurationData(CommandSettingsHolder.class)
.migrationService(commandMigrationService)
.create();
CommandConfig commandConfig = settingsManager.getProperty(CommandSettingsHolder.COMMANDS);
onJoinCommands = newReplacer(commandConfig.getOnJoin());
onLoginCommands = newOnLoginCmdReplacer(commandConfig.getOnLogin());
@@ -1,8 +1,8 @@
package fr.xephi.authme.settings.commandconfig;
import ch.jalu.configme.configurationdata.ConfigurationData;
import ch.jalu.configme.migration.MigrationService;
import ch.jalu.configme.properties.Property;
import ch.jalu.configme.resource.PropertyResource;
import ch.jalu.configme.resource.PropertyReader;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import fr.xephi.authme.settings.SettingsMigrationService;
@@ -30,10 +30,10 @@ class CommandMigrationService implements MigrationService {
}
@Override
public boolean checkAndMigrate(PropertyResource resource, List<Property<?>> properties) {
final CommandConfig commandConfig = CommandSettingsHolder.COMMANDS.getValue(resource);
if (moveOtherAccountsConfig(commandConfig) || isFileEmpty(resource)) {
resource.setValue("", commandConfig);
public boolean checkAndMigrate(PropertyReader reader, ConfigurationData configurationData) {
final CommandConfig commandConfig = CommandSettingsHolder.COMMANDS.determineValue(reader);
if (moveOtherAccountsConfig(commandConfig) || isAnyCommandMissing(reader)) {
configurationData.setValue(CommandSettingsHolder.COMMANDS, commandConfig);
return true;
}
return false;
@@ -59,7 +59,7 @@ class CommandMigrationService implements MigrationService {
.replace("%playerip%", "%ip");
}
private static boolean isFileEmpty(PropertyResource resource) {
return COMMAND_CONFIG_PROPERTIES.stream().anyMatch(property -> resource.getObject(property) == null);
private static boolean isAnyCommandMissing(PropertyReader reader) {
return COMMAND_CONFIG_PROPERTIES.stream().anyMatch(property -> reader.getObject(property) == null);
}
}
@@ -1,13 +1,10 @@
package fr.xephi.authme.settings.commandconfig;
import ch.jalu.configme.SectionComments;
import ch.jalu.configme.SettingsHolder;
import ch.jalu.configme.configurationdata.CommentsConfiguration;
import ch.jalu.configme.properties.BeanProperty;
import ch.jalu.configme.properties.Property;
import java.util.HashMap;
import java.util.Map;
/**
* Settings holder class for the commands.yml settings.
*/
@@ -16,12 +13,11 @@ public final class CommandSettingsHolder implements SettingsHolder {
public static final Property<CommandConfig> COMMANDS =
new BeanProperty<>(CommandConfig.class, "", new CommandConfig());
private CommandSettingsHolder() {
}
@SectionComments
public static Map<String, String[]> sectionComments() {
@Override
public void registerComments(CommentsConfiguration conf) {
String[] rootComments = {
"This configuration file allows you to execute commands on various events.",
"Supported placeholders in commands:",
@@ -60,21 +56,15 @@ public final class CommandSettingsHolder implements SettingsHolder {
" ifNumberOfAccountsAtLeast: 5"
};
Map<String, String[]> commentMap = new HashMap<>();
commentMap.put("", rootComments);
commentMap.put("onFirstLogin", new String[]{
"Commands to run for players logging in whose 'last login date' was empty"
});
commentMap.put("onUnregister", new String[]{
"Commands to run whenever a player is unregistered (by himself, or by an admin)"
});
commentMap.put("onLogout", new String[]{
conf.setComment("", rootComments);
conf.setComment("onFirstLogin",
"Commands to run for players logging in whose 'last login date' was empty");
conf.setComment("onUnregister",
"Commands to run whenever a player is unregistered (by himself, or by an admin)");
conf.setComment("onLogout",
"These commands are called whenever a logged in player uses /logout or quits.",
"The commands are not run if a player that was not logged in quits the server.",
"Note: if your server crashes, these commands won't be run, so don't rely on them to undo",
"'onLogin' commands that would be dangerous for non-logged in players to have!"
});
return commentMap;
"'onLogin' commands that would be dangerous for non-logged in players to have!");
}
}
@@ -19,7 +19,7 @@ public final class AuthMeSettingsRetriever {
* @return configuration data
*/
public static ConfigurationData buildConfigurationData() {
return ConfigurationDataBuilder.collectData(
return ConfigurationDataBuilder.createConfiguration(
DatabaseSettings.class, PluginSettings.class, RestrictionSettings.class,
EmailSettings.class, HooksSettings.class, ProtectionSettings.class,
PurgeSettings.class, SecuritySettings.class, RegistrationSettings.class,
@@ -1,12 +1,9 @@
package fr.xephi.authme.settings.properties;
import ch.jalu.configme.Comment;
import ch.jalu.configme.SectionComments;
import ch.jalu.configme.SettingsHolder;
import ch.jalu.configme.configurationdata.CommentsConfiguration;
import ch.jalu.configme.properties.Property;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
@@ -51,9 +48,9 @@ public final class ConverterSettings implements SettingsHolder {
private ConverterSettings() {
}
@SectionComments
public static Map<String, String[]> buildSectionComments() {
return ImmutableMap.of("Converter",
new String[]{"Converter settings: see https://github.com/AuthMe/AuthMeReloaded/wiki/Converters"});
@Override
public void registerComments(CommentsConfiguration conf) {
conf.setComment("Converter",
"Converter settings: see https://github.com/AuthMe/AuthMeReloaded/wiki/Converters");
}
}
@@ -1,17 +1,14 @@
package fr.xephi.authme.settings.properties;
import ch.jalu.configme.Comment;
import ch.jalu.configme.SectionComments;
import ch.jalu.configme.SettingsHolder;
import ch.jalu.configme.configurationdata.CommentsConfiguration;
import ch.jalu.configme.properties.Property;
import com.google.common.collect.ImmutableMap;
import fr.xephi.authme.data.limbo.AllowFlightRestoreType;
import fr.xephi.authme.data.limbo.WalkFlySpeedRestoreType;
import fr.xephi.authme.data.limbo.persistence.LimboPersistenceType;
import fr.xephi.authme.data.limbo.persistence.SegmentSize;
import java.util.Map;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
/**
@@ -72,8 +69,8 @@ public final class LimboSettings implements SettingsHolder {
private LimboSettings() {
}
@SectionComments
public static Map<String, String[]> createSectionComments() {
@Override
public void registerComments(CommentsConfiguration conf) {
String[] limboExplanation = {
"Before a user logs in, various properties are temporarily removed from the player,",
"such as OP status, ability to fly, and walk/fly speed.",
@@ -81,6 +78,6 @@ public final class LimboSettings implements SettingsHolder {
"In this section, you may define how these properties should be handled.",
"Read more at https://github.com/AuthMe/AuthMeReloaded/wiki/Limbo-players"
};
return ImmutableMap.of("limbo", limboExplanation);
conf.setComment("limbo", limboExplanation);
}
}
@@ -5,9 +5,10 @@ import ch.jalu.configme.SettingsHolder;
import ch.jalu.configme.properties.Property;
import java.util.List;
import java.util.Set;
import static ch.jalu.configme.properties.PropertyInitializer.newListProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newLowercaseListProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newLowercaseStringSetProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public final class RestrictionSettings implements SettingsHolder {
@@ -24,8 +25,8 @@ public final class RestrictionSettings implements SettingsHolder {
newProperty("settings.restrictions.hideChat", false);
@Comment("Allowed commands for unauthenticated players")
public static final Property<List<String>> ALLOW_COMMANDS =
newLowercaseListProperty("settings.restrictions.allowCommands",
public static final Property<Set<String>> ALLOW_COMMANDS =
newLowercaseStringSetProperty("settings.restrictions.allowCommands",
"/login", "/register", "/l", "/reg", "/email", "/captcha", "/2fa", "/totp");
@Comment({
@@ -83,8 +84,8 @@ public final class RestrictionSettings implements SettingsHolder {
" AllowedRestrictedUser:",
" - playername;127.0.0.1",
" - playername;regex:127\\.0\\.0\\..*"})
public static final Property<List<String>> RESTRICTED_USERS =
newLowercaseListProperty("settings.restrictions.AllowedRestrictedUser");
public static final Property<Set<String>> RESTRICTED_USERS =
newLowercaseStringSetProperty("settings.restrictions.AllowedRestrictedUser");
@Comment("Ban unknown IPs trying to log in with a restricted username?")
public static final Property<Boolean> BAN_UNKNOWN_IP =
@@ -177,8 +178,8 @@ public final class RestrictionSettings implements SettingsHolder {
"- 'npcPlayer'",
"- 'npcPlayer2'"
})
public static final Property<List<String>> UNRESTRICTED_NAMES =
newLowercaseListProperty("settings.unrestrictions.UnrestrictedName");
public static final Property<Set<String>> UNRESTRICTED_NAMES =
newLowercaseStringSetProperty("settings.unrestrictions.UnrestrictedName");
private RestrictionSettings() {
}
@@ -6,10 +6,9 @@ import ch.jalu.configme.properties.Property;
import fr.xephi.authme.security.HashAlgorithm;
import fr.xephi.authme.settings.EnumSetProperty;
import java.util.List;
import java.util.Set;
import static ch.jalu.configme.properties.PropertyInitializer.newLowercaseListProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newLowercaseStringSetProperty;
import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
public final class SecuritySettings implements SettingsHolder {
@@ -86,8 +85,8 @@ public final class SecuritySettings implements SettingsHolder {
"- '123456'",
"- 'password'",
"- 'help'"})
public static final Property<List<String>> UNSAFE_PASSWORDS =
newLowercaseListProperty("settings.security.unsafePasswords",
public static final Property<Set<String>> UNSAFE_PASSWORDS =
newLowercaseStringSetProperty("settings.security.unsafePasswords",
"123456", "password", "qwerty", "12345", "54321", "123456789", "help");
@Comment("Tempban a user's IP address if they enter the wrong password too many times")