Merge pull request #120 from AuthMe-Team/603-improve-settings
603 improve settings
This commit is contained in:
commit
f448cb5f9c
@ -44,6 +44,7 @@ import fr.xephi.authme.security.PasswordSecurity;
|
|||||||
import fr.xephi.authme.security.crypts.SHA256;
|
import fr.xephi.authme.security.crypts.SHA256;
|
||||||
import fr.xephi.authme.settings.NewSetting;
|
import fr.xephi.authme.settings.NewSetting;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.SettingsMigrationService;
|
||||||
import fr.xephi.authme.settings.SpawnLoader;
|
import fr.xephi.authme.settings.SpawnLoader;
|
||||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||||
@ -52,6 +53,8 @@ import fr.xephi.authme.settings.properties.PluginSettings;
|
|||||||
import fr.xephi.authme.settings.properties.PurgeSettings;
|
import fr.xephi.authme.settings.properties.PurgeSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
|
import fr.xephi.authme.settings.properties.SettingsFieldRetriever;
|
||||||
|
import fr.xephi.authme.settings.propertymap.PropertyMap;
|
||||||
import fr.xephi.authme.util.CollectionUtils;
|
import fr.xephi.authme.util.CollectionUtils;
|
||||||
import fr.xephi.authme.util.FileUtils;
|
import fr.xephi.authme.util.FileUtils;
|
||||||
import fr.xephi.authme.util.GeoLiteAPI;
|
import fr.xephi.authme.util.GeoLiteAPI;
|
||||||
@ -464,8 +467,10 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
private NewSetting createNewSetting() {
|
private NewSetting createNewSetting() {
|
||||||
File configFile = new File(getDataFolder(), "config.yml");
|
File configFile = new File(getDataFolder(), "config.yml");
|
||||||
|
PropertyMap properties = SettingsFieldRetriever.getAllPropertyFields();
|
||||||
|
SettingsMigrationService migrationService = new SettingsMigrationService();
|
||||||
return FileUtils.copyFileFromResource(configFile, "config.yml")
|
return FileUtils.copyFileFromResource(configFile, "config.yml")
|
||||||
? new NewSetting(configFile, getDataFolder())
|
? new NewSetting(configFile, getDataFolder(), properties, migrationService)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,7 +679,10 @@ public class AuthMe extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
String name = player.getName().toLowerCase();
|
String name = player.getName().toLowerCase();
|
||||||
if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead() && Settings.isSaveQuitLocationEnabled) {
|
if (PlayerCache.getInstance().isAuthenticated(name) && !player.isDead() && Settings.isSaveQuitLocationEnabled) {
|
||||||
final PlayerAuth auth = new PlayerAuth(player.getName().toLowerCase(), player.getLocation().getX(), player.getLocation().getY(), player.getLocation().getZ(), player.getWorld().getName(), player.getName());
|
final PlayerAuth auth = PlayerAuth.builder()
|
||||||
|
.name(player.getName().toLowerCase())
|
||||||
|
.realName(player.getName())
|
||||||
|
.location(player.getLocation()).build();
|
||||||
database.updateQuitLoc(auth);
|
database.updateQuitLoc(auth);
|
||||||
}
|
}
|
||||||
if (LimboCache.getInstance().hasLimboPlayer(name)) {
|
if (LimboCache.getInstance().hasLimboPlayer(name)) {
|
||||||
|
|||||||
@ -8,20 +8,24 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* AuthMe player data.
|
||||||
*/
|
*/
|
||||||
public class PlayerAuth {
|
public class PlayerAuth {
|
||||||
|
|
||||||
|
/** The player's name in lowercase, e.g. "xephi". */
|
||||||
private String nickname;
|
private String nickname;
|
||||||
|
/** The player's name in the correct casing, e.g. "Xephi". */
|
||||||
|
private String realName;
|
||||||
private HashedPassword password;
|
private HashedPassword password;
|
||||||
|
private String email;
|
||||||
private String ip;
|
private String ip;
|
||||||
|
private int groupId;
|
||||||
private long lastLogin;
|
private long lastLogin;
|
||||||
|
// Fields storing the player's quit location
|
||||||
private double x;
|
private double x;
|
||||||
private double y;
|
private double y;
|
||||||
private double z;
|
private double z;
|
||||||
private String world;
|
private String world;
|
||||||
private int groupId;
|
|
||||||
private String email;
|
|
||||||
private String realName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param serialized String
|
* @param serialized String
|
||||||
@ -31,80 +35,19 @@ public class PlayerAuth {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for PlayerAuth.
|
* Constructor. Instantiate objects with the {@link #builder() builder}.
|
||||||
*
|
*
|
||||||
* @param nickname String
|
* @param nickname all lowercase name of the player
|
||||||
* @param x double
|
* @param password password
|
||||||
* @param y double
|
* @param groupId the group id
|
||||||
* @param z double
|
* @param ip the associated ip address
|
||||||
* @param world String
|
* @param lastLogin player's last login (timestamp)
|
||||||
* @param realName String
|
* @param x quit location: x coordinate
|
||||||
*/
|
* @param y quit location: y coordinate
|
||||||
public PlayerAuth(String nickname, double x, double y, double z, String world, String realName) {
|
* @param z quit location: z coordinate
|
||||||
this(nickname, new HashedPassword(""), -1, "127.0.0.1", System.currentTimeMillis(), x, y, z, world,
|
* @param world quit location: world name
|
||||||
"your@email.com", realName);
|
* @param email the associated email
|
||||||
}
|
* @param realName the player's name with proper casing
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for PlayerAuth.
|
|
||||||
*
|
|
||||||
* @param nickname String
|
|
||||||
* @param hash String
|
|
||||||
* @param ip String
|
|
||||||
* @param lastLogin long
|
|
||||||
* @param realName String
|
|
||||||
*/
|
|
||||||
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, String realName) {
|
|
||||||
this(nickname, new HashedPassword(hash), -1, ip, lastLogin, 0, 0, 0, "world", "your@email.com", realName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for PlayerAuth.
|
|
||||||
*
|
|
||||||
* @param nickname String
|
|
||||||
* @param hash String
|
|
||||||
* @param ip String
|
|
||||||
* @param lastLogin long
|
|
||||||
* @param email String
|
|
||||||
* @param realName String
|
|
||||||
*/
|
|
||||||
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, String email, String realName) {
|
|
||||||
this(nickname, new HashedPassword(hash), -1, ip, lastLogin, 0, 0, 0, "world", email, realName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for PlayerAuth.
|
|
||||||
*
|
|
||||||
* @param nickname String
|
|
||||||
* @param hash String
|
|
||||||
* @param ip String
|
|
||||||
* @param lastLogin long
|
|
||||||
* @param x double
|
|
||||||
* @param y double
|
|
||||||
* @param z double
|
|
||||||
* @param world String
|
|
||||||
* @param email String
|
|
||||||
* @param realName String
|
|
||||||
*/
|
|
||||||
public PlayerAuth(String nickname, String hash, String ip, long lastLogin, double x, double y, double z,
|
|
||||||
String world, String email, String realName) {
|
|
||||||
this(nickname, new HashedPassword(hash), -1, ip, lastLogin, x, y, z, world, email, realName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for PlayerAuth.
|
|
||||||
*
|
|
||||||
* @param nickname String
|
|
||||||
* @param password String
|
|
||||||
* @param groupId int
|
|
||||||
* @param ip String
|
|
||||||
* @param lastLogin long
|
|
||||||
* @param x double
|
|
||||||
* @param y double
|
|
||||||
* @param z double
|
|
||||||
* @param world String
|
|
||||||
* @param email String
|
|
||||||
* @param realName String
|
|
||||||
*/
|
*/
|
||||||
private PlayerAuth(String nickname, HashedPassword password, int groupId, String ip, long lastLogin,
|
private PlayerAuth(String nickname, HashedPassword password, int groupId, String ip, long lastLogin,
|
||||||
double x, double y, double z, String world, String email, String realName) {
|
double x, double y, double z, String world, String email, String realName) {
|
||||||
@ -121,24 +64,6 @@ public class PlayerAuth {
|
|||||||
this.realName = realName;
|
this.realName = realName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method set.
|
|
||||||
*
|
|
||||||
* @param auth PlayerAuth
|
|
||||||
*/
|
|
||||||
public void set(PlayerAuth auth) {
|
|
||||||
this.setEmail(auth.getEmail());
|
|
||||||
this.setPassword(auth.getPassword());
|
|
||||||
this.setIp(auth.getIp());
|
|
||||||
this.setLastLogin(auth.getLastLogin());
|
|
||||||
this.setNickname(auth.getNickname());
|
|
||||||
this.setQuitLocX(auth.getQuitLocX());
|
|
||||||
this.setQuitLocY(auth.getQuitLocY());
|
|
||||||
this.setQuitLocZ(auth.getQuitLocZ());
|
|
||||||
this.setWorld(auth.getWorld());
|
|
||||||
this.setRealName(auth.getRealName());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setNickname(String nickname) {
|
public void setNickname(String nickname) {
|
||||||
this.nickname = nickname.toLowerCase();
|
this.nickname = nickname.toLowerCase();
|
||||||
|
|||||||
@ -31,27 +31,13 @@ public class CrazyLoginConverter implements Converter {
|
|||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method getInstance.
|
|
||||||
*
|
|
||||||
* @return CrazyLoginConverter
|
|
||||||
*/
|
|
||||||
public CrazyLoginConverter getInstance() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method run.
|
|
||||||
*
|
|
||||||
* @see java.lang.Runnable#run()
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String fileName = Settings.crazyloginFileName;
|
String fileName = Settings.crazyloginFileName;
|
||||||
try {
|
try {
|
||||||
File source = new File(AuthMe.getInstance().getDataFolder() + File.separator + fileName);
|
File source = new File(AuthMe.getInstance().getDataFolder() + File.separator + fileName);
|
||||||
if (!source.exists()) {
|
if (!source.exists()) {
|
||||||
sender.sendMessage("Error while trying to import datas, please put " + fileName + " in AuthMe folder!");
|
sender.sendMessage("Error while trying to import data, please put " + fileName + " in AuthMe folder!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String line;
|
String line;
|
||||||
@ -59,14 +45,17 @@ public class CrazyLoginConverter implements Converter {
|
|||||||
while ((line = users.readLine()) != null) {
|
while ((line = users.readLine()) != null) {
|
||||||
if (line.contains("|")) {
|
if (line.contains("|")) {
|
||||||
String[] args = line.split("\\|");
|
String[] args = line.split("\\|");
|
||||||
if (args.length < 2)
|
if (args.length < 2 || "name".equalsIgnoreCase(args[0])) {
|
||||||
continue;
|
continue;
|
||||||
if (args[0].equalsIgnoreCase("name"))
|
}
|
||||||
continue;
|
String playerName = args[0];
|
||||||
String playerName = args[0].toLowerCase();
|
|
||||||
String psw = args[1];
|
String psw = args[1];
|
||||||
if (psw != null) {
|
if (psw != null) {
|
||||||
PlayerAuth auth = new PlayerAuth(playerName, psw, "127.0.0.1", System.currentTimeMillis(), playerName);
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
|
.name(playerName.toLowerCase())
|
||||||
|
.realName(playerName)
|
||||||
|
.password(psw, null)
|
||||||
|
.build();
|
||||||
database.saveAuth(auth);
|
database.saveAuth(auth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,35 +5,46 @@ import fr.xephi.authme.ConsoleLogger;
|
|||||||
import fr.xephi.authme.cache.auth.PlayerAuth;
|
import fr.xephi.authme.cache.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.util.StringUtils.makePath;
|
||||||
|
|
||||||
public class RoyalAuthConverter implements Converter {
|
public class RoyalAuthConverter implements Converter {
|
||||||
|
|
||||||
|
private static final String LAST_LOGIN_PATH = "timestamps.quit";
|
||||||
|
private static final String PASSWORD_PATH = "login.password";
|
||||||
private final AuthMe plugin;
|
private final AuthMe plugin;
|
||||||
private final DataSource data;
|
private final DataSource dataSource;
|
||||||
|
|
||||||
public RoyalAuthConverter(AuthMe plugin) {
|
public RoyalAuthConverter(AuthMe plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.data = plugin.getDataSource();
|
this.dataSource = plugin.getDataSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
for (OfflinePlayer o : plugin.getServer().getOfflinePlayers()) {
|
for (OfflinePlayer player : plugin.getServer().getOfflinePlayers()) {
|
||||||
try {
|
try {
|
||||||
String name = o.getName().toLowerCase();
|
String name = player.getName().toLowerCase();
|
||||||
String sp = File.separator;
|
File file = new File(makePath(".", "plugins", "RoyalAuth", "userdata", name + ".yml"));
|
||||||
File file = new File("." + sp + "plugins" + sp + "RoyalAuth" + sp + "userdata" + sp + name + ".yml");
|
|
||||||
if (data.isAuthAvailable(name))
|
if (dataSource.isAuthAvailable(name) || !file.exists()) {
|
||||||
continue;
|
continue;
|
||||||
if (!file.exists())
|
}
|
||||||
continue;
|
FileConfiguration configuration = YamlConfiguration.loadConfiguration(file);
|
||||||
RoyalAuthYamlReader ra = new RoyalAuthYamlReader(file);
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
PlayerAuth auth = new PlayerAuth(name, ra.getHash(), "127.0.0.1", ra.getLastLogin(), "your@email.com", o.getName());
|
.name(name)
|
||||||
data.saveAuth(auth);
|
.password(configuration.getString(PASSWORD_PATH), null)
|
||||||
|
.lastLogin(configuration.getLong(LAST_LOGIN_PATH))
|
||||||
|
.realName(player.getName())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
dataSource.saveAuth(auth);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ConsoleLogger.logException("Error while trying to import " + o.getName() + " RoyalAuth data", e);
|
ConsoleLogger.logException("Error while trying to import " + player.getName() + " RoyalAuth data", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
package fr.xephi.authme.converter;
|
|
||||||
|
|
||||||
import fr.xephi.authme.settings.CustomConfiguration;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
class RoyalAuthYamlReader extends CustomConfiguration {
|
|
||||||
|
|
||||||
public RoyalAuthYamlReader(File file) {
|
|
||||||
super(file);
|
|
||||||
load();
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLastLogin() {
|
|
||||||
return getLong("timestamps.quit");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHash() {
|
|
||||||
return getString("login.password");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -12,6 +12,8 @@ import java.io.IOException;
|
|||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.util.StringUtils.makePath;
|
||||||
|
|
||||||
class vAuthFileReader {
|
class vAuthFileReader {
|
||||||
|
|
||||||
private final AuthMe plugin;
|
private final AuthMe plugin;
|
||||||
@ -28,7 +30,7 @@ class vAuthFileReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void convert() {
|
public void convert() {
|
||||||
final File file = new File(plugin.getDataFolder().getParent() + File.separator + "vAuth" + File.separator + "passwords.yml");
|
final File file = new File(plugin.getDataFolder().getParent(), makePath("vAuth", "passwords.yml"));
|
||||||
Scanner scanner;
|
Scanner scanner;
|
||||||
try {
|
try {
|
||||||
scanner = new Scanner(file);
|
scanner = new Scanner(file);
|
||||||
@ -46,9 +48,15 @@ class vAuthFileReader {
|
|||||||
}
|
}
|
||||||
if (pname == null)
|
if (pname == null)
|
||||||
continue;
|
continue;
|
||||||
auth = new PlayerAuth(pname.toLowerCase(), password, "127.0.0.1", System.currentTimeMillis(), "your@email.com", pname);
|
auth = PlayerAuth.builder()
|
||||||
|
.name(pname.toLowerCase())
|
||||||
|
.realName(pname)
|
||||||
|
.password(password, null).build();
|
||||||
} else {
|
} else {
|
||||||
auth = new PlayerAuth(name.toLowerCase(), password, "127.0.0.1", System.currentTimeMillis(), "your@email.com", name);
|
auth = PlayerAuth.builder()
|
||||||
|
.name(name.toLowerCase())
|
||||||
|
.realName(name)
|
||||||
|
.password(password, null).build();
|
||||||
}
|
}
|
||||||
database.saveAuth(auth);
|
database.saveAuth(auth);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,10 @@ class xAuthToFlat {
|
|||||||
String pl = getIdPlayer(id);
|
String pl = getIdPlayer(id);
|
||||||
String psw = getPassword(id);
|
String psw = getPassword(id);
|
||||||
if (psw != null && !psw.isEmpty() && pl != null) {
|
if (psw != null && !psw.isEmpty() && pl != null) {
|
||||||
PlayerAuth auth = new PlayerAuth(pl, psw, "192.168.0.1", 0, "your@email.com", pl);
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
|
.name(pl.toLowerCase())
|
||||||
|
.realName(pl)
|
||||||
|
.password(psw, null).build();
|
||||||
database.saveAuth(auth);
|
database.saveAuth(auth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +72,8 @@ class xAuthToFlat {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = String.format("SELECT `playername` FROM `%s` WHERE `id` = ?", xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
|
String sql = String.format("SELECT `playername` FROM `%s` WHERE `id` = ?",
|
||||||
|
xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
|
||||||
ps = conn.prepareStatement(sql);
|
ps = conn.prepareStatement(sql);
|
||||||
ps.setInt(1, id);
|
ps.setInt(1, id);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
@ -91,7 +95,8 @@ class xAuthToFlat {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = String.format("SELECT * FROM `%s`", xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
|
String sql = String.format("SELECT * FROM `%s`",
|
||||||
|
xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
|
||||||
ps = conn.prepareStatement(sql);
|
ps = conn.prepareStatement(sql);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
@ -112,7 +117,8 @@ class xAuthToFlat {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = String.format("SELECT `password`, `pwtype` FROM `%s` WHERE `id` = ?", xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
|
String sql = String.format("SELECT `password`, `pwtype` FROM `%s` WHERE `id` = ?",
|
||||||
|
xAuth.getPlugin().getDatabaseController().getTable(DatabaseTables.ACCOUNT));
|
||||||
ps = conn.prepareStatement(sql);
|
ps = conn.prepareStatement(sql);
|
||||||
ps.setInt(1, accountId);
|
ps.setInt(1, accountId);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import fr.xephi.authme.settings.Settings;
|
|||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
@ -19,6 +20,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Deprecated flat file datasource. The only method guaranteed to work is {@link FlatFile#getAllAuths()}
|
||||||
|
* as to migrate the entries to {@link SQLite} when AuthMe starts.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class FlatFile implements DataSource {
|
public class FlatFile implements DataSource {
|
||||||
@ -76,19 +79,11 @@ public class FlatFile implements DataSource {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
|
||||||
return false;
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -110,17 +105,12 @@ public class FlatFile implements DataSource {
|
|||||||
BufferedWriter bw = null;
|
BufferedWriter bw = null;
|
||||||
try {
|
try {
|
||||||
bw = new BufferedWriter(new FileWriter(source, true));
|
bw = new BufferedWriter(new FileWriter(source, true));
|
||||||
bw.write(auth.getNickname() + ":" + auth.getPassword() + ":" + auth.getIp() + ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY() + ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n");
|
bw.write(auth.getNickname() + ":" + auth.getPassword().getHash() + ":" + auth.getIp() + ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY() + ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n");
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
if (bw != null) {
|
silentClose(bw);
|
||||||
try {
|
|
||||||
bw.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -131,6 +121,7 @@ public class FlatFile implements DataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
// Note ljacqu 20151230: This does not persist the salt; it is not supported in flat file.
|
||||||
public boolean updatePassword(String user, HashedPassword password) {
|
public boolean updatePassword(String user, HashedPassword password) {
|
||||||
user = user.toLowerCase();
|
user = user.toLowerCase();
|
||||||
if (!isAuthAvailable(user)) {
|
if (!isAuthAvailable(user)) {
|
||||||
@ -144,45 +135,18 @@ public class FlatFile implements DataSource {
|
|||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
String[] args = line.split(":");
|
String[] args = line.split(":");
|
||||||
if (args[0].equals(user)) {
|
if (args[0].equals(user)) {
|
||||||
// Note ljacqu 20151230: This does not persist the salt; it is not supported in flat file.
|
newAuth = buildAuthFromArray(args);
|
||||||
switch (args.length) {
|
if (newAuth != null) {
|
||||||
case 4: {
|
newAuth.setPassword(password);
|
||||||
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), 0, 0, 0, "world", "your@email.com", args[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 7: {
|
|
||||||
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "world", "your@email.com", args[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 8: {
|
|
||||||
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 9: {
|
|
||||||
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
newAuth = new PlayerAuth(args[0], password.getHash(), args[2], 0, 0, 0, 0, "world", "your@email.com", args[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
|
||||||
return false;
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (newAuth != null) {
|
if (newAuth != null) {
|
||||||
removeAuth(user);
|
removeAuth(user);
|
||||||
@ -204,44 +168,19 @@ public class FlatFile implements DataSource {
|
|||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
String[] args = line.split(":");
|
String[] args = line.split(":");
|
||||||
if (args[0].equalsIgnoreCase(auth.getNickname())) {
|
if (args[0].equalsIgnoreCase(auth.getNickname())) {
|
||||||
switch (args.length) {
|
newAuth = buildAuthFromArray(args);
|
||||||
case 4: {
|
if (newAuth != null) {
|
||||||
newAuth = new PlayerAuth(args[0], args[1], auth.getIp(), auth.getLastLogin(), 0, 0, 0, "world", "your@email.com", args[0]);
|
newAuth.setLastLogin(auth.getLastLogin());
|
||||||
break;
|
newAuth.setIp(auth.getIp());
|
||||||
}
|
|
||||||
case 7: {
|
|
||||||
newAuth = new PlayerAuth(args[0], args[1], auth.getIp(), auth.getLastLogin(), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "world", "your@email.com", args[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 8: {
|
|
||||||
newAuth = new PlayerAuth(args[0], args[1], auth.getIp(), auth.getLastLogin(), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 9: {
|
|
||||||
newAuth = new PlayerAuth(args[0], args[1], auth.getIp(), auth.getLastLogin(), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
newAuth = new PlayerAuth(args[0], args[1], auth.getIp(), auth.getLastLogin(), 0, 0, 0, "world", "your@email.com", args[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
|
||||||
return false;
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (newAuth != null) {
|
if (newAuth != null) {
|
||||||
removeAuth(auth.getNickname());
|
removeAuth(auth.getNickname());
|
||||||
@ -263,23 +202,22 @@ public class FlatFile implements DataSource {
|
|||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
String[] args = line.split(":");
|
String[] args = line.split(":");
|
||||||
if (args[0].equalsIgnoreCase(auth.getNickname())) {
|
if (args[0].equalsIgnoreCase(auth.getNickname())) {
|
||||||
newAuth = new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ(), auth.getWorld(), auth.getEmail(), args[0]);
|
newAuth = buildAuthFromArray(args);
|
||||||
|
if (newAuth != null) {
|
||||||
|
newAuth.setQuitLocX(auth.getQuitLocX());
|
||||||
|
newAuth.setQuitLocY(auth.getQuitLocY());
|
||||||
|
newAuth.setQuitLocZ(auth.getQuitLocZ());
|
||||||
|
newAuth.setWorld(auth.getWorld());
|
||||||
|
newAuth.setEmail(auth.getEmail());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
|
||||||
return false;
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (newAuth != null) {
|
if (newAuth != null) {
|
||||||
removeAuth(auth.getNickname());
|
removeAuth(auth.getNickname());
|
||||||
@ -311,25 +249,12 @@ public class FlatFile implements DataSource {
|
|||||||
for (String l : lines) {
|
for (String l : lines) {
|
||||||
bw.write(l + "\n");
|
bw.write(l + "\n");
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
|
||||||
return cleared;
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
return cleared;
|
return cleared;
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
silentClose(bw);
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bw != null) {
|
|
||||||
try {
|
|
||||||
bw.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return cleared;
|
return cleared;
|
||||||
}
|
}
|
||||||
@ -355,25 +280,12 @@ public class FlatFile implements DataSource {
|
|||||||
for (String l : lines) {
|
for (String l : lines) {
|
||||||
bw.write(l + "\n");
|
bw.write(l + "\n");
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
|
||||||
return false;
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
return false;
|
return false;
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
silentClose(bw);
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bw != null) {
|
|
||||||
try {
|
|
||||||
bw.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -387,35 +299,14 @@ public class FlatFile implements DataSource {
|
|||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
String[] args = line.split(":");
|
String[] args = line.split(":");
|
||||||
if (args[0].equalsIgnoreCase(user)) {
|
if (args[0].equalsIgnoreCase(user)) {
|
||||||
switch (args.length) {
|
return buildAuthFromArray(args);
|
||||||
case 2:
|
|
||||||
return new PlayerAuth(args[0], args[1], "192.168.0.1", 0, "your@email.com", args[0]);
|
|
||||||
case 3:
|
|
||||||
return new PlayerAuth(args[0], args[1], args[2], 0, "your@email.com", args[0]);
|
|
||||||
case 4:
|
|
||||||
return new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), "your@email.com", args[0]);
|
|
||||||
case 7:
|
|
||||||
return new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), "unavailableworld", "your@email.com", args[0]);
|
|
||||||
case 8:
|
|
||||||
return new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], "your@email.com", args[0]);
|
|
||||||
case 9:
|
|
||||||
return new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], args[8], args[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
|
||||||
return null;
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -437,7 +328,10 @@ public class FlatFile implements DataSource {
|
|||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
String[] args = line.split(":");
|
String[] args = line.split(":");
|
||||||
if (args[0].equals(auth.getNickname())) {
|
if (args[0].equals(auth.getNickname())) {
|
||||||
newAuth = new PlayerAuth(args[0], args[1], args[2], Long.parseLong(args[3]), Double.parseDouble(args[4]), Double.parseDouble(args[5]), Double.parseDouble(args[6]), args[7], auth.getEmail(), args[0]);
|
newAuth = buildAuthFromArray(args);
|
||||||
|
if (newAuth != null) {
|
||||||
|
newAuth.setEmail(auth.getEmail());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,18 +439,8 @@ public class FlatFile implements DataSource {
|
|||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
silentClose(bw);
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bw != null) {
|
|
||||||
try {
|
|
||||||
bw.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,12 +479,7 @@ public class FlatFile implements DataSource {
|
|||||||
ConsoleLogger.showError(ex.getMessage());
|
ConsoleLogger.showError(ex.getMessage());
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -624,32 +503,15 @@ public class FlatFile implements DataSource {
|
|||||||
String line;
|
String line;
|
||||||
while ((line = br.readLine()) != null) {
|
while ((line = br.readLine()) != null) {
|
||||||
String[] args = line.split(":");
|
String[] args = line.split(":");
|
||||||
// We expect to encounter 2, 3, 4, 7, 8 or 9 fields. Ignore the line otherwise
|
PlayerAuth auth = buildAuthFromArray(args);
|
||||||
if (args.length >= 2 && args.length != 5 && args.length != 6 && args.length <= 9) {
|
if (auth != null) {
|
||||||
PlayerAuth.Builder builder = PlayerAuth.builder()
|
auths.add(auth);
|
||||||
.name(args[0]).realName(args[0])
|
|
||||||
.password(args[1], null);
|
|
||||||
if (args.length >= 3) builder.ip(args[2]);
|
|
||||||
if (args.length >= 4) builder.lastLogin(Long.parseLong(args[3]));
|
|
||||||
if (args.length >= 7) {
|
|
||||||
builder.locX(Double.parseDouble(args[4]))
|
|
||||||
.locY(Double.parseDouble(args[5]))
|
|
||||||
.locZ(Double.parseDouble(args[6]));
|
|
||||||
}
|
|
||||||
if (args.length >= 8) builder.locWorld(args[7]);
|
|
||||||
if (args.length >= 9) builder.email(args[8]);
|
|
||||||
auths.add(builder.build());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
ConsoleLogger.logException("Error while getting auths from flatfile:", ex);
|
ConsoleLogger.logException("Error while getting auths from flatfile:", ex);
|
||||||
} finally {
|
} finally {
|
||||||
if (br != null) {
|
silentClose(br);
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return auths;
|
return auths;
|
||||||
}
|
}
|
||||||
@ -663,4 +525,34 @@ public class FlatFile implements DataSource {
|
|||||||
public boolean isEmailStored(String email) {
|
public boolean isEmailStored(String email) {
|
||||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static PlayerAuth buildAuthFromArray(String[] args) {
|
||||||
|
// Format allows 2, 3, 4, 7, 8, 9 fields. Anything else is unknown
|
||||||
|
if (args.length >= 2 && args.length <= 9 && args.length != 5 && args.length != 6) {
|
||||||
|
PlayerAuth.Builder builder = PlayerAuth.builder()
|
||||||
|
.name(args[0]).realName(args[0]).password(args[1], null);
|
||||||
|
|
||||||
|
if (args.length >= 3) builder.ip(args[2]);
|
||||||
|
if (args.length >= 4) builder.lastLogin(Long.parseLong(args[3]));
|
||||||
|
if (args.length >= 7) {
|
||||||
|
builder.locX(Double.parseDouble(args[4]))
|
||||||
|
.locY(Double.parseDouble(args[5]))
|
||||||
|
.locZ(Double.parseDouble(args[6]));
|
||||||
|
}
|
||||||
|
if (args.length >= 8) builder.locWorld(args[7]);
|
||||||
|
if (args.length >= 9) builder.email(args[8]);
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void silentClose(Closeable closeable) {
|
||||||
|
if (closeable != null) {
|
||||||
|
try {
|
||||||
|
closeable.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
// silent close
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,94 +0,0 @@
|
|||||||
package fr.xephi.authme.settings;
|
|
||||||
|
|
||||||
import fr.xephi.authme.AuthMe;
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
|
||||||
import org.bukkit.configuration.InvalidConfigurationException;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
public abstract class CustomConfiguration extends YamlConfiguration {
|
|
||||||
|
|
||||||
private final File configFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor for CustomConfiguration.
|
|
||||||
*
|
|
||||||
* @param file the config file
|
|
||||||
*/
|
|
||||||
public CustomConfiguration(File file) {
|
|
||||||
this.configFile = file;
|
|
||||||
load();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load() {
|
|
||||||
try {
|
|
||||||
super.load(configFile);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
ConsoleLogger.showError("Could not find " + configFile.getName() + ", creating new one...");
|
|
||||||
reLoad();
|
|
||||||
} catch (IOException e) {
|
|
||||||
ConsoleLogger.showError("Could not load " + configFile.getName());
|
|
||||||
} catch (InvalidConfigurationException e) {
|
|
||||||
ConsoleLogger.showError(configFile.getName() + " is no valid configuration file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean reLoad() {
|
|
||||||
boolean out = true;
|
|
||||||
if (!configFile.exists()) {
|
|
||||||
out = loadResource(configFile);
|
|
||||||
}
|
|
||||||
if (out)
|
|
||||||
load();
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void save() {
|
|
||||||
try {
|
|
||||||
super.save(configFile);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
ConsoleLogger.showError("Could not save config to " + configFile.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getConfigFile() {
|
|
||||||
return configFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean loadResource(File file) {
|
|
||||||
if (!file.exists()) {
|
|
||||||
try {
|
|
||||||
if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int i = file.getPath().indexOf("AuthMe");
|
|
||||||
if (i > -1) {
|
|
||||||
String path = file.getPath().substring(i + 6).replace('\\', '/');
|
|
||||||
InputStream is = AuthMe.class.getResourceAsStream(path);
|
|
||||||
Files.copy(is, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
ConsoleLogger.logException("Failed to load config from JAR", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsAll(String... paths) {
|
|
||||||
for (String path : paths) {
|
|
||||||
if (!contains(path)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -6,7 +6,6 @@ import fr.xephi.authme.ConsoleLogger;
|
|||||||
import fr.xephi.authme.settings.domain.Property;
|
import fr.xephi.authme.settings.domain.Property;
|
||||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.SettingsFieldRetriever;
|
|
||||||
import fr.xephi.authme.settings.propertymap.PropertyMap;
|
import fr.xephi.authme.settings.propertymap.PropertyMap;
|
||||||
import fr.xephi.authme.util.CollectionUtils;
|
import fr.xephi.authme.util.CollectionUtils;
|
||||||
import fr.xephi.authme.util.StringUtils;
|
import fr.xephi.authme.util.StringUtils;
|
||||||
@ -33,6 +32,8 @@ public class NewSetting {
|
|||||||
|
|
||||||
private final File pluginFolder;
|
private final File pluginFolder;
|
||||||
private final File configFile;
|
private final File configFile;
|
||||||
|
private final PropertyMap propertyMap;
|
||||||
|
private final SettingsMigrationService migrationService;
|
||||||
private FileConfiguration configuration;
|
private FileConfiguration configuration;
|
||||||
/** The file with the localized messages based on {@link PluginSettings#MESSAGES_LANGUAGE}. */
|
/** The file with the localized messages based on {@link PluginSettings#MESSAGES_LANGUAGE}. */
|
||||||
private File messagesFile;
|
private File messagesFile;
|
||||||
@ -44,11 +45,16 @@ public class NewSetting {
|
|||||||
*
|
*
|
||||||
* @param configFile The configuration file
|
* @param configFile The configuration file
|
||||||
* @param pluginFolder The AuthMe plugin folder
|
* @param pluginFolder The AuthMe plugin folder
|
||||||
|
* @param propertyMap Collection of all available settings
|
||||||
|
* @param migrationService Migration service to check the settings file with
|
||||||
*/
|
*/
|
||||||
public NewSetting(File configFile, File pluginFolder) {
|
public NewSetting(File configFile, File pluginFolder, PropertyMap propertyMap,
|
||||||
|
SettingsMigrationService migrationService) {
|
||||||
this.configuration = YamlConfiguration.loadConfiguration(configFile);
|
this.configuration = YamlConfiguration.loadConfiguration(configFile);
|
||||||
this.configFile = configFile;
|
this.configFile = configFile;
|
||||||
this.pluginFolder = pluginFolder;
|
this.pluginFolder = pluginFolder;
|
||||||
|
this.propertyMap = propertyMap;
|
||||||
|
this.migrationService = migrationService;
|
||||||
validateAndLoadOptions();
|
validateAndLoadOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,16 +63,21 @@ public class NewSetting {
|
|||||||
*
|
*
|
||||||
* @param configuration The FileConfiguration object to use
|
* @param configuration The FileConfiguration object to use
|
||||||
* @param configFile The file to write to
|
* @param configFile The file to write to
|
||||||
|
* @param pluginFolder The plugin folder
|
||||||
* @param propertyMap The property map whose properties should be verified for presence, or null to skip this
|
* @param propertyMap The property map whose properties should be verified for presence, or null to skip this
|
||||||
|
* @param migrationService Migration service, or null to skip migration checks
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
NewSetting(FileConfiguration configuration, File configFile, PropertyMap propertyMap) {
|
NewSetting(FileConfiguration configuration, File configFile, File pluginFolder, PropertyMap propertyMap,
|
||||||
|
SettingsMigrationService migrationService) {
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
this.configFile = configFile;
|
this.configFile = configFile;
|
||||||
this.pluginFolder = new File("");
|
this.pluginFolder = pluginFolder;
|
||||||
|
this.propertyMap = propertyMap;
|
||||||
|
this.migrationService = migrationService;
|
||||||
|
|
||||||
if (propertyMap != null && SettingsMigrationService.checkAndMigrate(configuration, propertyMap, pluginFolder)) {
|
if (propertyMap != null && migrationService != null) {
|
||||||
save(propertyMap);
|
validateAndLoadOptions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,13 +103,6 @@ public class NewSetting {
|
|||||||
configuration.set(property.getPath(), value);
|
configuration.set(property.getPath(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Save the config file. Use after migrating one or more settings.
|
|
||||||
*/
|
|
||||||
public void save() {
|
|
||||||
save(SettingsFieldRetriever.getAllPropertyFields());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the messages file based on the messages language config.
|
* Return the messages file based on the messages language config.
|
||||||
*
|
*
|
||||||
@ -133,7 +137,10 @@ public class NewSetting {
|
|||||||
validateAndLoadOptions();
|
validateAndLoadOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void save(PropertyMap propertyMap) {
|
/**
|
||||||
|
* Save the config file. Use after migrating one or more settings.
|
||||||
|
*/
|
||||||
|
public void save() {
|
||||||
try (FileWriter writer = new FileWriter(configFile)) {
|
try (FileWriter writer = new FileWriter(configFile)) {
|
||||||
Yaml simpleYaml = newYaml(false);
|
Yaml simpleYaml = newYaml(false);
|
||||||
Yaml singleQuoteYaml = newYaml(true);
|
Yaml singleQuoteYaml = newYaml(true);
|
||||||
@ -186,11 +193,10 @@ public class NewSetting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void validateAndLoadOptions() {
|
private void validateAndLoadOptions() {
|
||||||
PropertyMap propertyMap = SettingsFieldRetriever.getAllPropertyFields();
|
if (migrationService.checkAndMigrate(configuration, propertyMap, pluginFolder)) {
|
||||||
if (SettingsMigrationService.checkAndMigrate(configuration, propertyMap, pluginFolder)) {
|
|
||||||
ConsoleLogger.info("Merged new config options");
|
ConsoleLogger.info("Merged new config options");
|
||||||
ConsoleLogger.info("Please check your config.yml file for new settings!");
|
ConsoleLogger.info("Please check your config.yml file for new settings!");
|
||||||
save(propertyMap);
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
messagesFile = buildMessagesFile();
|
messagesFile = buildMessagesFile();
|
||||||
@ -205,18 +211,20 @@ public class NewSetting {
|
|||||||
|
|
||||||
private File buildMessagesFile() {
|
private File buildMessagesFile() {
|
||||||
String languageCode = getProperty(PluginSettings.MESSAGES_LANGUAGE);
|
String languageCode = getProperty(PluginSettings.MESSAGES_LANGUAGE);
|
||||||
File messagesFile = buildMessagesFileFromCode(languageCode);
|
|
||||||
if (messagesFile.exists()) {
|
String filePath = buildMessagesFilePathFromCode(languageCode);
|
||||||
|
File messagesFile = new File(pluginFolder, filePath);
|
||||||
|
if (copyFileFromResource(messagesFile, filePath)) {
|
||||||
return messagesFile;
|
return messagesFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
return copyFileFromResource(messagesFile, buildMessagesFilePathFromCode(languageCode))
|
// File doesn't exist or couldn't be copied - try again with default, "en"
|
||||||
? messagesFile
|
String defaultFilePath = buildMessagesFilePathFromCode("en");
|
||||||
: buildMessagesFileFromCode("en");
|
File defaultFile = new File(pluginFolder, defaultFilePath);
|
||||||
}
|
copyFileFromResource(defaultFile, defaultFilePath);
|
||||||
|
|
||||||
private File buildMessagesFileFromCode(String language) {
|
// No matter the result, need to return a file
|
||||||
return new File(pluginFolder, buildMessagesFilePathFromCode(language));
|
return defaultFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildMessagesFilePathFromCode(String language) {
|
private static String buildMessagesFilePathFromCode(String language) {
|
||||||
@ -243,7 +251,7 @@ public class NewSetting {
|
|||||||
final Charset charset = Charset.forName("UTF-8");
|
final Charset charset = Charset.forName("UTF-8");
|
||||||
if (copyFileFromResource(emailFile, "email.html")) {
|
if (copyFileFromResource(emailFile, "email.html")) {
|
||||||
try {
|
try {
|
||||||
return StringUtils.join("", Files.readLines(emailFile, charset));
|
return StringUtils.join("\n", Files.readLines(emailFile, charset));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
ConsoleLogger.logException("Failed to read file '" + emailFile.getPath() + "':", e);
|
ConsoleLogger.logException("Failed to read file '" + emailFile.getPath() + "':", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package fr.xephi.authme.settings;
|
package fr.xephi.authme.settings;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.settings.domain.Property;
|
import fr.xephi.authme.settings.domain.Property;
|
||||||
import fr.xephi.authme.settings.propertymap.PropertyMap;
|
import fr.xephi.authme.settings.propertymap.PropertyMap;
|
||||||
@ -18,25 +17,23 @@ import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_NI
|
|||||||
/**
|
/**
|
||||||
* Service for verifying that the configuration is up-to-date.
|
* Service for verifying that the configuration is up-to-date.
|
||||||
*/
|
*/
|
||||||
public final class SettingsMigrationService {
|
public class SettingsMigrationService {
|
||||||
|
|
||||||
private SettingsMigrationService() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the config file and does any necessary migrations.
|
* Checks the config file and performs any necessary migrations.
|
||||||
*
|
*
|
||||||
* @param configuration The file configuration to check and migrate
|
* @param configuration The file configuration to check and migrate
|
||||||
* @param propertyMap The property map of all existing properties
|
* @param propertyMap The property map of all existing properties
|
||||||
* @param pluginFolder The plugin folder
|
* @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
|
* @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) {
|
public boolean checkAndMigrate(FileConfiguration configuration, PropertyMap propertyMap, File pluginFolder) {
|
||||||
return performMigrations(configuration, pluginFolder) || hasDeprecatedProperties(configuration)
|
return performMigrations(configuration, pluginFolder)
|
||||||
|
|| hasDeprecatedProperties(configuration)
|
||||||
|| !containsAllSettings(configuration, propertyMap);
|
|| !containsAllSettings(configuration, propertyMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean performMigrations(FileConfiguration configuration, File pluginFolder) {
|
private boolean performMigrations(FileConfiguration configuration, File pluginFolder) {
|
||||||
boolean changes = false;
|
boolean changes = false;
|
||||||
if ("[a-zA-Z0-9_?]*".equals(configuration.getString(ALLOWED_NICKNAME_CHARACTERS.getPath()))) {
|
if ("[a-zA-Z0-9_?]*".equals(configuration.getString(ALLOWED_NICKNAME_CHARACTERS.getPath()))) {
|
||||||
configuration.set(ALLOWED_NICKNAME_CHARACTERS.getPath(), "[a-zA-Z0-9_]*");
|
configuration.set(ALLOWED_NICKNAME_CHARACTERS.getPath(), "[a-zA-Z0-9_]*");
|
||||||
@ -50,8 +47,7 @@ public final class SettingsMigrationService {
|
|||||||
| migrateJoinLeaveMessages(configuration);
|
| migrateJoinLeaveMessages(configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
public boolean containsAllSettings(FileConfiguration configuration, PropertyMap propertyMap) {
|
||||||
static boolean containsAllSettings(FileConfiguration configuration, PropertyMap propertyMap) {
|
|
||||||
for (Property<?> property : propertyMap.keySet()) {
|
for (Property<?> property : propertyMap.keySet()) {
|
||||||
if (!property.isPresent(configuration)) {
|
if (!property.isPresent(configuration)) {
|
||||||
return false;
|
return false;
|
||||||
@ -80,16 +76,16 @@ public final class SettingsMigrationService {
|
|||||||
* Check if {@code Email.mailText} is present and move it to the Email.html file if it doesn't exist yet.
|
* 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 configuration The file configuration to verify
|
||||||
* @param dataFolder The plugin data folder
|
* @param pluginFolder The plugin data folder
|
||||||
* @return True if a migration has been completed, false otherwise
|
* @return True if a migration has been completed, false otherwise
|
||||||
*/
|
*/
|
||||||
private static boolean performMailTextToFileMigration(FileConfiguration configuration, File dataFolder) {
|
private static boolean performMailTextToFileMigration(FileConfiguration configuration, File pluginFolder) {
|
||||||
final String oldSettingPath = "Email.mailText";
|
final String oldSettingPath = "Email.mailText";
|
||||||
if (!configuration.contains(oldSettingPath)) {
|
if (!configuration.contains(oldSettingPath)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final File emailFile = new File(dataFolder, "email.html");
|
final File emailFile = new File(pluginFolder, "email.html");
|
||||||
final String mailText = configuration.getString(oldSettingPath)
|
final String mailText = configuration.getString(oldSettingPath)
|
||||||
.replace("<playername>", "<playername />")
|
.replace("<playername>", "<playername />")
|
||||||
.replace("<servername>", "<servername />")
|
.replace("<servername>", "<servername />")
|
||||||
|
|||||||
@ -12,6 +12,6 @@ import java.lang.annotation.Target;
|
|||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
public @interface Comment {
|
public @interface Comment {
|
||||||
|
|
||||||
String[] value();
|
String[] value();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
package fr.xephi.authme.settings.domain;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum property.
|
||||||
|
*
|
||||||
|
* @param <E> The enum class
|
||||||
|
*/
|
||||||
|
class EnumProperty<E extends Enum<E>> extends Property<E> {
|
||||||
|
|
||||||
|
private Class<E> clazz;
|
||||||
|
|
||||||
|
public EnumProperty(Class<E> clazz, String path, E defaultValue) {
|
||||||
|
super(path, defaultValue);
|
||||||
|
this.clazz = clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public E getFromFile(FileConfiguration configuration) {
|
||||||
|
String textValue = configuration.getString(getPath());
|
||||||
|
if (textValue == null) {
|
||||||
|
return getDefaultValue();
|
||||||
|
}
|
||||||
|
E mappedValue = mapToEnum(textValue);
|
||||||
|
return mappedValue != null ? mappedValue : getDefaultValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPresent(FileConfiguration configuration) {
|
||||||
|
return super.isPresent(configuration) && mapToEnum(configuration.getString(getPath())) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) {
|
||||||
|
E value = getFromFile(configuration);
|
||||||
|
return singleQuoteYaml.dump(value.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
private E mapToEnum(String value) {
|
||||||
|
for (E entry : clazz.getEnumConstants()) {
|
||||||
|
if (entry.name().equalsIgnoreCase(value)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,48 +0,0 @@
|
|||||||
package fr.xephi.authme.settings.domain;
|
|
||||||
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enum property type.
|
|
||||||
*
|
|
||||||
* @param <E> The enum class
|
|
||||||
*/
|
|
||||||
class EnumPropertyType<E extends Enum<E>> extends PropertyType<E> {
|
|
||||||
|
|
||||||
private Class<E> clazz;
|
|
||||||
|
|
||||||
public EnumPropertyType(Class<E> clazz) {
|
|
||||||
this.clazz = clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public E getFromFile(Property<E> property, FileConfiguration configuration) {
|
|
||||||
String textValue = configuration.getString(property.getPath());
|
|
||||||
if (textValue == null) {
|
|
||||||
return property.getDefaultValue();
|
|
||||||
}
|
|
||||||
E mappedValue = mapToEnum(textValue);
|
|
||||||
return mappedValue != null ? mappedValue : property.getDefaultValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(Property<E> 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)) {
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -10,45 +10,27 @@ import java.util.Objects;
|
|||||||
/**
|
/**
|
||||||
* Property class, representing a <i>setting</i> that is read from the config.yml file.
|
* Property class, representing a <i>setting</i> that is read from the config.yml file.
|
||||||
*/
|
*/
|
||||||
public class Property<T> {
|
public abstract class Property<T> {
|
||||||
|
|
||||||
private final PropertyType<T> type;
|
|
||||||
private final String path;
|
private final String path;
|
||||||
private final T defaultValue;
|
private final T defaultValue;
|
||||||
|
|
||||||
private Property(PropertyType<T> type, String path, T defaultValue) {
|
protected Property(String path, T defaultValue) {
|
||||||
Objects.requireNonNull(defaultValue);
|
Objects.requireNonNull(defaultValue);
|
||||||
this.type = type;
|
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.defaultValue = defaultValue;
|
this.defaultValue = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new property. See also {@link #newProperty(PropertyType, String, Object[])} for lists and
|
* Create a new string list property.
|
||||||
* {@link #newProperty(Class, String, Enum)}.
|
|
||||||
*
|
*
|
||||||
* @param type The property type
|
|
||||||
* @param path The property's path
|
* @param path The property's path
|
||||||
* @param defaultValue The default value
|
* @param defaultValues The items in the default list
|
||||||
* @param <T> The type of the property
|
|
||||||
* @return The created property
|
|
||||||
*/
|
|
||||||
public static <T> Property<T> newProperty(PropertyType<T> 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 <U> The list type
|
|
||||||
* @return The created list property
|
* @return The created list property
|
||||||
*/
|
*/
|
||||||
@SafeVarargs
|
public static Property<List<String>> newListProperty(String path, String... defaultValues) {
|
||||||
public static <U> Property<List<U>> newProperty(PropertyType<List<U>> type, String path, U... defaultValues) {
|
// does not have the same name as not to clash with #newProperty(String, String)
|
||||||
return new Property<>(type, path, Arrays.asList(defaultValues));
|
return new StringListProperty(path, defaultValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,36 +43,28 @@ public class Property<T> {
|
|||||||
* @return The created enum property
|
* @return The created enum property
|
||||||
*/
|
*/
|
||||||
public static <E extends Enum<E>> Property<E> newProperty(Class<E> clazz, String path, E defaultValue) {
|
public static <E extends Enum<E>> Property<E> newProperty(Class<E> clazz, String path, E defaultValue) {
|
||||||
return new Property<>(new EnumPropertyType<>(clazz), path, defaultValue);
|
return new EnumProperty<>(clazz, path, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
|
||||||
// Overloaded convenience methods for specific types
|
|
||||||
// -----
|
|
||||||
public static Property<Boolean> newProperty(String path, boolean defaultValue) {
|
public static Property<Boolean> newProperty(String path, boolean defaultValue) {
|
||||||
return new Property<>(PropertyType.BOOLEAN, path, defaultValue);
|
return new BooleanProperty(path, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Property<Integer> newProperty(String path, int defaultValue) {
|
public static Property<Integer> newProperty(String path, int defaultValue) {
|
||||||
return new Property<>(PropertyType.INTEGER, path, defaultValue);
|
return new IntegerProperty(path, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Property<String> newProperty(String path, String defaultValue) {
|
public static Property<String> newProperty(String path, String defaultValue) {
|
||||||
return new Property<>(PropertyType.STRING, path, defaultValue);
|
return new StringProperty(path, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
|
||||||
// Hooks to the PropertyType methods
|
|
||||||
// -----
|
|
||||||
/**
|
/**
|
||||||
* Get the property value from the given configuration – guaranteed to never return null.
|
* Get the property value from the given configuration – guaranteed to never return null.
|
||||||
*
|
*
|
||||||
* @param configuration The configuration to read the value from
|
* @param configuration The configuration to read the value from
|
||||||
* @return The value, or default if not present
|
* @return The value, or default if not present
|
||||||
*/
|
*/
|
||||||
public T getFromFile(FileConfiguration configuration) {
|
public abstract T getFromFile(FileConfiguration configuration);
|
||||||
return type.getFromFile(this, configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether or not the given configuration file contains the property.
|
* Return whether or not the given configuration file contains the property.
|
||||||
@ -99,7 +73,7 @@ public class Property<T> {
|
|||||||
* @return True if the property is present, false otherwise
|
* @return True if the property is present, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean isPresent(FileConfiguration configuration) {
|
public boolean isPresent(FileConfiguration configuration) {
|
||||||
return type.contains(this, configuration);
|
return configuration.contains(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -111,12 +85,9 @@ public class Property<T> {
|
|||||||
* @return The generated YAML
|
* @return The generated YAML
|
||||||
*/
|
*/
|
||||||
public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) {
|
public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) {
|
||||||
return type.toYaml(getFromFile(configuration), simpleYaml, singleQuoteYaml);
|
return simpleYaml.dump(getFromFile(configuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
|
||||||
// Trivial getters
|
|
||||||
// -----
|
|
||||||
/**
|
/**
|
||||||
* Return the default value of the property.
|
* Return the default value of the property.
|
||||||
*
|
*
|
||||||
@ -140,4 +111,89 @@ public class Property<T> {
|
|||||||
return "Property '" + path + "'";
|
return "Property '" + path + "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean property.
|
||||||
|
*/
|
||||||
|
private static final class BooleanProperty extends Property<Boolean> {
|
||||||
|
|
||||||
|
public BooleanProperty(String path, Boolean defaultValue) {
|
||||||
|
super(path, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getFromFile(FileConfiguration configuration) {
|
||||||
|
return configuration.getBoolean(getPath(), getDefaultValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integer property.
|
||||||
|
*/
|
||||||
|
private static final class IntegerProperty extends Property<Integer> {
|
||||||
|
|
||||||
|
public IntegerProperty(String path, Integer defaultValue) {
|
||||||
|
super(path, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getFromFile(FileConfiguration configuration) {
|
||||||
|
return configuration.getInt(getPath(), getDefaultValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String property.
|
||||||
|
*/
|
||||||
|
private static final class StringProperty extends Property<String> {
|
||||||
|
|
||||||
|
public StringProperty(String path, String defaultValue) {
|
||||||
|
super(path, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFromFile(FileConfiguration configuration) {
|
||||||
|
return configuration.getString(getPath(), getDefaultValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) {
|
||||||
|
return singleQuoteYaml.dump(getFromFile(configuration));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String list property.
|
||||||
|
*/
|
||||||
|
private static final class StringListProperty extends Property<List<String>> {
|
||||||
|
|
||||||
|
public StringListProperty(String path, String[] defaultValues) {
|
||||||
|
super(path, Arrays.asList(defaultValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getFromFile(FileConfiguration configuration) {
|
||||||
|
if (!configuration.isList(getPath())) {
|
||||||
|
return getDefaultValue();
|
||||||
|
}
|
||||||
|
return configuration.getStringList(getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPresent(FileConfiguration configuration) {
|
||||||
|
return configuration.isList(getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toYaml(FileConfiguration configuration, Yaml simpleYaml, Yaml singleQuoteYaml) {
|
||||||
|
List<String> value = getFromFile(configuration);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,116 +0,0 @@
|
|||||||
package fr.xephi.authme.settings.domain;
|
|
||||||
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a certain property type and provides type-specific functionality.
|
|
||||||
*
|
|
||||||
* @param <T> The value of the property
|
|
||||||
* @see Property
|
|
||||||
*/
|
|
||||||
public abstract class PropertyType<T> {
|
|
||||||
|
|
||||||
public static final PropertyType<Boolean> BOOLEAN = new BooleanProperty();
|
|
||||||
public static final PropertyType<Integer> INTEGER = new IntegerProperty();
|
|
||||||
public static final PropertyType<String> STRING = new StringProperty();
|
|
||||||
public static final PropertyType<List<String>> STRING_LIST = new StringListProperty();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the property's value from the given YAML configuration.
|
|
||||||
*
|
|
||||||
* @param property The property to retrieve
|
|
||||||
* @param configuration The YAML configuration to read from
|
|
||||||
* @return The read value, or the default value if absent
|
|
||||||
*/
|
|
||||||
public abstract T getFromFile(Property<T> property, FileConfiguration configuration);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether the property is present in the given configuration.
|
|
||||||
*
|
|
||||||
* @param property The property to search for
|
|
||||||
* @param configuration The configuration to verify
|
|
||||||
* @return True if the property is present, false otherwise
|
|
||||||
*/
|
|
||||||
public boolean contains(Property<T> property, FileConfiguration configuration) {
|
|
||||||
return configuration.contains(property.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format 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
|
|
||||||
*/
|
|
||||||
public String toYaml(T value, Yaml simpleYaml, Yaml singleQuoteYaml) {
|
|
||||||
return simpleYaml.dump(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Boolean property.
|
|
||||||
*/
|
|
||||||
private static final class BooleanProperty extends PropertyType<Boolean> {
|
|
||||||
@Override
|
|
||||||
public Boolean getFromFile(Property<Boolean> property, FileConfiguration configuration) {
|
|
||||||
return configuration.getBoolean(property.getPath(), property.getDefaultValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Integer property.
|
|
||||||
*/
|
|
||||||
private static final class IntegerProperty extends PropertyType<Integer> {
|
|
||||||
@Override
|
|
||||||
public Integer getFromFile(Property<Integer> property, FileConfiguration configuration) {
|
|
||||||
return configuration.getInt(property.getPath(), property.getDefaultValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String property.
|
|
||||||
*/
|
|
||||||
private static final class StringProperty extends PropertyType<String> {
|
|
||||||
@Override
|
|
||||||
public String getFromFile(Property<String> property, FileConfiguration configuration) {
|
|
||||||
return configuration.getString(property.getPath(), property.getDefaultValue());
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public String toYaml(String value, Yaml simpleYaml, Yaml singleQuoteYaml) {
|
|
||||||
return singleQuoteYaml.dump(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String list property.
|
|
||||||
*/
|
|
||||||
private static final class StringListProperty extends PropertyType<List<String>> {
|
|
||||||
@Override
|
|
||||||
public List<String> getFromFile(Property<List<String>> property, FileConfiguration configuration) {
|
|
||||||
if (!configuration.isList(property.getPath())) {
|
|
||||||
return property.getDefaultValue();
|
|
||||||
}
|
|
||||||
return configuration.getStringList(property.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(Property<List<String>> property, FileConfiguration configuration) {
|
|
||||||
return configuration.contains(property.getPath()) && configuration.isList(property.getPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toYaml(List<String> 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -5,26 +5,24 @@ import fr.xephi.authme.settings.domain.Property;
|
|||||||
import fr.xephi.authme.settings.domain.SettingsClass;
|
import fr.xephi.authme.settings.domain.SettingsClass;
|
||||||
|
|
||||||
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
||||||
import static fr.xephi.authme.settings.domain.PropertyType.BOOLEAN;
|
|
||||||
import static fr.xephi.authme.settings.domain.PropertyType.STRING;
|
|
||||||
|
|
||||||
public class ConverterSettings implements SettingsClass {
|
public class ConverterSettings implements SettingsClass {
|
||||||
|
|
||||||
@Comment("Rakamak file name")
|
@Comment("Rakamak file name")
|
||||||
public static final Property<String> RAKAMAK_FILE_NAME =
|
public static final Property<String> RAKAMAK_FILE_NAME =
|
||||||
newProperty(STRING, "Converter.Rakamak.fileName", "users.rak");
|
newProperty("Converter.Rakamak.fileName", "users.rak");
|
||||||
|
|
||||||
@Comment("Rakamak use IP?")
|
@Comment("Rakamak use IP?")
|
||||||
public static final Property<Boolean> RAKAMAK_USE_IP =
|
public static final Property<Boolean> RAKAMAK_USE_IP =
|
||||||
newProperty(BOOLEAN, "Converter.Rakamak.useIP", false);
|
newProperty("Converter.Rakamak.useIP", false);
|
||||||
|
|
||||||
@Comment("Rakamak IP file name")
|
@Comment("Rakamak IP file name")
|
||||||
public static final Property<String> RAKAMAK_IP_FILE_NAME =
|
public static final Property<String> RAKAMAK_IP_FILE_NAME =
|
||||||
newProperty(STRING, "Converter.Rakamak.ipFileName", "UsersIp.rak");
|
newProperty("Converter.Rakamak.ipFileName", "UsersIp.rak");
|
||||||
|
|
||||||
@Comment("CrazyLogin database file name")
|
@Comment("CrazyLogin database file name")
|
||||||
public static final Property<String> CRAZYLOGIN_FILE_NAME =
|
public static final Property<String> CRAZYLOGIN_FILE_NAME =
|
||||||
newProperty(STRING, "Converter.CrazyLogin.fileName", "accounts.db");
|
newProperty("Converter.CrazyLogin.fileName", "accounts.db");
|
||||||
|
|
||||||
private ConverterSettings() {
|
private ConverterSettings() {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,29 +6,26 @@ import fr.xephi.authme.settings.domain.SettingsClass;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.settings.domain.Property.newListProperty;
|
||||||
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
||||||
import static fr.xephi.authme.settings.domain.PropertyType.BOOLEAN;
|
|
||||||
import static fr.xephi.authme.settings.domain.PropertyType.INTEGER;
|
|
||||||
import static fr.xephi.authme.settings.domain.PropertyType.STRING;
|
|
||||||
import static fr.xephi.authme.settings.domain.PropertyType.STRING_LIST;
|
|
||||||
|
|
||||||
public class EmailSettings implements SettingsClass {
|
public class EmailSettings implements SettingsClass {
|
||||||
|
|
||||||
@Comment("Email SMTP server host")
|
@Comment("Email SMTP server host")
|
||||||
public static final Property<String> SMTP_HOST =
|
public static final Property<String> SMTP_HOST =
|
||||||
newProperty(STRING, "Email.mailSMTP", "smtp.gmail.com");
|
newProperty("Email.mailSMTP", "smtp.gmail.com");
|
||||||
|
|
||||||
@Comment("Email SMTP server port")
|
@Comment("Email SMTP server port")
|
||||||
public static final Property<Integer> SMTP_PORT =
|
public static final Property<Integer> SMTP_PORT =
|
||||||
newProperty(INTEGER, "Email.mailPort", 465);
|
newProperty("Email.mailPort", 465);
|
||||||
|
|
||||||
@Comment("Email account which sends the mails")
|
@Comment("Email account which sends the mails")
|
||||||
public static final Property<String> MAIL_ACCOUNT =
|
public static final Property<String> MAIL_ACCOUNT =
|
||||||
newProperty(STRING, "Email.mailAccount", "");
|
newProperty("Email.mailAccount", "");
|
||||||
|
|
||||||
@Comment("Email account password")
|
@Comment("Email account password")
|
||||||
public static final Property<String> MAIL_PASSWORD =
|
public static final Property<String> MAIL_PASSWORD =
|
||||||
newProperty(STRING, "Email.mailPassword", "");
|
newProperty("Email.mailPassword", "");
|
||||||
|
|
||||||
@Comment("Custom sender name, replacing the mailAccount name in the email")
|
@Comment("Custom sender name, replacing the mailAccount name in the email")
|
||||||
public static final Property<String> MAIL_SENDER_NAME =
|
public static final Property<String> MAIL_SENDER_NAME =
|
||||||
@ -36,39 +33,39 @@ public class EmailSettings implements SettingsClass {
|
|||||||
|
|
||||||
@Comment("Recovery password length")
|
@Comment("Recovery password length")
|
||||||
public static final Property<Integer> RECOVERY_PASSWORD_LENGTH =
|
public static final Property<Integer> RECOVERY_PASSWORD_LENGTH =
|
||||||
newProperty(INTEGER, "Email.RecoveryPasswordLength", 8);
|
newProperty("Email.RecoveryPasswordLength", 8);
|
||||||
|
|
||||||
@Comment("Mail Subject")
|
@Comment("Mail Subject")
|
||||||
public static final Property<String> RECOVERY_MAIL_SUBJECT =
|
public static final Property<String> RECOVERY_MAIL_SUBJECT =
|
||||||
newProperty(STRING, "Email.mailSubject", "Your new AuthMe password");
|
newProperty("Email.mailSubject", "Your new AuthMe password");
|
||||||
|
|
||||||
@Comment("Like maxRegPerIP but with email")
|
@Comment("Like maxRegPerIP but with email")
|
||||||
public static final Property<Integer> MAX_REG_PER_EMAIL =
|
public static final Property<Integer> MAX_REG_PER_EMAIL =
|
||||||
newProperty(INTEGER, "Email.maxRegPerEmail", 1);
|
newProperty("Email.maxRegPerEmail", 1);
|
||||||
|
|
||||||
@Comment("Recall players to add an email?")
|
@Comment("Recall players to add an email?")
|
||||||
public static final Property<Boolean> RECALL_PLAYERS =
|
public static final Property<Boolean> RECALL_PLAYERS =
|
||||||
newProperty(BOOLEAN, "Email.recallPlayers", false);
|
newProperty("Email.recallPlayers", false);
|
||||||
|
|
||||||
@Comment("Delay in minute for the recall scheduler")
|
@Comment("Delay in minute for the recall scheduler")
|
||||||
public static final Property<Integer> DELAY_RECALL =
|
public static final Property<Integer> DELAY_RECALL =
|
||||||
newProperty(INTEGER, "Email.delayRecall", 5);
|
newProperty("Email.delayRecall", 5);
|
||||||
|
|
||||||
@Comment("Blacklist these domains for emails")
|
@Comment("Blacklist these domains for emails")
|
||||||
public static final Property<List<String>> DOMAIN_BLACKLIST =
|
public static final Property<List<String>> DOMAIN_BLACKLIST =
|
||||||
newProperty(STRING_LIST, "Email.emailBlacklisted", "10minutemail.com");
|
newListProperty("Email.emailBlacklisted", "10minutemail.com");
|
||||||
|
|
||||||
@Comment("Whitelist ONLY these domains for emails")
|
@Comment("Whitelist ONLY these domains for emails")
|
||||||
public static final Property<List<String>> DOMAIN_WHITELIST =
|
public static final Property<List<String>> DOMAIN_WHITELIST =
|
||||||
newProperty(STRING_LIST, "Email.emailWhitelisted");
|
newListProperty("Email.emailWhitelisted");
|
||||||
|
|
||||||
@Comment("Send the new password drawn in an image?")
|
@Comment("Send the new password drawn in an image?")
|
||||||
public static final Property<Boolean> PASSWORD_AS_IMAGE =
|
public static final Property<Boolean> PASSWORD_AS_IMAGE =
|
||||||
newProperty(BOOLEAN, "Email.generateImage", false);
|
newProperty("Email.generateImage", false);
|
||||||
|
|
||||||
@Comment("The OAuth2 token")
|
@Comment("The OAuth2 token")
|
||||||
public static final Property<String> OAUTH2_TOKEN =
|
public static final Property<String> OAUTH2_TOKEN =
|
||||||
newProperty(STRING, "Email.emailOauth2Token", "");
|
newProperty("Email.emailOauth2Token", "");
|
||||||
|
|
||||||
private EmailSettings() {
|
private EmailSettings() {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,11 @@ package fr.xephi.authme.settings.properties;
|
|||||||
|
|
||||||
import fr.xephi.authme.settings.domain.Comment;
|
import fr.xephi.authme.settings.domain.Comment;
|
||||||
import fr.xephi.authme.settings.domain.Property;
|
import fr.xephi.authme.settings.domain.Property;
|
||||||
import fr.xephi.authme.settings.domain.PropertyType;
|
|
||||||
import fr.xephi.authme.settings.domain.SettingsClass;
|
import fr.xephi.authme.settings.domain.SettingsClass;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.settings.domain.Property.newListProperty;
|
||||||
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
||||||
|
|
||||||
public class HooksSettings implements SettingsClass {
|
public class HooksSettings implements SettingsClass {
|
||||||
@ -48,7 +48,7 @@ public class HooksSettings implements SettingsClass {
|
|||||||
|
|
||||||
@Comment("Other MySQL columns where we need to put the username (case-sensitive)")
|
@Comment("Other MySQL columns where we need to put the username (case-sensitive)")
|
||||||
public static final Property<List<String>> MYSQL_OTHER_USERNAME_COLS =
|
public static final Property<List<String>> MYSQL_OTHER_USERNAME_COLS =
|
||||||
newProperty(PropertyType.STRING_LIST, "ExternalBoardOptions.mySQLOtherUsernameColumns");
|
newListProperty("ExternalBoardOptions.mySQLOtherUsernameColumns");
|
||||||
|
|
||||||
@Comment("How much log2 rounds needed in BCrypt (do not change if you do not know what it does)")
|
@Comment("How much log2 rounds needed in BCrypt (do not change if you do not know what it does)")
|
||||||
public static final Property<Integer> BCRYPT_LOG2_ROUND =
|
public static final Property<Integer> BCRYPT_LOG2_ROUND =
|
||||||
|
|||||||
@ -6,39 +6,37 @@ import fr.xephi.authme.settings.domain.SettingsClass;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.settings.domain.Property.newListProperty;
|
||||||
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
||||||
import static fr.xephi.authme.settings.domain.PropertyType.BOOLEAN;
|
|
||||||
import static fr.xephi.authme.settings.domain.PropertyType.INTEGER;
|
|
||||||
import static fr.xephi.authme.settings.domain.PropertyType.STRING_LIST;
|
|
||||||
|
|
||||||
|
|
||||||
public class ProtectionSettings implements SettingsClass {
|
public class ProtectionSettings implements SettingsClass {
|
||||||
|
|
||||||
@Comment("Enable some servers protection (country based login, antibot)")
|
@Comment("Enable some servers protection (country based login, antibot)")
|
||||||
public static final Property<Boolean> ENABLE_PROTECTION =
|
public static final Property<Boolean> ENABLE_PROTECTION =
|
||||||
newProperty(BOOLEAN, "Protection.enableProtection", false);
|
newProperty("Protection.enableProtection", false);
|
||||||
|
|
||||||
@Comment({"Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes",
|
@Comment({"Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes",
|
||||||
"PLEASE USE QUOTES!"})
|
"PLEASE USE QUOTES!"})
|
||||||
public static final Property<List<String>> COUNTRIES_WHITELIST =
|
public static final Property<List<String>> COUNTRIES_WHITELIST =
|
||||||
newProperty(STRING_LIST, "Protection.countries", "US", "GB", "A1");
|
newListProperty("Protection.countries", "US", "GB", "A1");
|
||||||
|
|
||||||
@Comment({"Countries not allowed to join the server and register",
|
@Comment({"Countries not allowed to join the server and register",
|
||||||
"PLEASE USE QUOTES!"})
|
"PLEASE USE QUOTES!"})
|
||||||
public static final Property<List<String>> COUNTRIES_BLACKLIST =
|
public static final Property<List<String>> COUNTRIES_BLACKLIST =
|
||||||
newProperty(STRING_LIST, "Protection.countriesBlacklist");
|
newListProperty("Protection.countriesBlacklist");
|
||||||
|
|
||||||
@Comment("Do we need to enable automatic antibot system?")
|
@Comment("Do we need to enable automatic antibot system?")
|
||||||
public static final Property<Boolean> ENABLE_ANTIBOT =
|
public static final Property<Boolean> ENABLE_ANTIBOT =
|
||||||
newProperty(BOOLEAN, "Protection.enableAntiBot", false);
|
newProperty("Protection.enableAntiBot", false);
|
||||||
|
|
||||||
@Comment("Max number of player allowed to login in 5 secs before enable AntiBot system automatically")
|
@Comment("Max number of player allowed to login in 5 secs before enable AntiBot system automatically")
|
||||||
public static final Property<Integer> ANTIBOT_SENSIBILITY =
|
public static final Property<Integer> ANTIBOT_SENSIBILITY =
|
||||||
newProperty(INTEGER, "Protection.antiBotSensibility", 5);
|
newProperty("Protection.antiBotSensibility", 5);
|
||||||
|
|
||||||
@Comment("Duration in minutes of the antibot automatic system")
|
@Comment("Duration in minutes of the antibot automatic system")
|
||||||
public static final Property<Integer> ANTIBOT_DURATION =
|
public static final Property<Integer> ANTIBOT_DURATION =
|
||||||
newProperty(INTEGER, "Protection.antiBotDuration", 10);
|
newProperty("Protection.antiBotDuration", 10);
|
||||||
|
|
||||||
private ProtectionSettings() {
|
private ProtectionSettings() {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,11 @@ package fr.xephi.authme.settings.properties;
|
|||||||
|
|
||||||
import fr.xephi.authme.settings.domain.Comment;
|
import fr.xephi.authme.settings.domain.Comment;
|
||||||
import fr.xephi.authme.settings.domain.Property;
|
import fr.xephi.authme.settings.domain.Property;
|
||||||
import fr.xephi.authme.settings.domain.PropertyType;
|
|
||||||
import fr.xephi.authme.settings.domain.SettingsClass;
|
import fr.xephi.authme.settings.domain.SettingsClass;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.settings.domain.Property.newListProperty;
|
||||||
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
||||||
|
|
||||||
public class RegistrationSettings implements SettingsClass {
|
public class RegistrationSettings implements SettingsClass {
|
||||||
@ -50,21 +50,21 @@ public class RegistrationSettings implements SettingsClass {
|
|||||||
|
|
||||||
@Comment("Force these commands after /login, without any '/', use %p to replace with player name")
|
@Comment("Force these commands after /login, without any '/', use %p to replace with player name")
|
||||||
public static final Property<List<String>> FORCE_COMMANDS =
|
public static final Property<List<String>> FORCE_COMMANDS =
|
||||||
newProperty(PropertyType.STRING_LIST, "settings.forceCommands");
|
newListProperty("settings.forceCommands");
|
||||||
|
|
||||||
@Comment("Force these commands after /login as service console, without any '/'. "
|
@Comment("Force these commands after /login as service console, without any '/'. "
|
||||||
+ "Use %p to replace with player name")
|
+ "Use %p to replace with player name")
|
||||||
public static final Property<List<String>> FORCE_COMMANDS_AS_CONSOLE =
|
public static final Property<List<String>> FORCE_COMMANDS_AS_CONSOLE =
|
||||||
newProperty(PropertyType.STRING_LIST, "settings.forceCommandsAsConsole");
|
newListProperty("settings.forceCommandsAsConsole");
|
||||||
|
|
||||||
@Comment("Force these commands after /register, without any '/', use %p to replace with player name")
|
@Comment("Force these commands after /register, without any '/', use %p to replace with player name")
|
||||||
public static final Property<List<String>> FORCE_REGISTER_COMMANDS =
|
public static final Property<List<String>> FORCE_REGISTER_COMMANDS =
|
||||||
newProperty(PropertyType.STRING_LIST, "settings.forceRegisterCommands");
|
newListProperty("settings.forceRegisterCommands");
|
||||||
|
|
||||||
@Comment("Force these commands after /register as a server console, without any '/'. "
|
@Comment("Force these commands after /register as a server console, without any '/'. "
|
||||||
+ "Use %p to replace with player name")
|
+ "Use %p to replace with player name")
|
||||||
public static final Property<List<String>> FORCE_REGISTER_COMMANDS_AS_CONSOLE =
|
public static final Property<List<String>> FORCE_REGISTER_COMMANDS_AS_CONSOLE =
|
||||||
newProperty(PropertyType.STRING_LIST, "settings.forceRegisterCommandsAsConsole");
|
newListProperty("settings.forceRegisterCommandsAsConsole");
|
||||||
|
|
||||||
@Comment({
|
@Comment({
|
||||||
"Enable to display the welcome message (welcome.txt) after a registration or a login",
|
"Enable to display the welcome message (welcome.txt) after a registration or a login",
|
||||||
|
|||||||
@ -2,11 +2,11 @@ package fr.xephi.authme.settings.properties;
|
|||||||
|
|
||||||
import fr.xephi.authme.settings.domain.Comment;
|
import fr.xephi.authme.settings.domain.Comment;
|
||||||
import fr.xephi.authme.settings.domain.Property;
|
import fr.xephi.authme.settings.domain.Property;
|
||||||
import fr.xephi.authme.settings.domain.PropertyType;
|
|
||||||
import fr.xephi.authme.settings.domain.SettingsClass;
|
import fr.xephi.authme.settings.domain.SettingsClass;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.settings.domain.Property.newListProperty;
|
||||||
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
||||||
|
|
||||||
public class RestrictionSettings implements SettingsClass {
|
public class RestrictionSettings implements SettingsClass {
|
||||||
@ -26,7 +26,7 @@ public class RestrictionSettings implements SettingsClass {
|
|||||||
|
|
||||||
@Comment("Allowed commands for unauthenticated players")
|
@Comment("Allowed commands for unauthenticated players")
|
||||||
public static final Property<List<String>> ALLOW_COMMANDS =
|
public static final Property<List<String>> ALLOW_COMMANDS =
|
||||||
newProperty(PropertyType.STRING_LIST, "settings.restrictions.allowCommands",
|
newListProperty("settings.restrictions.allowCommands",
|
||||||
"login", "register", "l", "reg", "email", "captcha");
|
"login", "register", "l", "reg", "email", "captcha");
|
||||||
|
|
||||||
@Comment("Max number of allowed registrations per IP")
|
@Comment("Max number of allowed registrations per IP")
|
||||||
@ -75,7 +75,7 @@ public class RestrictionSettings implements SettingsClass {
|
|||||||
" AllowedRestrictedUser:",
|
" AllowedRestrictedUser:",
|
||||||
" - playername;127.0.0.1"})
|
" - playername;127.0.0.1"})
|
||||||
public static final Property<List<String>> ALLOWED_RESTRICTED_USERS =
|
public static final Property<List<String>> ALLOWED_RESTRICTED_USERS =
|
||||||
newProperty(PropertyType.STRING_LIST, "settings.restrictions.AllowedRestrictedUser");
|
newListProperty("settings.restrictions.AllowedRestrictedUser");
|
||||||
|
|
||||||
@Comment("Should unregistered players be kicked immediately?")
|
@Comment("Should unregistered players be kicked immediately?")
|
||||||
public static final Property<Boolean> KICK_NON_REGISTERED =
|
public static final Property<Boolean> KICK_NON_REGISTERED =
|
||||||
@ -148,7 +148,7 @@ public class RestrictionSettings implements SettingsClass {
|
|||||||
"WorldNames where we need to force the spawn location for ForceSpawnLocOnJoinEnabled",
|
"WorldNames where we need to force the spawn location for ForceSpawnLocOnJoinEnabled",
|
||||||
"Case-sensitive!"})
|
"Case-sensitive!"})
|
||||||
public static final Property<List<String>> FORCE_SPAWN_ON_WORLDS =
|
public static final Property<List<String>> FORCE_SPAWN_ON_WORLDS =
|
||||||
newProperty(PropertyType.STRING_LIST, "settings.restrictions.ForceSpawnOnTheseWorlds",
|
newListProperty("settings.restrictions.ForceSpawnOnTheseWorlds",
|
||||||
"world", "world_nether", "world_the_end");
|
"world", "world_nether", "world_the_end");
|
||||||
|
|
||||||
@Comment("Ban ip when the ip is not the ip registered in database")
|
@Comment("Ban ip when the ip is not the ip registered in database")
|
||||||
@ -189,7 +189,7 @@ public class RestrictionSettings implements SettingsClass {
|
|||||||
"It is case-sensitive!"
|
"It is case-sensitive!"
|
||||||
})
|
})
|
||||||
public static final Property<List<String>> UNRESTRICTED_NAMES =
|
public static final Property<List<String>> UNRESTRICTED_NAMES =
|
||||||
newProperty(PropertyType.STRING_LIST, "settings.unrestrictions.UnrestrictedName");
|
newListProperty("settings.unrestrictions.UnrestrictedName");
|
||||||
|
|
||||||
|
|
||||||
private RestrictionSettings() {
|
private RestrictionSettings() {
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import fr.xephi.authme.settings.domain.SettingsClass;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.settings.domain.Property.newListProperty;
|
||||||
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
||||||
import static fr.xephi.authme.settings.domain.PropertyType.STRING_LIST;
|
|
||||||
|
|
||||||
public class SecuritySettings implements SettingsClass {
|
public class SecuritySettings implements SettingsClass {
|
||||||
|
|
||||||
@ -98,8 +98,7 @@ public class SecuritySettings implements SettingsClass {
|
|||||||
"- '123456'",
|
"- '123456'",
|
||||||
"- 'password'"})
|
"- 'password'"})
|
||||||
public static final Property<List<String>> UNSAFE_PASSWORDS =
|
public static final Property<List<String>> UNSAFE_PASSWORDS =
|
||||||
newProperty(STRING_LIST, "settings.security.unsafePasswords",
|
newListProperty("settings.security.unsafePasswords", "123456", "password", "qwerty", "12345", "54321");
|
||||||
"123456", "password", "qwerty", "12345", "54321");
|
|
||||||
|
|
||||||
private SecuritySettings() {
|
private SecuritySettings() {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package fr.xephi.authme.settings.propertymap;
|
package fr.xephi.authme.settings.propertymap;
|
||||||
|
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -37,14 +39,13 @@ final class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a node to the root, creating any intermediary children that don't exist.
|
* Add a child node, creating any intermediary children that don't exist.
|
||||||
*
|
*
|
||||||
* @param root The root to add the path to
|
|
||||||
* @param fullPath The entire path of the node to add, separate by periods
|
* @param fullPath The entire path of the node to add, separate by periods
|
||||||
*/
|
*/
|
||||||
public static void addNode(Node root, String fullPath) {
|
public void addNode(String fullPath) {
|
||||||
String[] pathParts = fullPath.split("\\.");
|
String[] pathParts = fullPath.split("\\.");
|
||||||
Node parent = root;
|
Node parent = this;
|
||||||
for (String part : pathParts) {
|
for (String part : pathParts) {
|
||||||
Node child = parent.getChild(part);
|
Node child = parent.getChild(part);
|
||||||
if (child == null) {
|
if (child == null) {
|
||||||
@ -59,17 +60,16 @@ final class Node {
|
|||||||
* Compare two nodes by this class' sorting behavior (insertion order).
|
* Compare two nodes by this class' sorting behavior (insertion order).
|
||||||
* Note that this method assumes that both supplied paths exist in the tree.
|
* Note that this method assumes that both supplied paths exist in the tree.
|
||||||
*
|
*
|
||||||
* @param root The root of the tree
|
|
||||||
* @param fullPath1 The full path to the first node
|
* @param fullPath1 The full path to the first node
|
||||||
* @param fullPath2 The full path to the second node
|
* @param fullPath2 The full path to the second node
|
||||||
* @return The comparison result, in the same format as {@link Comparable#compareTo}
|
* @return The comparison result, in the same format as {@link Comparable#compareTo}
|
||||||
*/
|
*/
|
||||||
public static int compare(Node root, String fullPath1, String fullPath2) {
|
public int compare(String fullPath1, String fullPath2) {
|
||||||
String[] path1 = fullPath1.split("\\.");
|
String[] path1 = fullPath1.split("\\.");
|
||||||
String[] path2 = fullPath2.split("\\.");
|
String[] path2 = fullPath2.split("\\.");
|
||||||
|
|
||||||
int commonCount = 0;
|
int commonCount = 0;
|
||||||
Node commonNode = root;
|
Node commonNode = this;
|
||||||
while (commonCount < path1.length && commonCount < path2.length
|
while (commonCount < path1.length && commonCount < path2.length
|
||||||
&& path1[commonCount].equals(path2[commonCount]) && commonNode != null) {
|
&& path1[commonCount].equals(path2[commonCount]) && commonNode != null) {
|
||||||
commonNode = commonNode.getChild(path1[commonCount]);
|
commonNode = commonNode.getChild(path1[commonCount]);
|
||||||
@ -77,7 +77,7 @@ final class Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (commonNode == null) {
|
if (commonNode == null) {
|
||||||
System.err.println("Could not find common node for '" + fullPath1 + "' at index " + commonCount);
|
ConsoleLogger.showError("Could not find common node for '" + fullPath1 + "' at index " + commonCount);
|
||||||
return fullPath1.compareTo(fullPath2); // fallback
|
return fullPath1.compareTo(fullPath2); // fallback
|
||||||
} else if (commonCount >= path1.length || commonCount >= path2.length) {
|
} else if (commonCount >= path1.length || commonCount >= path2.length) {
|
||||||
return Integer.compare(path1.length, path2.length);
|
return Integer.compare(path1.length, path2.length);
|
||||||
|
|||||||
@ -23,12 +23,12 @@ final class PropertyMapComparator implements Comparator<Property> {
|
|||||||
* @param property The property that is being added
|
* @param property The property that is being added
|
||||||
*/
|
*/
|
||||||
public void add(Property property) {
|
public void add(Property property) {
|
||||||
Node.addNode(parent, property.getPath());
|
parent.addNode(property.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(Property p1, Property p2) {
|
public int compare(Property p1, Property p2) {
|
||||||
return Node.compare(parent, p1.getPath(), p2.getPath());
|
return parent.compare(p1.getPath(), p2.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,75 @@
|
|||||||
|
package fr.xephi.authme.output;
|
||||||
|
|
||||||
|
import fr.xephi.authme.TestHelper;
|
||||||
|
import fr.xephi.authme.util.StringUtils;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that all YML message files can be loaded.
|
||||||
|
*/
|
||||||
|
public class MessagesFileYamlCheckerTest {
|
||||||
|
|
||||||
|
/** Path in the resources folder where the message files are located. */
|
||||||
|
private static final String MESSAGES_FOLDER = "/messages/";
|
||||||
|
/** Pattern of the message file names. */
|
||||||
|
private static final Pattern MESSAGE_FILE_PATTERN = Pattern.compile("messages_\\w+\\.yml");
|
||||||
|
/** Message key that is present in all files. Used to make sure that text is returned. */
|
||||||
|
private static final MessageKey MESSAGE_KEY = MessageKey.LOGIN_MESSAGE;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldAllBeValidYaml() {
|
||||||
|
// given
|
||||||
|
List<File> messageFiles = getMessageFiles();
|
||||||
|
|
||||||
|
// when
|
||||||
|
List<String> errors = new ArrayList<>();
|
||||||
|
for (File file : messageFiles) {
|
||||||
|
String error = null;
|
||||||
|
try {
|
||||||
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(file);
|
||||||
|
if (StringUtils.isEmpty(configuration.getString(MESSAGE_KEY.getKey()))) {
|
||||||
|
error = "Message for '" + MESSAGE_KEY + "' is empty";
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
error = "Could not load file: " + StringUtils.formatException(e);
|
||||||
|
}
|
||||||
|
if (!StringUtils.isEmpty(error)) {
|
||||||
|
errors.add(file.getName() + ": " + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// then
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
fail("Errors during verification of message files:\n-" + StringUtils.join("\n-", errors));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<File> getMessageFiles() {
|
||||||
|
File folder = TestHelper.getJarFile(MESSAGES_FOLDER);
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
if (files == null) {
|
||||||
|
throw new IllegalStateException("Could not read folder '" + folder.getName() + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<File> messageFiles = new ArrayList<>();
|
||||||
|
for (File file : files) {
|
||||||
|
if (MESSAGE_FILE_PATTERN.matcher(file.getName()).matches()) {
|
||||||
|
messageFiles.add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (messageFiles.isEmpty()) {
|
||||||
|
throw new IllegalStateException("Error getting message files: list of files is empty");
|
||||||
|
}
|
||||||
|
return messageFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -35,10 +35,10 @@ public class ConfigFileConsistencyTest {
|
|||||||
// given
|
// given
|
||||||
File configFile = TestHelper.getJarFile(CONFIG_FILE);
|
File configFile = TestHelper.getJarFile(CONFIG_FILE);
|
||||||
FileConfiguration configuration = YamlConfiguration.loadConfiguration(configFile);
|
FileConfiguration configuration = YamlConfiguration.loadConfiguration(configFile);
|
||||||
|
SettingsMigrationService migration = new SettingsMigrationService();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
boolean result = SettingsMigrationService.containsAllSettings(
|
boolean result = migration.containsAllSettings(configuration, SettingsFieldRetriever.getAllPropertyFields());
|
||||||
configuration, SettingsFieldRetriever.getAllPropertyFields());
|
|
||||||
|
|
||||||
// then
|
// then
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
|||||||
@ -1,27 +1,31 @@
|
|||||||
package fr.xephi.authme.settings;
|
package fr.xephi.authme.settings;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import fr.xephi.authme.ReflectionTestUtils;
|
import com.google.common.io.Files;
|
||||||
|
import fr.xephi.authme.ConsoleLoggerTestInitializer;
|
||||||
|
import fr.xephi.authme.TestHelper;
|
||||||
import fr.xephi.authme.settings.domain.Property;
|
import fr.xephi.authme.settings.domain.Property;
|
||||||
import fr.xephi.authme.settings.properties.TestConfiguration;
|
import fr.xephi.authme.settings.properties.TestConfiguration;
|
||||||
import fr.xephi.authme.settings.properties.TestEnum;
|
import fr.xephi.authme.settings.properties.TestEnum;
|
||||||
import fr.xephi.authme.settings.propertymap.PropertyMap;
|
import fr.xephi.authme.settings.propertymap.PropertyMap;
|
||||||
import fr.xephi.authme.util.WrapperMock;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.TemporaryFolder;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static fr.xephi.authme.TestHelper.getJarFile;
|
import static fr.xephi.authme.settings.TestSettingsMigrationServices.checkAllPropertiesPresent;
|
||||||
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.junit.Assume.assumeThat;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration test for {@link NewSetting}.
|
* Integration test for {@link NewSetting}.
|
||||||
@ -35,16 +39,33 @@ public class NewSettingIntegrationTest {
|
|||||||
/** File name for testing difficult values. */
|
/** File name for testing difficult values. */
|
||||||
private static final String DIFFICULT_FILE = "/config-difficult-values.yml";
|
private static final String DIFFICULT_FILE = "/config-difficult-values.yml";
|
||||||
|
|
||||||
private static PropertyMap propertyMap = generatePropertyMap();
|
private static PropertyMap propertyMap = TestConfiguration.generatePropertyMap();
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||||
|
|
||||||
|
private File testPluginFolder;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpLogger() {
|
||||||
|
ConsoleLoggerTestInitializer.setupLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUpTestPluginFolder() throws IOException {
|
||||||
|
testPluginFolder = temporaryFolder.newFolder();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldLoadAndReadAllProperties() {
|
public void shouldLoadAndReadAllProperties() throws IOException {
|
||||||
// given
|
// given
|
||||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(getJarFile(COMPLETE_FILE));
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(copyFileFromResources(COMPLETE_FILE));
|
||||||
File file = new File("unused");
|
// Pass another, non-existent file to check if the settings had to be rewritten
|
||||||
|
File newFile = temporaryFolder.newFile();
|
||||||
|
|
||||||
// when / then
|
// when / then
|
||||||
NewSetting settings = new NewSetting(configuration, file, propertyMap);
|
NewSetting settings = new NewSetting(configuration, newFile, testPluginFolder, propertyMap,
|
||||||
|
checkAllPropertiesPresent());
|
||||||
Map<Property<?>, Object> expectedValues = ImmutableMap.<Property<?>, Object>builder()
|
Map<Property<?>, Object> expectedValues = ImmutableMap.<Property<?>, Object>builder()
|
||||||
.put(TestConfiguration.DURATION_IN_SECONDS, 22)
|
.put(TestConfiguration.DURATION_IN_SECONDS, 22)
|
||||||
.put(TestConfiguration.SYSTEM_NAME, "Custom sys name")
|
.put(TestConfiguration.SYSTEM_NAME, "Custom sys name")
|
||||||
@ -61,23 +82,23 @@ public class NewSettingIntegrationTest {
|
|||||||
assertThat("Property '" + entry.getKey().getPath() + "' has expected value",
|
assertThat("Property '" + entry.getKey().getPath() + "' has expected value",
|
||||||
settings.getProperty(entry.getKey()), equalTo(entry.getValue()));
|
settings.getProperty(entry.getKey()), equalTo(entry.getValue()));
|
||||||
}
|
}
|
||||||
assertThat(file.exists(), equalTo(false));
|
assertThat(newFile.length(), equalTo(0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldWriteMissingProperties() {
|
public void shouldWriteMissingProperties() {
|
||||||
// given/when
|
// given/when
|
||||||
File file = getJarFile(INCOMPLETE_FILE);
|
File file = copyFileFromResources(INCOMPLETE_FILE);
|
||||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(file);
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(file);
|
||||||
assumeThat(configuration.contains(TestConfiguration.BORING_COLORS.getPath()), equalTo(false));
|
|
||||||
// Expectation: File is rewritten to since it does not have all configurations
|
// Expectation: File is rewritten to since it does not have all configurations
|
||||||
new NewSetting(configuration, file, propertyMap);
|
new NewSetting(configuration, file, testPluginFolder, propertyMap, checkAllPropertiesPresent());
|
||||||
|
|
||||||
// Load the settings again -> checks that what we wrote can be loaded again
|
// Load the settings again -> checks that what we wrote can be loaded again
|
||||||
configuration = YamlConfiguration.loadConfiguration(file);
|
configuration = YamlConfiguration.loadConfiguration(file);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
NewSetting settings = new NewSetting(configuration, file, propertyMap);
|
NewSetting settings = new NewSetting(configuration, file, testPluginFolder, propertyMap,
|
||||||
|
checkAllPropertiesPresent());
|
||||||
Map<Property<?>, Object> expectedValues = ImmutableMap.<Property<?>, Object>builder()
|
Map<Property<?>, Object> expectedValues = ImmutableMap.<Property<?>, Object>builder()
|
||||||
.put(TestConfiguration.DURATION_IN_SECONDS, 22)
|
.put(TestConfiguration.DURATION_IN_SECONDS, 22)
|
||||||
.put(TestConfiguration.SYSTEM_NAME, "[TestDefaultValue]")
|
.put(TestConfiguration.SYSTEM_NAME, "[TestDefaultValue]")
|
||||||
@ -100,29 +121,28 @@ public class NewSettingIntegrationTest {
|
|||||||
@Test
|
@Test
|
||||||
public void shouldProperlyExportAnyValues() {
|
public void shouldProperlyExportAnyValues() {
|
||||||
// given
|
// given
|
||||||
File file = getJarFile(DIFFICULT_FILE);
|
File file = copyFileFromResources(DIFFICULT_FILE);
|
||||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(file);
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(file);
|
||||||
assumeThat(configuration.contains(TestConfiguration.DUST_LEVEL.getPath()), equalTo(false));
|
|
||||||
|
|
||||||
// Additional string properties
|
// Additional string properties
|
||||||
List<Property<String>> additionalProperties = Arrays.asList(
|
List<Property<String>> additionalProperties = Arrays.asList(
|
||||||
newProperty("more.string1", "it's a text with some \\'apostrophes'"),
|
newProperty("more.string1", "it's a text with some \\'apostrophes'"),
|
||||||
newProperty("more.string2", "\tthis one\nhas some\nnew '' lines-test")
|
newProperty("more.string2", "\tthis one\nhas some\nnew '' lines-test")
|
||||||
);
|
);
|
||||||
PropertyMap propertyMap = generatePropertyMap();
|
|
||||||
for (Property<?> property : additionalProperties) {
|
for (Property<?> property : additionalProperties) {
|
||||||
propertyMap.put(property, new String[0]);
|
propertyMap.put(property, new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
new NewSetting(configuration, file, propertyMap);
|
new NewSetting(configuration, file, testPluginFolder, propertyMap, checkAllPropertiesPresent());
|
||||||
// reload the file as settings should hav been rewritten
|
// reload the file as settings should have been rewritten
|
||||||
configuration = YamlConfiguration.loadConfiguration(file);
|
configuration = YamlConfiguration.loadConfiguration(file);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
// assert that we won't rewrite the settings again! One rewrite should produce a valid, complete configuration
|
// 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");
|
File unusedFile = new File("config-difficult-values.unused.yml");
|
||||||
NewSetting settings = new NewSetting(configuration, unusedFile, propertyMap);
|
NewSetting settings = new NewSetting(configuration, unusedFile, testPluginFolder, propertyMap,
|
||||||
|
checkAllPropertiesPresent());
|
||||||
assertThat(unusedFile.exists(), equalTo(false));
|
assertThat(unusedFile.exists(), equalTo(false));
|
||||||
assertThat(configuration.contains(TestConfiguration.DUST_LEVEL.getPath()), equalTo(true));
|
assertThat(configuration.contains(TestConfiguration.DUST_LEVEL.getPath()), equalTo(true));
|
||||||
|
|
||||||
@ -147,23 +167,32 @@ public class NewSettingIntegrationTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Test
|
||||||
* Generate a property map with all properties in {@link TestConfiguration}.
|
public void shouldReloadSettings() throws IOException {
|
||||||
*
|
// given
|
||||||
* @return The generated property map
|
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(temporaryFolder.newFile());
|
||||||
*/
|
File fullConfigFile = copyFileFromResources(COMPLETE_FILE);
|
||||||
private static PropertyMap generatePropertyMap() {
|
NewSetting settings = new NewSetting(configuration, fullConfigFile, testPluginFolder, propertyMap,
|
||||||
WrapperMock.createInstance();
|
TestSettingsMigrationServices.alwaysFulfilled());
|
||||||
PropertyMap propertyMap = new PropertyMap();
|
|
||||||
for (Field field : TestConfiguration.class.getDeclaredFields()) {
|
// when
|
||||||
Object fieldValue = ReflectionTestUtils.getFieldValue(TestConfiguration.class, null, field.getName());
|
assertThat(settings.getProperty(TestConfiguration.RATIO_ORDER),
|
||||||
if (fieldValue instanceof Property<?>) {
|
equalTo(TestConfiguration.RATIO_ORDER.getDefaultValue()));
|
||||||
Property<?> property = (Property<?>) fieldValue;
|
settings.reload();
|
||||||
String[] comments = new String[]{"Comment for '" + property.getPath() + "'"};
|
|
||||||
propertyMap.put(property, comments);
|
// then
|
||||||
}
|
assertThat(settings.getProperty(TestConfiguration.RATIO_ORDER), equalTo(TestEnum.FIRST));
|
||||||
|
}
|
||||||
|
|
||||||
|
private File copyFileFromResources(String path) {
|
||||||
|
try {
|
||||||
|
File source = TestHelper.getJarFile(path);
|
||||||
|
File destination = temporaryFolder.newFile();
|
||||||
|
Files.copy(source, destination);
|
||||||
|
return destination;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException("Could not copy test file", e);
|
||||||
}
|
}
|
||||||
return propertyMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,30 @@
|
|||||||
package fr.xephi.authme.settings;
|
package fr.xephi.authme.settings;
|
||||||
|
|
||||||
|
import fr.xephi.authme.ConsoleLoggerTestInitializer;
|
||||||
import fr.xephi.authme.settings.domain.Property;
|
import fr.xephi.authme.settings.domain.Property;
|
||||||
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.TestConfiguration;
|
import fr.xephi.authme.settings.properties.TestConfiguration;
|
||||||
import fr.xephi.authme.settings.properties.TestEnum;
|
import fr.xephi.authme.settings.properties.TestEnum;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.TemporaryFolder;
|
||||||
import org.mockito.internal.stubbing.answers.ReturnsArgumentAt;
|
import org.mockito.internal.stubbing.answers.ReturnsArgumentAt;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.settings.properties.PluginSettings.MESSAGES_LANGUAGE;
|
||||||
|
import static fr.xephi.authme.util.StringUtils.makePath;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
import static org.mockito.BDDMockito.given;
|
import static org.mockito.BDDMockito.given;
|
||||||
@ -21,13 +34,28 @@ import static org.mockito.Matchers.anyInt;
|
|||||||
import static org.mockito.Matchers.anyString;
|
import static org.mockito.Matchers.anyString;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.Matchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@link NewSetting}.
|
* Unit tests for {@link NewSetting}.
|
||||||
*/
|
*/
|
||||||
public class NewSettingTest {
|
public class NewSettingTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||||
|
private File testPluginFolder;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpLogger() {
|
||||||
|
ConsoleLoggerTestInitializer.setupLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUpTestPluginFolder() throws IOException {
|
||||||
|
testPluginFolder = temporaryFolder.newFolder();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldLoadAllConfigs() {
|
public void shouldLoadAllConfigs() {
|
||||||
// given
|
// given
|
||||||
@ -43,7 +71,7 @@ public class NewSettingTest {
|
|||||||
setReturnValue(configuration, TestConfiguration.SYSTEM_NAME, "myTestSys");
|
setReturnValue(configuration, TestConfiguration.SYSTEM_NAME, "myTestSys");
|
||||||
|
|
||||||
// when / then
|
// when / then
|
||||||
NewSetting settings = new NewSetting(configuration, null, null);
|
NewSetting settings = new NewSetting(configuration, null, null, null, null);
|
||||||
|
|
||||||
assertThat(settings.getProperty(TestConfiguration.VERSION_NUMBER), equalTo(20));
|
assertThat(settings.getProperty(TestConfiguration.VERSION_NUMBER), equalTo(20));
|
||||||
assertThat(settings.getProperty(TestConfiguration.SKIP_BORING_FEATURES), equalTo(true));
|
assertThat(settings.getProperty(TestConfiguration.SKIP_BORING_FEATURES), equalTo(true));
|
||||||
@ -59,7 +87,7 @@ public class NewSettingTest {
|
|||||||
public void shouldReturnDefaultFile() throws IOException {
|
public void shouldReturnDefaultFile() throws IOException {
|
||||||
// given
|
// given
|
||||||
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
NewSetting settings = new NewSetting(configuration, null, null);
|
NewSetting settings = new NewSetting(configuration, null, null, null, null);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
String defaultFile = settings.getDefaultMessagesFile();
|
String defaultFile = settings.getDefaultMessagesFile();
|
||||||
@ -71,6 +99,99 @@ public class NewSettingTest {
|
|||||||
assertThat(stream.read(), not(equalTo(0)));
|
assertThat(stream.read(), not(equalTo(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldSetProperty() {
|
||||||
|
// given
|
||||||
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
|
NewSetting settings = new NewSetting(configuration, null, null, null, null);
|
||||||
|
|
||||||
|
// when
|
||||||
|
settings.setProperty(TestConfiguration.DUST_LEVEL, -4);
|
||||||
|
|
||||||
|
// then
|
||||||
|
verify(configuration).set(TestConfiguration.DUST_LEVEL.getPath(), -4);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldReturnMessagesFile() {
|
||||||
|
// given
|
||||||
|
// Use some code that is for sure not present in our JAR
|
||||||
|
String languageCode = "notinjar";
|
||||||
|
File file = new File(testPluginFolder, makePath("messages", "messages_" + languageCode + ".yml"));
|
||||||
|
createFile(file);
|
||||||
|
|
||||||
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
|
given(configuration.contains(anyString())).willReturn(true);
|
||||||
|
setReturnValue(configuration, MESSAGES_LANGUAGE, languageCode);
|
||||||
|
NewSetting settings = new NewSetting(configuration, null, testPluginFolder,
|
||||||
|
TestConfiguration.generatePropertyMap(), TestSettingsMigrationServices.alwaysFulfilled());
|
||||||
|
|
||||||
|
// when
|
||||||
|
File messagesFile = settings.getMessagesFile();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(messagesFile.getPath(), endsWith("messages_" + languageCode + ".yml"));
|
||||||
|
assertThat(messagesFile.exists(), equalTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldCopyDefaultForUnknownLanguageCode() {
|
||||||
|
// given
|
||||||
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
|
given(configuration.contains(anyString())).willReturn(true);
|
||||||
|
setReturnValue(configuration, MESSAGES_LANGUAGE, "doesntexist");
|
||||||
|
NewSetting settings = new NewSetting(configuration, null, testPluginFolder,
|
||||||
|
TestConfiguration.generatePropertyMap(), TestSettingsMigrationServices.alwaysFulfilled());
|
||||||
|
|
||||||
|
// when
|
||||||
|
File messagesFile = settings.getMessagesFile();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(messagesFile.getPath(), endsWith("messages_en.yml"));
|
||||||
|
assertThat(messagesFile.exists(), equalTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldLoadWelcomeMessage() throws IOException {
|
||||||
|
// given
|
||||||
|
String welcomeMessage = "This is my welcome message for testing\nBye!";
|
||||||
|
File welcomeFile = new File(testPluginFolder, "welcome.txt");
|
||||||
|
createFile(welcomeFile);
|
||||||
|
Files.write(welcomeFile.toPath(), welcomeMessage.getBytes());
|
||||||
|
|
||||||
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
|
setReturnValue(configuration, RegistrationSettings.USE_WELCOME_MESSAGE, true);
|
||||||
|
NewSetting settings = new NewSetting(configuration, null, testPluginFolder,
|
||||||
|
TestConfiguration.generatePropertyMap(), TestSettingsMigrationServices.alwaysFulfilled());
|
||||||
|
|
||||||
|
// when
|
||||||
|
List<String> result = settings.getWelcomeMessage();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result, hasSize(2));
|
||||||
|
assertThat(result.get(0), equalTo(welcomeMessage.split("\\n")[0]));
|
||||||
|
assertThat(result.get(1), equalTo(welcomeMessage.split("\\n")[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldLoadEmailMessage() throws IOException {
|
||||||
|
// given
|
||||||
|
String emailMessage = "Sample email message\nThat's all!";
|
||||||
|
File emailFile = new File(testPluginFolder, "email.html");
|
||||||
|
createFile(emailFile);
|
||||||
|
Files.write(emailFile.toPath(), emailMessage.getBytes());
|
||||||
|
|
||||||
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
|
NewSetting settings = new NewSetting(configuration, null, testPluginFolder,
|
||||||
|
TestConfiguration.generatePropertyMap(), TestSettingsMigrationServices.alwaysFulfilled());
|
||||||
|
|
||||||
|
// when
|
||||||
|
String result = settings.getEmailMessage();
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(result, equalTo(emailMessage));
|
||||||
|
}
|
||||||
|
|
||||||
private static <T> void setReturnValue(YamlConfiguration config, Property<T> property, T value) {
|
private static <T> void setReturnValue(YamlConfiguration config, Property<T> property, T value) {
|
||||||
if (value instanceof String) {
|
if (value instanceof String) {
|
||||||
when(config.getString(eq(property.getPath()), anyString())).thenReturn((String) value);
|
when(config.getString(eq(property.getPath()), anyString())).thenReturn((String) value);
|
||||||
@ -91,4 +212,13 @@ public class NewSettingTest {
|
|||||||
setting.getProperty(property).equals(property.getDefaultValue()), equalTo(true));
|
setting.getProperty(property).equals(property.getDefaultValue()), equalTo(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void createFile(File file) {
|
||||||
|
try {
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
file.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,9 +42,10 @@ public class SettingsMigrationServiceTest {
|
|||||||
FileConfiguration configuration = YamlConfiguration.loadConfiguration(configTestFile);
|
FileConfiguration configuration = YamlConfiguration.loadConfiguration(configTestFile);
|
||||||
PropertyMap propertyMap = SettingsFieldRetriever.getAllPropertyFields();
|
PropertyMap propertyMap = SettingsFieldRetriever.getAllPropertyFields();
|
||||||
assumeThat(testFolder.listFiles(), arrayWithSize(1));
|
assumeThat(testFolder.listFiles(), arrayWithSize(1));
|
||||||
|
SettingsMigrationService migrationService = new SettingsMigrationService();
|
||||||
|
|
||||||
// when
|
// when
|
||||||
boolean result = SettingsMigrationService.checkAndMigrate(configuration, propertyMap, testFolder);
|
boolean result = migrationService.checkAndMigrate(configuration, propertyMap, testFolder);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result, equalTo(false));
|
assertThat(result, equalTo(false));
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
package fr.xephi.authme.settings;
|
||||||
|
|
||||||
|
import fr.xephi.authme.settings.propertymap.PropertyMap;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides {@link SettingsMigrationService} implementations for testing.
|
||||||
|
*/
|
||||||
|
public final class TestSettingsMigrationServices {
|
||||||
|
|
||||||
|
private TestSettingsMigrationServices() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a settings migration service which always answers that all data is up-to-date.
|
||||||
|
*
|
||||||
|
* @return test settings migration service
|
||||||
|
*/
|
||||||
|
public static SettingsMigrationService alwaysFulfilled() {
|
||||||
|
return new SettingsMigrationService() {
|
||||||
|
@Override
|
||||||
|
public boolean checkAndMigrate(FileConfiguration configuration, PropertyMap propertyMap, File pluginFolder) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean containsAllSettings(FileConfiguration configuration, PropertyMap propertyMap) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a simple settings migration service which is fulfilled if all properties are present.
|
||||||
|
*
|
||||||
|
* @return test settings migration service
|
||||||
|
*/
|
||||||
|
public static SettingsMigrationService checkAllPropertiesPresent() {
|
||||||
|
return new SettingsMigrationService() {
|
||||||
|
// See parent javadoc: true = some migration had to be done, false = config file is up-to-date
|
||||||
|
@Override
|
||||||
|
public boolean checkAndMigrate(FileConfiguration configuration, PropertyMap propertyMap, File pluginFolder) {
|
||||||
|
return !super.containsAllSettings(configuration, propertyMap);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -9,20 +9,19 @@ import static org.mockito.BDDMockito.given;
|
|||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@link EnumPropertyType}.
|
* Test for {@link EnumProperty}.
|
||||||
*/
|
*/
|
||||||
public class EnumPropertyTypeTest {
|
public class EnumPropertyTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldReturnCorrectEnumValue() {
|
public void shouldReturnCorrectEnumValue() {
|
||||||
// given
|
// given
|
||||||
PropertyType<TestEnum> propertyType = new EnumPropertyType<>(TestEnum.class);
|
|
||||||
Property<TestEnum> property = Property.newProperty(TestEnum.class, "enum.path", TestEnum.ENTRY_C);
|
Property<TestEnum> property = Property.newProperty(TestEnum.class, "enum.path", TestEnum.ENTRY_C);
|
||||||
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
given(configuration.getString(property.getPath())).willReturn("Entry_B");
|
given(configuration.getString(property.getPath())).willReturn("Entry_B");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
TestEnum result = propertyType.getFromFile(property, configuration);
|
TestEnum result = property.getFromFile(configuration);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result, equalTo(TestEnum.ENTRY_B));
|
assertThat(result, equalTo(TestEnum.ENTRY_B));
|
||||||
@ -31,13 +30,12 @@ public class EnumPropertyTypeTest {
|
|||||||
@Test
|
@Test
|
||||||
public void shouldFallBackToDefaultForInvalidValue() {
|
public void shouldFallBackToDefaultForInvalidValue() {
|
||||||
// given
|
// given
|
||||||
PropertyType<TestEnum> propertyType = new EnumPropertyType<>(TestEnum.class);
|
|
||||||
Property<TestEnum> property = Property.newProperty(TestEnum.class, "enum.path", TestEnum.ENTRY_C);
|
Property<TestEnum> property = Property.newProperty(TestEnum.class, "enum.path", TestEnum.ENTRY_C);
|
||||||
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
given(configuration.getString(property.getPath())).willReturn("Bogus");
|
given(configuration.getString(property.getPath())).willReturn("Bogus");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
TestEnum result = propertyType.getFromFile(property, configuration);
|
TestEnum result = property.getFromFile(configuration);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result, equalTo(TestEnum.ENTRY_C));
|
assertThat(result, equalTo(TestEnum.ENTRY_C));
|
||||||
@ -46,13 +44,12 @@ public class EnumPropertyTypeTest {
|
|||||||
@Test
|
@Test
|
||||||
public void shouldFallBackToDefaultForNonExistentValue() {
|
public void shouldFallBackToDefaultForNonExistentValue() {
|
||||||
// given
|
// given
|
||||||
PropertyType<TestEnum> propertyType = new EnumPropertyType<>(TestEnum.class);
|
|
||||||
Property<TestEnum> property = Property.newProperty(TestEnum.class, "enum.path", TestEnum.ENTRY_C);
|
Property<TestEnum> property = Property.newProperty(TestEnum.class, "enum.path", TestEnum.ENTRY_C);
|
||||||
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
given(configuration.getString(property.getPath())).willReturn(null);
|
given(configuration.getString(property.getPath())).willReturn(null);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
TestEnum result = propertyType.getFromFile(property, configuration);
|
TestEnum result = property.getFromFile(configuration);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result, equalTo(TestEnum.ENTRY_C));
|
assertThat(result, equalTo(TestEnum.ENTRY_C));
|
||||||
@ -61,14 +58,13 @@ public class EnumPropertyTypeTest {
|
|||||||
@Test
|
@Test
|
||||||
public void shouldReturnTrueForContainsCheck() {
|
public void shouldReturnTrueForContainsCheck() {
|
||||||
// given
|
// given
|
||||||
PropertyType<TestEnum> propertyType = new EnumPropertyType<>(TestEnum.class);
|
|
||||||
Property<TestEnum> property = Property.newProperty(TestEnum.class, "my.test.path", TestEnum.ENTRY_C);
|
Property<TestEnum> property = Property.newProperty(TestEnum.class, "my.test.path", TestEnum.ENTRY_C);
|
||||||
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
given(configuration.contains(property.getPath())).willReturn(true);
|
given(configuration.contains(property.getPath())).willReturn(true);
|
||||||
given(configuration.getString(property.getPath())).willReturn("ENTRY_B");
|
given(configuration.getString(property.getPath())).willReturn("ENTRY_B");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
boolean result = propertyType.contains(property, configuration);
|
boolean result = property.isPresent(configuration);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result, equalTo(true));
|
assertThat(result, equalTo(true));
|
||||||
@ -77,13 +73,12 @@ public class EnumPropertyTypeTest {
|
|||||||
@Test
|
@Test
|
||||||
public void shouldReturnFalseForFileWithoutConfig() {
|
public void shouldReturnFalseForFileWithoutConfig() {
|
||||||
// given
|
// given
|
||||||
PropertyType<TestEnum> propertyType = new EnumPropertyType<>(TestEnum.class);
|
|
||||||
Property<TestEnum> property = Property.newProperty(TestEnum.class, "my.test.path", TestEnum.ENTRY_C);
|
Property<TestEnum> property = Property.newProperty(TestEnum.class, "my.test.path", TestEnum.ENTRY_C);
|
||||||
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
given(configuration.contains(property.getPath())).willReturn(false);
|
given(configuration.contains(property.getPath())).willReturn(false);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
boolean result = propertyType.contains(property, configuration);
|
boolean result = property.isPresent(configuration);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result, equalTo(false));
|
assertThat(result, equalTo(false));
|
||||||
@ -92,14 +87,13 @@ public class EnumPropertyTypeTest {
|
|||||||
@Test
|
@Test
|
||||||
public void shouldReturnFalseForUnknownValue() {
|
public void shouldReturnFalseForUnknownValue() {
|
||||||
// given
|
// given
|
||||||
PropertyType<TestEnum> propertyType = new EnumPropertyType<>(TestEnum.class);
|
|
||||||
Property<TestEnum> property = Property.newProperty(TestEnum.class, "my.test.path", TestEnum.ENTRY_C);
|
Property<TestEnum> property = Property.newProperty(TestEnum.class, "my.test.path", TestEnum.ENTRY_C);
|
||||||
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
YamlConfiguration configuration = mock(YamlConfiguration.class);
|
||||||
given(configuration.contains(property.getPath())).willReturn(true);
|
given(configuration.contains(property.getPath())).willReturn(true);
|
||||||
given(configuration.getString(property.getPath())).willReturn("wrong value");
|
given(configuration.getString(property.getPath())).willReturn("wrong value");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
boolean result = propertyType.contains(property, configuration);
|
boolean result = property.isPresent(configuration);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(result, equalTo(false));
|
assertThat(result, equalTo(false));
|
||||||
@ -3,8 +3,7 @@ package fr.xephi.authme.settings.domain;
|
|||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.internal.stubbing.answers.ReturnsArgumentAt;
|
||||||
import org.mockito.stubbing.Answer;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -20,9 +19,9 @@ import static org.mockito.Mockito.mock;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@link PropertyType} and the contained subtypes.
|
* Test for {@link Property} and the contained subtypes.
|
||||||
*/
|
*/
|
||||||
public class PropertyTypeTest {
|
public class PropertyTest {
|
||||||
|
|
||||||
private static YamlConfiguration configuration;
|
private static YamlConfiguration configuration;
|
||||||
|
|
||||||
@ -31,11 +30,11 @@ public class PropertyTypeTest {
|
|||||||
configuration = mock(YamlConfiguration.class);
|
configuration = mock(YamlConfiguration.class);
|
||||||
|
|
||||||
when(configuration.getBoolean(eq("bool.path.test"), anyBoolean())).thenReturn(true);
|
when(configuration.getBoolean(eq("bool.path.test"), anyBoolean())).thenReturn(true);
|
||||||
when(configuration.getBoolean(eq("bool.path.wrong"), anyBoolean())).thenAnswer(secondParameter());
|
when(configuration.getBoolean(eq("bool.path.wrong"), anyBoolean())).thenAnswer(new ReturnsArgumentAt(1));
|
||||||
when(configuration.getInt(eq("int.path.test"), anyInt())).thenReturn(27);
|
when(configuration.getInt(eq("int.path.test"), anyInt())).thenReturn(27);
|
||||||
when(configuration.getInt(eq("int.path.wrong"), anyInt())).thenAnswer(secondParameter());
|
when(configuration.getInt(eq("int.path.wrong"), anyInt())).thenAnswer(new ReturnsArgumentAt(1));
|
||||||
when(configuration.getString(eq("str.path.test"), anyString())).thenReturn("Test value");
|
when(configuration.getString(eq("str.path.test"), anyString())).thenReturn("Test value");
|
||||||
when(configuration.getString(eq("str.path.wrong"), anyString())).thenAnswer(secondParameter());
|
when(configuration.getString(eq("str.path.wrong"), anyString())).thenAnswer(new ReturnsArgumentAt(1));
|
||||||
when(configuration.isList("list.path.test")).thenReturn(true);
|
when(configuration.isList("list.path.test")).thenReturn(true);
|
||||||
when(configuration.getStringList("list.path.test")).thenReturn(Arrays.asList("test1", "Test2", "3rd test"));
|
when(configuration.getStringList("list.path.test")).thenReturn(Arrays.asList("test1", "Test2", "3rd test"));
|
||||||
when(configuration.isList("list.path.wrong")).thenReturn(false);
|
when(configuration.isList("list.path.wrong")).thenReturn(false);
|
||||||
@ -120,7 +119,7 @@ public class PropertyTypeTest {
|
|||||||
@Test
|
@Test
|
||||||
public void shouldGetStringListValue() {
|
public void shouldGetStringListValue() {
|
||||||
// given
|
// given
|
||||||
Property<List<String>> property = Property.newProperty(PropertyType.STRING_LIST, "list.path.test", "1", "b");
|
Property<List<String>> property = Property.newListProperty("list.path.test", "1", "b");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
List<String> result = property.getFromFile(configuration);
|
List<String> result = property.getFromFile(configuration);
|
||||||
@ -133,7 +132,7 @@ public class PropertyTypeTest {
|
|||||||
public void shouldGetStringListDefault() {
|
public void shouldGetStringListDefault() {
|
||||||
// given
|
// given
|
||||||
Property<List<String>> property =
|
Property<List<String>> property =
|
||||||
Property.newProperty(PropertyType.STRING_LIST, "list.path.wrong", "default", "list", "elements");
|
Property.newListProperty("list.path.wrong", "default", "list", "elements");
|
||||||
|
|
||||||
// when
|
// when
|
||||||
List<String> result = property.getFromFile(configuration);
|
List<String> result = property.getFromFile(configuration);
|
||||||
@ -142,13 +141,4 @@ public class PropertyTypeTest {
|
|||||||
assertThat(result, contains("default", "list", "elements"));
|
assertThat(result, contains("default", "list", "elements"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> Answer<T> secondParameter() {
|
|
||||||
return new Answer<T>() {
|
|
||||||
@Override
|
|
||||||
public T answer(InvocationOnMock invocation) throws Throwable {
|
|
||||||
// Return the second parameter -> the default
|
|
||||||
return (T) invocation.getArguments()[1];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -9,6 +9,7 @@ import org.junit.Test;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -92,6 +93,17 @@ public class SettingsClassConsistencyTest {
|
|||||||
constructors, arrayWithSize(1));
|
constructors, arrayWithSize(1));
|
||||||
assertThat("Constructor of " + clazz + " is private",
|
assertThat("Constructor of " + clazz + " is private",
|
||||||
Modifier.isPrivate(constructors[0].getModifiers()), equalTo(true));
|
Modifier.isPrivate(constructors[0].getModifiers()), equalTo(true));
|
||||||
|
|
||||||
|
// Ugly hack to get coverage on the private constructors
|
||||||
|
// http://stackoverflow.com/questions/14077842/how-to-test-a-private-constructor-in-java-application
|
||||||
|
try {
|
||||||
|
Constructor<?> constructor = clazz.getDeclaredConstructor();
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
constructor.newInstance();
|
||||||
|
} catch (NoSuchMethodException | InstantiationException
|
||||||
|
| IllegalAccessException | InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,14 @@
|
|||||||
package fr.xephi.authme.settings.properties;
|
package fr.xephi.authme.settings.properties;
|
||||||
|
|
||||||
|
import fr.xephi.authme.ReflectionTestUtils;
|
||||||
import fr.xephi.authme.settings.domain.Property;
|
import fr.xephi.authme.settings.domain.Property;
|
||||||
import fr.xephi.authme.settings.domain.PropertyType;
|
|
||||||
import fr.xephi.authme.settings.domain.SettingsClass;
|
import fr.xephi.authme.settings.domain.SettingsClass;
|
||||||
|
import fr.xephi.authme.settings.propertymap.PropertyMap;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.settings.domain.Property.newListProperty;
|
||||||
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
import static fr.xephi.authme.settings.domain.Property.newProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,7 +26,7 @@ public final class TestConfiguration implements SettingsClass {
|
|||||||
newProperty(TestEnum.class, "sample.ratio.order", TestEnum.SECOND);
|
newProperty(TestEnum.class, "sample.ratio.order", TestEnum.SECOND);
|
||||||
|
|
||||||
public static final Property<List<String>> RATIO_FIELDS =
|
public static final Property<List<String>> RATIO_FIELDS =
|
||||||
newProperty(PropertyType.STRING_LIST, "sample.ratio.fields", "a", "b", "c");
|
newListProperty("sample.ratio.fields", "a", "b", "c");
|
||||||
|
|
||||||
public static final Property<Integer> VERSION_NUMBER =
|
public static final Property<Integer> VERSION_NUMBER =
|
||||||
newProperty("version", 32046);
|
newProperty("version", 32046);
|
||||||
@ -32,7 +35,7 @@ public final class TestConfiguration implements SettingsClass {
|
|||||||
newProperty("features.boring.skip", false);
|
newProperty("features.boring.skip", false);
|
||||||
|
|
||||||
public static final Property<List<String>> BORING_COLORS =
|
public static final Property<List<String>> BORING_COLORS =
|
||||||
newProperty(PropertyType.STRING_LIST, "features.boring.colors");
|
newListProperty("features.boring.colors");
|
||||||
|
|
||||||
public static final Property<Integer> DUST_LEVEL =
|
public static final Property<Integer> DUST_LEVEL =
|
||||||
newProperty("features.boring.dustLevel", -1);
|
newProperty("features.boring.dustLevel", -1);
|
||||||
@ -41,10 +44,28 @@ public final class TestConfiguration implements SettingsClass {
|
|||||||
newProperty("features.cool.enabled", false);
|
newProperty("features.cool.enabled", false);
|
||||||
|
|
||||||
public static final Property<List<String>> COOL_OPTIONS =
|
public static final Property<List<String>> COOL_OPTIONS =
|
||||||
newProperty(PropertyType.STRING_LIST, "features.cool.options", "Sparks", "Sprinkles");
|
newListProperty("features.cool.options", "Sparks", "Sprinkles");
|
||||||
|
|
||||||
|
|
||||||
private TestConfiguration() {
|
private TestConfiguration() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a property map with all properties in {@link TestConfiguration}.
|
||||||
|
*
|
||||||
|
* @return The generated property map
|
||||||
|
*/
|
||||||
|
public static PropertyMap generatePropertyMap() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user